From 17fc98b55f5c0e3620b60e796526a05d71655553 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 08:46:14 -0300 Subject: [PATCH 01/29] build: replace luarocks with lux --- invokation-scm-0.rockspec | 44 ----- lux.lock | 381 ++++++++++++++++++++++++++++++++++++++ lux.toml | 31 ++++ 3 files changed, 412 insertions(+), 44 deletions(-) delete mode 100644 invokation-scm-0.rockspec create mode 100644 lux.lock create mode 100644 lux.toml diff --git a/invokation-scm-0.rockspec b/invokation-scm-0.rockspec deleted file mode 100644 index bca99d8..0000000 --- a/invokation-scm-0.rockspec +++ /dev/null @@ -1,44 +0,0 @@ -rockspec_format = "3.0" -package = "invokation" -version = "scm-0" - -source = { - url = "git+https://github.com/13k/invokation", - branch = "main", -} - -description = { - summary = "Invokation School of Arcane Arts", - homepage = "https://github.com/13k/invokation", - issues_url = "https://github.com/13k/invokation/issues", - maintainer = "Kiyoshi '13k' Murata ", - labels = { "dota2", "dota2-addon", "dota2-custom-game", "invoker", "invoker-trainer", "trainer" }, - license = "MIT", -} - -supported_platforms = { - "linux", - "macosx", - "windows", -} - -dependencies = { - "lua == 5.1", -} - -test_dependencies = { - "bit32 ~> 5.3", - "busted", - "compat53 ~> 0.7", - "luacov", - "moses ~> 2.1", - "penlight ~> 1.13.1", -} - -test = { - type = "busted", -} - -build = { - type = "none", -} diff --git a/lux.lock b/lux.lock new file mode 100644 index 0000000..6d6572a --- /dev/null +++ b/lux.lock @@ -0,0 +1,381 @@ +{ + "version": "1.0.0", + "test_dependencies": { + "rocks": { + "01a3c364614bddff7370223a5a9c4580f8e62d144384148444c518ec5367a59b": { + "name": "mediator_lua", + "version": "1.1.2-0", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=1.1.1", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "url", + "url": "https://github.com/Olivine-Labs/mediator_lua/archive/v1.1.2-0.tar.gz" + }, + "hashes": { + "rockspec": "sha256-dR3r7+CqAPqTwK5jcZIgVSiemUiwIx0UMMIUEY/bPzs=", + "source": "sha256-+vWFn9IIG+Tp5PuIc6LcZffv8/2T1t0U2mX44SP8/5s=" + } + }, + "092886a00e3c7cb9cb944528116da6ce7d5e4a25b9d198735ac1b1307f77dca5": { + "name": "bit32", + "version": "5.3.5-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=5.3.0, <5.4.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "url", + "url": "https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.zip" + }, + "hashes": { + "rockspec": "sha256-7Zt9FHMZfzU/j6nbXRbyrQYMrGYOnur+r8U2/htYhWw=", + "source": "sha256-q53sd82FUQL+xw5rILdegS2xqZ4/KAMMWzTcD+uIyD0=" + } + }, + "117a52658298bf0e7dc607718e5e39ef93468c41c45dcf8650d7986d93e19341": { + "name": "luacov", + "version": "0.16.0-1", + "pinned": false, + "opt": false, + "dependencies": [ + "e496d4ec14c0feec0b3eac3f622f59eb3777d6e63b24469fdb464841e6ab4e63" + ], + "constraint": ">=0.16.0, <0.17.0", + "binaries": [ + "luacov", + "luacov" + ], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/luacov.git", + "ref": "v0.16.0" + }, + "hashes": { + "rockspec": "sha256-fbdS+kCvyMlE1qUZTDm+sGwroa1NCR0YFSR00a4pwPo=", + "source": "sha256-GoJqiFyXH4chQ/k/qBPttnh/V4vUSfR2Lg8rt3CPKoY=" + } + }, + "287e827f4a088d41bba04af5f61a13614346c16fe8150eb7c4246e67d6fd163e": { + "name": "lua-term", + "version": "0.8-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=0.1", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "url", + "url": "https://github.com/hoelzro/lua-term/archive/0.08.tar.gz" + }, + "hashes": { + "rockspec": "sha256-QB/befI0oJBIBdaM+a+zuQT8dTk0f+ZDLQxq1IekSJw=", + "source": "sha256-j/lPOQ6p2YxzRpk3PKOwzlANZRsqscuNfSM2/Ft5ze0=" + } + }, + "316ac0b30e04e86a253d64886f3b110bd0508267474e6b58a3b973bd6857dbf4": { + "name": "penlight", + "version": "1.14.0-3", + "pinned": false, + "opt": false, + "dependencies": [ + "832fd9862ce671c0c9777855d4c8b19f9ad9c2679fb5466c3a183785a51b76b0" + ], + "constraint": ">=1.3.2", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/penlight.git", + "ref": "1.14.0" + }, + "hashes": { + "rockspec": "sha256-8ckXDAqsbgL9zOIH3b4HOxasdAXGzBnr+bR6nkAHrOE=", + "source": "sha256-4zAt0GgQEkg9toaUaDn3ST3RvjLUDsuOzrKi9lhq0fQ=" + } + }, + "455cd98d50c6191a9685cffcda4ce783efbb957934625e134c39f43bd5df6818": { + "name": "luassert", + "version": "1.9.0-1", + "pinned": false, + "opt": false, + "dependencies": [ + "4e9592a499c9ced4f8ce366db9db7d9c0dd1424ea8d4c8c16c1550ea3a61a696" + ], + "constraint": ">=1.9.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/luassert.git", + "ref": "v1.9.0" + }, + "hashes": { + "rockspec": "sha256-rTPvF/GK/jMnH/q4wbwTCGBFELWh+JcvHeOCFAbIf64=", + "source": "sha256-jjdB95Vr5iVsh5T7E84WwZMW6/5H2k2R/ny2VBs2l3I=" + } + }, + "47b12edcdc032232157ace97bddf34bddd17f6f458095885e62bbd602ad9e9ec": { + "name": "luasystem", + "version": "0.6.3-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=0.2.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/luasystem.git", + "ref": "v0.6.3" + }, + "hashes": { + "rockspec": "sha256-TAprv90NktNCgtoH3wHuRZS+FHvUCNZ2XcDvu23OFX8=", + "source": "sha256-8d2835/EcyDJX9yTn6MTfaZryjY1wkSP+IIIKGPDXMk=" + } + }, + "4e9592a499c9ced4f8ce366db9db7d9c0dd1424ea8d4c8c16c1550ea3a61a696": { + "name": "say", + "version": "1.4.1-3", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=1.4.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/say.git", + "ref": "v1.4.1" + }, + "hashes": { + "rockspec": "sha256-WFKt1iWeyjO9A8SG0KUX8tkS9JvMqoVM8CKBUguuK0Y=", + "source": "sha256-IjNkK1leVtYgbEjUqguVMjbdW+0BHAOCE0pazrVuF50=" + } + }, + "672112d42de52914cd6daaac8a86cf906f80360bd81d6ad0a1df51224d74e9d4": { + "name": "busted-htest", + "version": "1.0.0-2", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=1.0.0, <1.1.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/hishamhm/busted-htest", + "ref": "1.0.0" + }, + "hashes": { + "rockspec": "sha256-tLFqua5M2bVIs9PYW7DX5QdZOMkLQUDu88S7LOC6ooE=", + "source": "sha256-tGAQUSeDt+OV/TBAJo/JFdyeBRRZaIQEJG+SKcCaQhs=" + } + }, + "6ce29c2c535c40246c386c056f24689344cddb56ec397473931431e6b67694d2": { + "name": "say", + "version": "1.4.1-3", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=1.4", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/say.git", + "ref": "v1.4.1" + }, + "hashes": { + "rockspec": "sha256-WFKt1iWeyjO9A8SG0KUX8tkS9JvMqoVM8CKBUguuK0Y=", + "source": "sha256-IjNkK1leVtYgbEjUqguVMjbdW+0BHAOCE0pazrVuF50=" + } + }, + "832fd9862ce671c0c9777855d4c8b19f9ad9c2679fb5466c3a183785a51b76b0": { + "name": "luafilesystem", + "version": "1.8.0-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": null, + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/keplerproject/luafilesystem", + "ref": "v1_8_0" + }, + "hashes": { + "rockspec": "sha256-ylWfvz35v68L9Sa92bQHDfFylaS7PEmZr62cBfRU06I=", + "source": "sha256-pEA+Z1pkykWLTT6NHQ5lo8roOh2P0fiHtnK+byTkF5o=" + } + }, + "8a29d183b38f69620275ab4765d677ada24ff5f96f48d2018d0ee7bcd8ad057e": { + "name": "busted", + "version": "2.2.0-1", + "pinned": false, + "opt": false, + "dependencies": [ + "a6c5176043cb3de56336b7de119443dbb3d9e024be1d50e06289ad4b4959a2da", + "47b12edcdc032232157ace97bddf34bddd17f6f458095885e62bbd602ad9e9ec", + "e4f17b9e67313bbd5e90f425672fc8998dd0bfa43335f7c57ed2de7a799e07a6", + "6ce29c2c535c40246c386c056f24689344cddb56ec397473931431e6b67694d2", + "455cd98d50c6191a9685cffcda4ce783efbb957934625e134c39f43bd5df6818", + "287e827f4a088d41bba04af5f61a13614346c16fe8150eb7c4246e67d6fd163e", + "316ac0b30e04e86a253d64886f3b110bd0508267474e6b58a3b973bd6857dbf4", + "01a3c364614bddff7370223a5a9c4580f8e62d144384148444c518ec5367a59b" + ], + "constraint": ">=2.2.0, <2.3.0", + "binaries": [ + "busted", + "busted" + ], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/busted.git", + "ref": "v2.2.0" + }, + "hashes": { + "rockspec": "sha256-zj6KqOotJVv+BaqYLin0yifoNTVWvg3oeByQyiiZn0A=", + "source": "sha256-5LxPqmoUwR3XaIToKUgap0L/sNS9uOV080MIenyLnl8=" + } + }, + "9a3c8a33388fd17cf44291697753b48efba841849e4a92dc37c4f7a4c6877c86": { + "name": "compat53", + "version": "0.14.4-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=0.14.0, <0.15.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "url", + "url": "https://github.com/lunarmodules/lua-compat-5.3/archive/v0.14.4.zip" + }, + "hashes": { + "rockspec": "sha256-gLSSnITq6MALS8pJp9BJ0n1+ic867+s3zX3F88xyUAU=", + "source": "sha256-hOUB5vXIHF7g/5AF355DcEOk7bKQaRjbG7YrwYqFddg=" + } + }, + "a6c5176043cb3de56336b7de119443dbb3d9e024be1d50e06289ad4b4959a2da": { + "name": "lua_cliargs", + "version": "3.0.2-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": "==3.0", + "binaries": [ + "watch-tests.sh", + "release", + "lint", + "docs", + "coverage" + ], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/lua_cliargs.git", + "ref": "v3.0.2" + }, + "hashes": { + "rockspec": "sha256-7qJVHj/KebRkOmK8pxNspNeuXIksdExjKrNhdWOy474=", + "source": "sha256-wL3qBQ8Lu3q8DK2Kaeo1dgzIHd8evaxFYJg47CcQiSg=" + } + }, + "c82b26bea8099fcea79b4e243145c4cf2597abdde010248e02fcd273e490e1bb": { + "name": "penlight", + "version": "1.14.0-3", + "pinned": false, + "opt": false, + "dependencies": [ + "832fd9862ce671c0c9777855d4c8b19f9ad9c2679fb5466c3a183785a51b76b0" + ], + "constraint": ">=1.14.0, <1.15.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/lunarmodules/penlight.git", + "ref": "1.14.0" + }, + "hashes": { + "rockspec": "sha256-8ckXDAqsbgL9zOIH3b4HOxasdAXGzBnr+bR6nkAHrOE=", + "source": "sha256-4zAt0GgQEkg9toaUaDn3ST3RvjLUDsuOzrKi9lhq0fQ=" + } + }, + "d792a2d7b67521e3af5c323f99f9c5b20625b649826613bdf93854482c22dd1b": { + "name": "moses", + "version": "2.1.0-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=2.1.0, <2.2.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "url", + "url": "https://github.com/Yonaba/Moses/archive/Moses-2.1.0-1.tar.gz" + }, + "hashes": { + "rockspec": "sha256-lWuiX5BRMhdjl6whl41GlJ8mkdR/T85t/3/bhBE2uyQ=", + "source": "sha256-koGDl+3kjV0EkeeTsmc5zuVoljT7s47Et8w8JoPfv1g=" + } + }, + "e496d4ec14c0feec0b3eac3f622f59eb3777d6e63b24469fdb464841e6ab4e63": { + "name": "datafile", + "version": "0.11-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": null, + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "git", + "url": "https://github.com/hishamhm/datafile.git", + "ref": "v0.11" + }, + "hashes": { + "rockspec": "sha256-2DDuPfJZustlH90MsItOvpTv2+weKIyFE2SwPxX2ICY=", + "source": "sha256-aHdxFJ2IB9v9UMK7vqk7tUA0rLmfvRd0nzhc9JO8AlQ=" + } + }, + "e4f17b9e67313bbd5e90f425672fc8998dd0bfa43335f7c57ed2de7a799e07a6": { + "name": "dkjson", + "version": "2.8-1", + "pinned": false, + "opt": false, + "dependencies": [], + "constraint": ">=2.1.0", + "binaries": [], + "source": "luarocks_rockspec+https://luarocks.org/", + "source_url": { + "type": "url", + "url": "http://dkolf.de/dkjson-lua/dkjson-2.8.tar.gz" + }, + "hashes": { + "rockspec": "sha256-arasJeX7yQ2Rg70RyepiGNvLdiyQz8Wn4HXrdTEIBBg=", + "source": "sha256-JOjNO+uRwchh63uz+8m9QYu/+a1KpdBHGBYlgjajFTI=" + } + } + }, + "entrypoints": [ + "092886a00e3c7cb9cb944528116da6ce7d5e4a25b9d198735ac1b1307f77dca5", + "117a52658298bf0e7dc607718e5e39ef93468c41c45dcf8650d7986d93e19341", + "672112d42de52914cd6daaac8a86cf906f80360bd81d6ad0a1df51224d74e9d4", + "8a29d183b38f69620275ab4765d677ada24ff5f96f48d2018d0ee7bcd8ad057e", + "9a3c8a33388fd17cf44291697753b48efba841849e4a92dc37c4f7a4c6877c86", + "c82b26bea8099fcea79b4e243145c4cf2597abdde010248e02fcd273e490e1bb", + "d792a2d7b67521e3af5c323f99f9c5b20625b649826613bdf93854482c22dd1b" + ] + } +} \ No newline at end of file diff --git a/lux.toml b/lux.toml new file mode 100644 index 0000000..d034085 --- /dev/null +++ b/lux.toml @@ -0,0 +1,31 @@ +package = "invokation" +version = "0.1.0" +lua = "==5.1" + +[description] +homepage = "https://github.com/13k/invokation" +issues_url = "https://github.com/13k/invokation/issues" +summary = "Invokation: School of Arcane Arts" +maintainer = "13k " +labels = ["dota2", "invoker", "practice", "trainer"] +license = "MIT" + +[dependencies] + +[test_dependencies] +bit32 = "~> 5.3" +busted = "~> 2.2" +busted-htest = "~> 1.0" +compat53 = "~> 0.14" +luacov = "~> 0.16" +moses = "~> 2.1" +penlight = "~> 1.14" + +[run] +args = ["game/scripts/vscripts/addon_game_mode.lua"] + +[build] +type = "none" + +[test] +type = "busted" From 3b652ff039efede4c0e6a692c6c5a9e14688ba06 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 08:47:11 -0300 Subject: [PATCH 02/29] chore(lsp): replace luals with emmylua_ls --- .emmyrc.json | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ .luarc.json | 14 -------------- 2 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 .emmyrc.json delete mode 100644 .luarc.json diff --git a/.emmyrc.json b/.emmyrc.json new file mode 100644 index 0000000..eeaab14 --- /dev/null +++ b/.emmyrc.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json", + "runtime": { + "pathStrict": true, + "special": { + "assertf": "assert", + "errorf": "error" + }, + "requirePattern": [ + "?.lua", + "?/init.lua" + ], + "version": "LuaJIT" + }, + "workspace": { + "ignoreDir": [ + ".busted", + ".lux", + "tmp" + ], + "workspaceRoots": [ + "game/scripts/vscripts", + "spec" + ], + "library": [ + ".luacats", + "game/scripts/vscripts/compat53", + "game/scripts/vscripts/fsm.lua", + "game/scripts/vscripts/inspect.lua", + "game/scripts/vscripts/middleclass.lua", + ".lux/jit/test_dependencies/jit/01a3c364614bddff7370223a5a9c4580f8e62d144384148444c518ec5367a59b-mediator_lua@1.1.2-0/src", + ".lux/jit/test_dependencies/jit/092886a00e3c7cb9cb944528116da6ce7d5e4a25b9d198735ac1b1307f77dca5-bit32@5.3.5-1/src", + ".lux/jit/test_dependencies/jit/117a52658298bf0e7dc607718e5e39ef93468c41c45dcf8650d7986d93e19341-luacov@0.16.0-1/src", + ".lux/jit/test_dependencies/jit/287e827f4a088d41bba04af5f61a13614346c16fe8150eb7c4246e67d6fd163e-lua-term@0.8-1/src", + ".lux/jit/test_dependencies/jit/316ac0b30e04e86a253d64886f3b110bd0508267474e6b58a3b973bd6857dbf4-penlight@1.14.0-3/src", + ".lux/jit/test_dependencies/jit/455cd98d50c6191a9685cffcda4ce783efbb957934625e134c39f43bd5df6818-luassert@1.9.0-1/src", + ".lux/jit/test_dependencies/jit/47b12edcdc032232157ace97bddf34bddd17f6f458095885e62bbd602ad9e9ec-luasystem@0.6.3-1/src", + ".lux/jit/test_dependencies/jit/4e9592a499c9ced4f8ce366db9db7d9c0dd1424ea8d4c8c16c1550ea3a61a696-say@1.4.1-3/src", + ".lux/jit/test_dependencies/jit/672112d42de52914cd6daaac8a86cf906f80360bd81d6ad0a1df51224d74e9d4-busted-htest@1.0.0-2/src", + ".lux/jit/test_dependencies/jit/6ce29c2c535c40246c386c056f24689344cddb56ec397473931431e6b67694d2-say@1.4.1-3/src", + ".lux/jit/test_dependencies/jit/832fd9862ce671c0c9777855d4c8b19f9ad9c2679fb5466c3a183785a51b76b0-luafilesystem@1.8.0-1/src", + ".lux/jit/test_dependencies/jit/8a29d183b38f69620275ab4765d677ada24ff5f96f48d2018d0ee7bcd8ad057e-busted@2.2.0-1/src", + ".lux/jit/test_dependencies/jit/9a3c8a33388fd17cf44291697753b48efba841849e4a92dc37c4f7a4c6877c86-compat53@0.14.4-1/src", + ".lux/jit/test_dependencies/jit/a6c5176043cb3de56336b7de119443dbb3d9e024be1d50e06289ad4b4959a2da-lua_cliargs@3.0.2-1/src", + ".lux/jit/test_dependencies/jit/c82b26bea8099fcea79b4e243145c4cf2597abdde010248e02fcd273e490e1bb-penlight@1.14.0-3/src", + ".lux/jit/test_dependencies/jit/d792a2d7b67521e3af5c323f99f9c5b20625b649826613bdf93854482c22dd1b-moses@2.1.0-1/src", + ".lux/jit/test_dependencies/jit/e496d4ec14c0feec0b3eac3f622f59eb3777d6e63b24469fdb464841e6ab4e63-datafile@0.11-1/src", + ".lux/jit/test_dependencies/jit/e4f17b9e67313bbd5e90f425672fc8998dd0bfa43335f7c57ed2de7a799e07a6-dkjson@2.8-1/src" + ] + } +} \ No newline at end of file diff --git a/.luarc.json b/.luarc.json deleted file mode 100644 index 3bf752e..0000000 --- a/.luarc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://github.com/LuaLS/vscode-lua/raw/master/setting/schema.json", - "runtime.version": "LuaJIT", - "runtime.pathStrict": true, - "runtime.path": ["game/scripts/vscripts/?.lua", "game/scripts/vscripts/?/init.lua"], - "workspace.ignoreDir": [".busted", ".luarocks", "lua_modules"], - "workspace.checkThirdParty": false, - "workspace.library": [ - ".luacats", - "game/scripts/vscripts/pl", - "game/scripts/vscripts/fsm.lua", - "game/scripts/vscripts/moses.lua" - ] -} From 8a6220b4237715c4075e0dd8b1cb46d6bf386720 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 08:50:04 -0300 Subject: [PATCH 03/29] chore(lint): update luacats types and selene stdlibs --- .luacats/busted.lua | 3 +- .luacats/dota2/enums.lua | 14201 +++++++++++++------------------- .luacats/dota2/events.lua | 154 +- .luacats/dota2/init.lua | 556 +- .luacats/dota2/types.lua | 1 + .luacats/luassert.lua | 2 +- .luacats/middleclass.lua | 27 + .luacats/pl/Date.lua | 294 - .luacats/pl/List.lua | 421 - .luacats/pl/Map.lua | 100 - .luacats/pl/MultiMap.lua | 31 - .luacats/pl/OrderedMap.lua | 90 - .luacats/pl/Set.lua | 194 - .luacats/pl/app.lua | 128 - .luacats/pl/array2d.lua | 325 - .luacats/pl/class.lua | 56 - .luacats/pl/compat.lua | 66 - .luacats/pl/comprehension.lua | 47 - .luacats/pl/config.lua | 65 - .luacats/pl/data.lua | 138 - .luacats/pl/dir.lua | 72 - .luacats/pl/file.lua | 29 - .luacats/pl/func.lua | 135 - .luacats/pl/import_into.lua | 20 - .luacats/pl/input.lua | 77 - .luacats/pl/lapp.lua | 71 - .luacats/pl/lexer.lua | 110 - .luacats/pl/luabalanced.lua | 88 - .luacats/pl/operator.lua | 278 - .luacats/pl/path.lua | 276 - .luacats/pl/permute.lua | 94 - .luacats/pl/pretty.lua | 98 - .luacats/pl/seq.lua | 701 -- .luacats/pl/sip.lua | 82 - .luacats/pl/strict.lua | 61 - .luacats/pl/stringio.lua | 94 - .luacats/pl/stringx.lua | 466 -- .luacats/pl/tablex.lua | 698 -- .luacats/pl/template.lua | 115 - .luacats/pl/test.lua | 102 - .luacats/pl/text.lua | 22 - .luacats/pl/types.lua | 98 - .luacats/pl/url.lua | 20 - .luacats/pl/utils.lua | 567 -- .luacats/pl/xml.lua | 362 - .selene/dota2-custom-game.yml | 27 +- .selene/dota2.yml | 386 +- 47 files changed, 6815 insertions(+), 15233 deletions(-) create mode 100644 .luacats/middleclass.lua delete mode 100644 .luacats/pl/Date.lua delete mode 100644 .luacats/pl/List.lua delete mode 100644 .luacats/pl/Map.lua delete mode 100644 .luacats/pl/MultiMap.lua delete mode 100644 .luacats/pl/OrderedMap.lua delete mode 100644 .luacats/pl/Set.lua delete mode 100644 .luacats/pl/app.lua delete mode 100644 .luacats/pl/array2d.lua delete mode 100644 .luacats/pl/class.lua delete mode 100644 .luacats/pl/compat.lua delete mode 100644 .luacats/pl/comprehension.lua delete mode 100644 .luacats/pl/config.lua delete mode 100644 .luacats/pl/data.lua delete mode 100644 .luacats/pl/dir.lua delete mode 100644 .luacats/pl/file.lua delete mode 100644 .luacats/pl/func.lua delete mode 100644 .luacats/pl/import_into.lua delete mode 100644 .luacats/pl/input.lua delete mode 100644 .luacats/pl/lapp.lua delete mode 100644 .luacats/pl/lexer.lua delete mode 100644 .luacats/pl/luabalanced.lua delete mode 100644 .luacats/pl/operator.lua delete mode 100644 .luacats/pl/path.lua delete mode 100644 .luacats/pl/permute.lua delete mode 100644 .luacats/pl/pretty.lua delete mode 100644 .luacats/pl/seq.lua delete mode 100644 .luacats/pl/sip.lua delete mode 100644 .luacats/pl/strict.lua delete mode 100644 .luacats/pl/stringio.lua delete mode 100644 .luacats/pl/stringx.lua delete mode 100644 .luacats/pl/tablex.lua delete mode 100644 .luacats/pl/template.lua delete mode 100644 .luacats/pl/test.lua delete mode 100644 .luacats/pl/text.lua delete mode 100644 .luacats/pl/types.lua delete mode 100644 .luacats/pl/url.lua delete mode 100644 .luacats/pl/utils.lua delete mode 100644 .luacats/pl/xml.lua diff --git a/.luacats/busted.lua b/.luacats/busted.lua index 10c06d6..452917b 100644 --- a/.luacats/busted.lua +++ b/.luacats/busted.lua @@ -1,4 +1,5 @@ ----@meta +--# selene: allow(incorrect_standard_library_use) +--- @meta assert = require("luassert") spy = require("luassert.spy") diff --git a/.luacats/dota2/enums.lua b/.luacats/dota2/enums.lua index 521dcc0..744f7b0 100644 --- a/.luacats/dota2/enums.lua +++ b/.luacats/dota2/enums.lua @@ -2,6 +2,7 @@ -- Generated by dota2-pos5 -- +--# selene: allow(incorrect_standard_library_use) --# selene: allow(unscoped_variables) --# selene: allow(unused_variable) @@ -13,7 +14,7 @@ DOTA_ITEM_INVENTORY_SIZE = 9 --- (availability: server) -DOTA_ITEM_MAX = 19 +DOTA_ITEM_MAX = 25 --- (availability: server) DOTA_ITEM_STASH_MAX = 15 @@ -25,7 +26,7 @@ DOTA_ITEM_STASH_MIN = 9 DOTA_ITEM_STASH_SIZE = 6 --- (availability: server & client) -DOTA_MAX_ABILITIES = 35 +DOTA_MAX_ABILITIES = 40 --- (availability: server & client) FIND_UNITS_EVERYWHERE = -1 @@ -34,8463 +35,6005 @@ FIND_UNITS_EVERYWHERE = -1 SPAWN_GROUP_HANDLE_INVALID = 0 --- (availability: server & client) ---- @alias ABILITY_TYPES ---- | `ABILITY_TYPE_BASIC` ---- | `ABILITY_TYPE_ULTIMATE` ---- | `ABILITY_TYPE_ATTRIBUTES` ---- | `ABILITY_TYPE_HIDDEN` - ---- @type ABILITY_TYPES -ABILITY_TYPE_BASIC = 0 ---- @type ABILITY_TYPES -ABILITY_TYPE_ULTIMATE = 1 ---- @type ABILITY_TYPES -ABILITY_TYPE_ATTRIBUTES = 2 ---- @type ABILITY_TYPES -ABILITY_TYPE_HIDDEN = 3 +--- @enum ABILITY_TYPES +--- @field ABILITY_TYPE_BASIC 0 +--- @field ABILITY_TYPE_ULTIMATE 1 +--- @field ABILITY_TYPE_ATTRIBUTES 2 +--- @field ABILITY_TYPE_HIDDEN 3 +local ABILITY_TYPES = {} +ABILITY_TYPE_BASIC = ABILITY_TYPES.ABILITY_TYPE_BASIC +ABILITY_TYPE_ULTIMATE = ABILITY_TYPES.ABILITY_TYPE_ULTIMATE +ABILITY_TYPE_ATTRIBUTES = ABILITY_TYPES.ABILITY_TYPE_ATTRIBUTES +ABILITY_TYPE_HIDDEN = ABILITY_TYPES.ABILITY_TYPE_HIDDEN --- (availability: server & client) ---- @alias AbilityLearnResult_t ---- | `ABILITY_CAN_BE_UPGRADED` ---- | `ABILITY_CANNOT_BE_UPGRADED_NOT_UPGRADABLE` ---- | `ABILITY_CANNOT_BE_UPGRADED_AT_MAX` ---- | `ABILITY_CANNOT_BE_UPGRADED_REQUIRES_LEVEL` ---- | `ABILITY_NOT_LEARNABLE` - ---- @type AbilityLearnResult_t -ABILITY_CAN_BE_UPGRADED = 0 ---- @type AbilityLearnResult_t -ABILITY_CANNOT_BE_UPGRADED_NOT_UPGRADABLE = 1 ---- @type AbilityLearnResult_t -ABILITY_CANNOT_BE_UPGRADED_AT_MAX = 2 ---- @type AbilityLearnResult_t -ABILITY_CANNOT_BE_UPGRADED_REQUIRES_LEVEL = 3 ---- @type AbilityLearnResult_t -ABILITY_NOT_LEARNABLE = 4 +--- @enum AbilityLearnResult_t +--- @field ABILITY_CAN_BE_UPGRADED 0 +--- @field ABILITY_CANNOT_BE_UPGRADED_NOT_UPGRADABLE 1 +--- @field ABILITY_CANNOT_BE_UPGRADED_AT_MAX 2 +--- @field ABILITY_CANNOT_BE_UPGRADED_REQUIRES_LEVEL 3 +--- @field ABILITY_NOT_LEARNABLE 4 +local AbilityLearnResult_t = {} +ABILITY_CAN_BE_UPGRADED = AbilityLearnResult_t.ABILITY_CAN_BE_UPGRADED +ABILITY_CANNOT_BE_UPGRADED_NOT_UPGRADABLE = AbilityLearnResult_t.ABILITY_CANNOT_BE_UPGRADED_NOT_UPGRADABLE +ABILITY_CANNOT_BE_UPGRADED_AT_MAX = AbilityLearnResult_t.ABILITY_CANNOT_BE_UPGRADED_AT_MAX +ABILITY_CANNOT_BE_UPGRADED_REQUIRES_LEVEL = AbilityLearnResult_t.ABILITY_CANNOT_BE_UPGRADED_REQUIRES_LEVEL +ABILITY_NOT_LEARNABLE = AbilityLearnResult_t.ABILITY_NOT_LEARNABLE --- (availability: server & client) ---- @alias ActivateType ---- | `ACTIVATE_TYPE_INITIAL_CREATION` ---- | `ACTIVATE_TYPE_DATAUPDATE_CREATION` ---- | `ACTIVATE_TYPE_ONRESTORE` - ---- @type ActivateType -ACTIVATE_TYPE_INITIAL_CREATION = 0 ---- @type ActivateType -ACTIVATE_TYPE_DATAUPDATE_CREATION = 1 ---- @type ActivateType -ACTIVATE_TYPE_ONRESTORE = 2 +--- @enum ActivateType +--- @field ACTIVATE_TYPE_INITIAL_CREATION 0 +--- @field ACTIVATE_TYPE_DATAUPDATE_CREATION 1 +--- @field ACTIVATE_TYPE_ONRESTORE 2 +local ActivateType = {} +ACTIVATE_TYPE_INITIAL_CREATION = ActivateType.ACTIVATE_TYPE_INITIAL_CREATION +ACTIVATE_TYPE_DATAUPDATE_CREATION = ActivateType.ACTIVATE_TYPE_DATAUPDATE_CREATION +ACTIVATE_TYPE_ONRESTORE = ActivateType.ACTIVATE_TYPE_ONRESTORE --- (availability: server) ---- @alias attackfail ---- | `DOTA_ATTACK_RECORD_FAIL_NO` ---- | `DOTA_ATTACK_RECORD_FAIL_TERRAIN_MISS` ---- | `DOTA_ATTACK_RECORD_FAIL_SOURCE_MISS` ---- | `DOTA_ATTACK_RECORD_FAIL_TARGET_EVADED` ---- | `DOTA_ATTACK_RECORD_FAIL_TARGET_INVULNERABLE` ---- | `DOTA_ATTACK_RECORD_FAIL_TARGET_OUT_OF_RANGE` ---- | `DOTA_ATTACK_RECORD_CANNOT_FAIL` ---- | `DOTA_ATTACK_RECORD_FAIL_BLOCKED_BY_OBSTRUCTION` - ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_NO = 0 ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_TERRAIN_MISS = 1 ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_SOURCE_MISS = 2 ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_TARGET_EVADED = 3 ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_TARGET_INVULNERABLE = 4 ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_TARGET_OUT_OF_RANGE = 5 ---- @type attackfail -DOTA_ATTACK_RECORD_CANNOT_FAIL = 6 ---- @type attackfail -DOTA_ATTACK_RECORD_FAIL_BLOCKED_BY_OBSTRUCTION = 7 +--- @enum attackfail +--- @field DOTA_ATTACK_RECORD_FAIL_NO 0 +--- @field DOTA_ATTACK_RECORD_FAIL_TERRAIN_MISS 1 +--- @field DOTA_ATTACK_RECORD_FAIL_SOURCE_MISS 2 +--- @field DOTA_ATTACK_RECORD_FAIL_TARGET_EVADED 3 +--- @field DOTA_ATTACK_RECORD_FAIL_TARGET_INVULNERABLE 4 +--- @field DOTA_ATTACK_RECORD_FAIL_TARGET_OUT_OF_RANGE 5 +--- @field DOTA_ATTACK_RECORD_CANNOT_FAIL 6 +--- @field DOTA_ATTACK_RECORD_FAIL_BLOCKED_BY_OBSTRUCTION 7 +local attackfail = {} +DOTA_ATTACK_RECORD_FAIL_NO = attackfail.DOTA_ATTACK_RECORD_FAIL_NO +DOTA_ATTACK_RECORD_FAIL_TERRAIN_MISS = attackfail.DOTA_ATTACK_RECORD_FAIL_TERRAIN_MISS +DOTA_ATTACK_RECORD_FAIL_SOURCE_MISS = attackfail.DOTA_ATTACK_RECORD_FAIL_SOURCE_MISS +DOTA_ATTACK_RECORD_FAIL_TARGET_EVADED = attackfail.DOTA_ATTACK_RECORD_FAIL_TARGET_EVADED +DOTA_ATTACK_RECORD_FAIL_TARGET_INVULNERABLE = attackfail.DOTA_ATTACK_RECORD_FAIL_TARGET_INVULNERABLE +DOTA_ATTACK_RECORD_FAIL_TARGET_OUT_OF_RANGE = attackfail.DOTA_ATTACK_RECORD_FAIL_TARGET_OUT_OF_RANGE +DOTA_ATTACK_RECORD_CANNOT_FAIL = attackfail.DOTA_ATTACK_RECORD_CANNOT_FAIL +DOTA_ATTACK_RECORD_FAIL_BLOCKED_BY_OBSTRUCTION = attackfail.DOTA_ATTACK_RECORD_FAIL_BLOCKED_BY_OBSTRUCTION --- (availability: server & client) ---- @alias AttributeDerivedStats ---- | `DOTA_ATTRIBUTE_STRENGTH_DAMAGE` ---- | `DOTA_ATTRIBUTE_STRENGTH_HP` ---- | `DOTA_ATTRIBUTE_STRENGTH_HP_REGEN` ---- | `DOTA_ATTRIBUTE_AGILITY_DAMAGE` ---- | `DOTA_ATTRIBUTE_AGILITY_ARMOR` ---- | `DOTA_ATTRIBUTE_AGILITY_ATTACK_SPEED` ---- | `DOTA_ATTRIBUTE_INTELLIGENCE_DAMAGE` ---- | `DOTA_ATTRIBUTE_INTELLIGENCE_MANA` ---- | `DOTA_ATTRIBUTE_INTELLIGENCE_MANA_REGEN` ---- | `DOTA_ATTRIBUTE_INTELLIGENCE_MAGIC_RESIST` ---- | `DOTA_ATTRIBUTE_ALL_DAMAGE` - ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_STRENGTH_DAMAGE = 0 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_STRENGTH_HP = 1 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_STRENGTH_HP_REGEN = 2 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_AGILITY_DAMAGE = 3 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_AGILITY_ARMOR = 4 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_AGILITY_ATTACK_SPEED = 5 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_INTELLIGENCE_DAMAGE = 6 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_INTELLIGENCE_MANA = 7 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_INTELLIGENCE_MANA_REGEN = 8 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_INTELLIGENCE_MAGIC_RESIST = 9 ---- @type AttributeDerivedStats -DOTA_ATTRIBUTE_ALL_DAMAGE = 10 +--- @enum AttributeDerivedStats +--- @field DOTA_ATTRIBUTE_STRENGTH_DAMAGE 0 +--- @field DOTA_ATTRIBUTE_STRENGTH_HP 1 +--- @field DOTA_ATTRIBUTE_STRENGTH_HP_REGEN 2 +--- @field DOTA_ATTRIBUTE_AGILITY_DAMAGE 3 +--- @field DOTA_ATTRIBUTE_AGILITY_ARMOR 4 +--- @field DOTA_ATTRIBUTE_AGILITY_ATTACK_SPEED 5 +--- @field DOTA_ATTRIBUTE_INTELLIGENCE_DAMAGE 6 +--- @field DOTA_ATTRIBUTE_INTELLIGENCE_MANA 7 +--- @field DOTA_ATTRIBUTE_INTELLIGENCE_MANA_REGEN 8 +--- @field DOTA_ATTRIBUTE_INTELLIGENCE_MAGIC_RESIST 9 +--- @field DOTA_ATTRIBUTE_ALL_DAMAGE 10 +local AttributeDerivedStats = {} +DOTA_ATTRIBUTE_STRENGTH_DAMAGE = AttributeDerivedStats.DOTA_ATTRIBUTE_STRENGTH_DAMAGE +DOTA_ATTRIBUTE_STRENGTH_HP = AttributeDerivedStats.DOTA_ATTRIBUTE_STRENGTH_HP +DOTA_ATTRIBUTE_STRENGTH_HP_REGEN = AttributeDerivedStats.DOTA_ATTRIBUTE_STRENGTH_HP_REGEN +DOTA_ATTRIBUTE_AGILITY_DAMAGE = AttributeDerivedStats.DOTA_ATTRIBUTE_AGILITY_DAMAGE +DOTA_ATTRIBUTE_AGILITY_ARMOR = AttributeDerivedStats.DOTA_ATTRIBUTE_AGILITY_ARMOR +DOTA_ATTRIBUTE_AGILITY_ATTACK_SPEED = AttributeDerivedStats.DOTA_ATTRIBUTE_AGILITY_ATTACK_SPEED +DOTA_ATTRIBUTE_INTELLIGENCE_DAMAGE = AttributeDerivedStats.DOTA_ATTRIBUTE_INTELLIGENCE_DAMAGE +DOTA_ATTRIBUTE_INTELLIGENCE_MANA = AttributeDerivedStats.DOTA_ATTRIBUTE_INTELLIGENCE_MANA +DOTA_ATTRIBUTE_INTELLIGENCE_MANA_REGEN = AttributeDerivedStats.DOTA_ATTRIBUTE_INTELLIGENCE_MANA_REGEN +DOTA_ATTRIBUTE_INTELLIGENCE_MAGIC_RESIST = AttributeDerivedStats.DOTA_ATTRIBUTE_INTELLIGENCE_MAGIC_RESIST +DOTA_ATTRIBUTE_ALL_DAMAGE = AttributeDerivedStats.DOTA_ATTRIBUTE_ALL_DAMAGE --- (availability: server & client) ---- @alias Attributes ---- | `DOTA_ATTRIBUTE_INVALID` ---- | `DOTA_ATTRIBUTE_STRENGTH` ---- | `DOTA_ATTRIBUTE_AGILITY` ---- | `DOTA_ATTRIBUTE_INTELLECT` ---- | `DOTA_ATTRIBUTE_ALL` ---- | `DOTA_ATTRIBUTE_MAX` - ---- @type Attributes -DOTA_ATTRIBUTE_INVALID = -1 ---- @type Attributes -DOTA_ATTRIBUTE_STRENGTH = 0 ---- @type Attributes -DOTA_ATTRIBUTE_AGILITY = 1 ---- @type Attributes -DOTA_ATTRIBUTE_INTELLECT = 2 ---- @type Attributes -DOTA_ATTRIBUTE_ALL = 3 ---- @type Attributes -DOTA_ATTRIBUTE_MAX = 4 +--- @enum Attributes +--- @field DOTA_ATTRIBUTE_INVALID -1 +--- @field DOTA_ATTRIBUTE_STRENGTH 0 +--- @field DOTA_ATTRIBUTE_AGILITY 1 +--- @field DOTA_ATTRIBUTE_INTELLECT 2 +--- @field DOTA_ATTRIBUTE_ALL 3 +--- @field DOTA_ATTRIBUTE_MAX 4 +local Attributes = {} +DOTA_ATTRIBUTE_INVALID = Attributes.DOTA_ATTRIBUTE_INVALID +DOTA_ATTRIBUTE_STRENGTH = Attributes.DOTA_ATTRIBUTE_STRENGTH +DOTA_ATTRIBUTE_AGILITY = Attributes.DOTA_ATTRIBUTE_AGILITY +DOTA_ATTRIBUTE_INTELLECT = Attributes.DOTA_ATTRIBUTE_INTELLECT +DOTA_ATTRIBUTE_ALL = Attributes.DOTA_ATTRIBUTE_ALL +DOTA_ATTRIBUTE_MAX = Attributes.DOTA_ATTRIBUTE_MAX --- (availability: server & client) ---- @alias CLICK_BEHAVIORS ---- | `DOTA_CLICK_BEHAVIOR_NONE` ---- | `DOTA_CLICK_BEHAVIOR_MOVE` ---- | `DOTA_CLICK_BEHAVIOR_ATTACK` ---- | `DOTA_CLICK_BEHAVIOR_CAST` ---- | `DOTA_CLICK_BEHAVIOR_DROP_ITEM` ---- | `DOTA_CLICK_BEHAVIOR_DROP_SHOP_ITEM` ---- | `DOTA_CLICK_BEHAVIOR_DRAG` ---- | `DOTA_CLICK_BEHAVIOR_LEARN_ABILITY` ---- | `DOTA_CLICK_BEHAVIOR_PATROL` ---- | `DOTA_CLICK_BEHAVIOR_VECTOR_CAST` ---- | `DOTA_CLICK_BEHAVIOR_UNUSED` ---- | `DOTA_CLICK_BEHAVIOR_RADAR` ---- | `DOTA_CLICK_BEHAVIOR_LAST` - ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_NONE = 0 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_MOVE = 1 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_ATTACK = 2 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_CAST = 3 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_DROP_ITEM = 4 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_DROP_SHOP_ITEM = 5 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_DRAG = 6 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_LEARN_ABILITY = 7 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_PATROL = 8 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_VECTOR_CAST = 9 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_UNUSED = 10 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_RADAR = 11 ---- @type CLICK_BEHAVIORS -DOTA_CLICK_BEHAVIOR_LAST = 12 +--- @enum CLICK_BEHAVIORS +--- @field DOTA_CLICK_BEHAVIOR_NONE 0 +--- @field DOTA_CLICK_BEHAVIOR_MOVE 1 +--- @field DOTA_CLICK_BEHAVIOR_ATTACK 2 +--- @field DOTA_CLICK_BEHAVIOR_CAST 3 +--- @field DOTA_CLICK_BEHAVIOR_DROP_ITEM 4 +--- @field DOTA_CLICK_BEHAVIOR_DROP_SHOP_ITEM 5 +--- @field DOTA_CLICK_BEHAVIOR_DRAG 6 +--- @field DOTA_CLICK_BEHAVIOR_LEARN_ABILITY 7 +--- @field DOTA_CLICK_BEHAVIOR_PATROL 8 +--- @field DOTA_CLICK_BEHAVIOR_VECTOR_CAST 9 +--- @field DOTA_CLICK_BEHAVIOR_UNUSED 10 +--- @field DOTA_CLICK_BEHAVIOR_RADAR 11 +--- @field DOTA_CLICK_BEHAVIOR_LAST 12 +local CLICK_BEHAVIORS = {} +DOTA_CLICK_BEHAVIOR_NONE = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_NONE +DOTA_CLICK_BEHAVIOR_MOVE = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_MOVE +DOTA_CLICK_BEHAVIOR_ATTACK = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_ATTACK +DOTA_CLICK_BEHAVIOR_CAST = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_CAST +DOTA_CLICK_BEHAVIOR_DROP_ITEM = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_DROP_ITEM +DOTA_CLICK_BEHAVIOR_DROP_SHOP_ITEM = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_DROP_SHOP_ITEM +DOTA_CLICK_BEHAVIOR_DRAG = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_DRAG +DOTA_CLICK_BEHAVIOR_LEARN_ABILITY = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_LEARN_ABILITY +DOTA_CLICK_BEHAVIOR_PATROL = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_PATROL +DOTA_CLICK_BEHAVIOR_VECTOR_CAST = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_VECTOR_CAST +DOTA_CLICK_BEHAVIOR_UNUSED = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_UNUSED +DOTA_CLICK_BEHAVIOR_RADAR = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_RADAR +DOTA_CLICK_BEHAVIOR_LAST = CLICK_BEHAVIORS.DOTA_CLICK_BEHAVIOR_LAST --- (availability: server & client) ---- @alias ConVarFlags ---- | `FCVAR_NONE` ---- | `FCVAR_DEVELOPMENTONLY` ---- | `FCVAR_HIDDEN` ---- | `FCVAR_PROTECTED` # Makes the ConVar value hidden from all clients (for example sv_password). Reported as "prot" by cvarlist. ---- | `FCVAR_SPONLY` # Executing the command or changing the ConVar is only allowed in singleplayer. Reported as "sp" by cvarlist. ---- | `FCVAR_ARCHIVE` # Save the ConVar value into config.cfg. Reported as "a" by cvarlist, except Lua ConVars. ---- | `FCVAR_NOTIFY` # For serverside ConVars, notifies all players with blue chat text when the value gets changed. Reported as "nf" by cvarlist. ---- | `FCVAR_USERINFO` # For clientside commands, sends the value to the server. Reported as "user" by cvarlist. ---- | `FCVAR_UNLOGGED` # Don't log the ConVar changes to console/log files/users. Reported as "log" by cvarlist. ---- | `FCVAR_REPLICATED` # For serverside ConVars, it will send its value to all clients. The ConVar with the same name must also exist on the client! Reported as "rep" by cvarlist. ---- | `FCVAR_CHEAT` # Requires sv_cheats to be enabled to change the ConVar or run the command. Reported as "cheat" by cvarlist. ---- | `FCVAR_PER_USER` ---- | `FCVAR_DEMO` # Force the ConVar to be recorded by demo recordings. Reported as "demo" by cvarlist. ---- | `FCVAR_DONTRECORD` # Opposite of FCVAR_DEMO, ensures the ConVar is not recorded in demos. Reported as "norecord" by cvarlist. ---- | `FCVAR_NOT_CONNECTED` # Makes the ConVar not changeable while connected to a server or in singleplayer. ---- | `FCVAR_VCONSOLE_SET_FOCUS` - ---- @type ConVarFlags -FCVAR_NONE = 0 ---- @type ConVarFlags -FCVAR_DEVELOPMENTONLY = 2 ---- @type ConVarFlags -FCVAR_HIDDEN = 16 ---- @type ConVarFlags -FCVAR_PROTECTED = 32 ---- @type ConVarFlags -FCVAR_SPONLY = 64 ---- @type ConVarFlags -FCVAR_ARCHIVE = 128 ---- @type ConVarFlags -FCVAR_NOTIFY = 256 ---- @type ConVarFlags -FCVAR_USERINFO = 512 ---- @type ConVarFlags -FCVAR_UNLOGGED = 2048 ---- @type ConVarFlags -FCVAR_REPLICATED = 8192 ---- @type ConVarFlags -FCVAR_CHEAT = 16384 ---- @type ConVarFlags -FCVAR_PER_USER = 32768 ---- @type ConVarFlags -FCVAR_DEMO = 65536 ---- @type ConVarFlags -FCVAR_DONTRECORD = 131072 ---- @type ConVarFlags -FCVAR_NOT_CONNECTED = 4194304 ---- @type ConVarFlags -FCVAR_VCONSOLE_SET_FOCUS = 134217728 +--- @enum ConVarFlags +--- @field FCVAR_NONE 0 +--- @field FCVAR_DEVELOPMENTONLY 2 +--- @field FCVAR_HIDDEN 16 +--- @field FCVAR_PROTECTED 32 Makes the ConVar value hidden from all clients (for example sv_password). Reported as "prot" by cvarlist. +--- @field FCVAR_SPONLY 64 Executing the command or changing the ConVar is only allowed in singleplayer. Reported as "sp" by cvarlist. +--- @field FCVAR_ARCHIVE 128 Save the ConVar value into config.cfg. Reported as "a" by cvarlist, except Lua ConVars. +--- @field FCVAR_NOTIFY 256 For serverside ConVars, notifies all players with blue chat text when the value gets changed. Reported as "nf" by cvarlist. +--- @field FCVAR_USERINFO 512 For clientside commands, sends the value to the server. Reported as "user" by cvarlist. +--- @field FCVAR_UNLOGGED 2048 Don't log the ConVar changes to console/log files/users. Reported as "log" by cvarlist. +--- @field FCVAR_REPLICATED 8192 For serverside ConVars, it will send its value to all clients. The ConVar with the same name must also exist on the client! Reported as "rep" by cvarlist. +--- @field FCVAR_CHEAT 16384 Requires sv_cheats to be enabled to change the ConVar or run the command. Reported as "cheat" by cvarlist. +--- @field FCVAR_PER_USER 32768 +--- @field FCVAR_DEMO 65536 Force the ConVar to be recorded by demo recordings. Reported as "demo" by cvarlist. +--- @field FCVAR_DONTRECORD 131072 Opposite of FCVAR_DEMO, ensures the ConVar is not recorded in demos. Reported as "norecord" by cvarlist. +--- @field FCVAR_NOT_CONNECTED 4194304 Makes the ConVar not changeable while connected to a server or in singleplayer. +--- @field FCVAR_VCONSOLE_SET_FOCUS 134217728 +local ConVarFlags = {} +FCVAR_NONE = ConVarFlags.FCVAR_NONE +FCVAR_DEVELOPMENTONLY = ConVarFlags.FCVAR_DEVELOPMENTONLY +FCVAR_HIDDEN = ConVarFlags.FCVAR_HIDDEN +FCVAR_PROTECTED = ConVarFlags.FCVAR_PROTECTED +FCVAR_SPONLY = ConVarFlags.FCVAR_SPONLY +FCVAR_ARCHIVE = ConVarFlags.FCVAR_ARCHIVE +FCVAR_NOTIFY = ConVarFlags.FCVAR_NOTIFY +FCVAR_USERINFO = ConVarFlags.FCVAR_USERINFO +FCVAR_UNLOGGED = ConVarFlags.FCVAR_UNLOGGED +FCVAR_REPLICATED = ConVarFlags.FCVAR_REPLICATED +FCVAR_CHEAT = ConVarFlags.FCVAR_CHEAT +FCVAR_PER_USER = ConVarFlags.FCVAR_PER_USER +FCVAR_DEMO = ConVarFlags.FCVAR_DEMO +FCVAR_DONTRECORD = ConVarFlags.FCVAR_DONTRECORD +FCVAR_NOT_CONNECTED = ConVarFlags.FCVAR_NOT_CONNECTED +FCVAR_VCONSOLE_SET_FOCUS = ConVarFlags.FCVAR_VCONSOLE_SET_FOCUS --- (availability: server) ---- @alias DAMAGE_TYPES ---- | `DAMAGE_TYPE_NONE` ---- | `DAMAGE_TYPE_PHYSICAL` ---- | `DAMAGE_TYPE_MAGICAL` ---- | `DAMAGE_TYPE_PURE` ---- | `DAMAGE_TYPE_ALL` ---- | `DAMAGE_TYPE_HP_REMOVAL` ---- | `DAMAGE_TYPE_ABILITY_DEFINED` - ---- @type DAMAGE_TYPES -DAMAGE_TYPE_NONE = 0 ---- @type DAMAGE_TYPES -DAMAGE_TYPE_PHYSICAL = 1 ---- @type DAMAGE_TYPES -DAMAGE_TYPE_MAGICAL = 2 ---- @type DAMAGE_TYPES -DAMAGE_TYPE_PURE = 4 ---- @type DAMAGE_TYPES -DAMAGE_TYPE_ALL = 7 ---- @type DAMAGE_TYPES -DAMAGE_TYPE_HP_REMOVAL = 8 ---- @type DAMAGE_TYPES -DAMAGE_TYPE_ABILITY_DEFINED = 22 +--- @enum DAMAGE_TYPES +--- @field DAMAGE_TYPE_NONE 0 +--- @field DAMAGE_TYPE_PHYSICAL 1 +--- @field DAMAGE_TYPE_MAGICAL 2 +--- @field DAMAGE_TYPE_PURE 4 +--- @field DAMAGE_TYPE_ALL 7 +--- @field DAMAGE_TYPE_HP_REMOVAL 8 +--- @field DAMAGE_TYPE_ABILITY_DEFINED 16 +local DAMAGE_TYPES = {} +DAMAGE_TYPE_NONE = DAMAGE_TYPES.DAMAGE_TYPE_NONE +DAMAGE_TYPE_PHYSICAL = DAMAGE_TYPES.DAMAGE_TYPE_PHYSICAL +DAMAGE_TYPE_MAGICAL = DAMAGE_TYPES.DAMAGE_TYPE_MAGICAL +DAMAGE_TYPE_PURE = DAMAGE_TYPES.DAMAGE_TYPE_PURE +DAMAGE_TYPE_ALL = DAMAGE_TYPES.DAMAGE_TYPE_ALL +DAMAGE_TYPE_HP_REMOVAL = DAMAGE_TYPES.DAMAGE_TYPE_HP_REMOVAL +DAMAGE_TYPE_ABILITY_DEFINED = DAMAGE_TYPES.DAMAGE_TYPE_ABILITY_DEFINED --- (availability: server) ---- @alias DamageCategory_t ---- | `DOTA_DAMAGE_CATEGORY_SPELL` ---- | `DOTA_DAMAGE_CATEGORY_ATTACK` - ---- @type DamageCategory_t -DOTA_DAMAGE_CATEGORY_SPELL = 0 ---- @type DamageCategory_t -DOTA_DAMAGE_CATEGORY_ATTACK = 1 +--- @enum DamageCategory_t +--- @field DOTA_DAMAGE_CATEGORY_SPELL 0 +--- @field DOTA_DAMAGE_CATEGORY_ATTACK 1 +--- @field DOTA_DAMAGE_CATEGORY_BARRIER 2 +local DamageCategory_t = {} +DOTA_DAMAGE_CATEGORY_SPELL = DamageCategory_t.DOTA_DAMAGE_CATEGORY_SPELL +DOTA_DAMAGE_CATEGORY_ATTACK = DamageCategory_t.DOTA_DAMAGE_CATEGORY_ATTACK +DOTA_DAMAGE_CATEGORY_BARRIER = DamageCategory_t.DOTA_DAMAGE_CATEGORY_BARRIER --- (availability: server & client) ---- @alias DOTA_ABILITY_BEHAVIOR ---- | `DOTA_ABILITY_BEHAVIOR_LAST_RESORT_POINT` ---- | `DOTA_ABILITY_BEHAVIOR_ALT_CASTABLE` ---- | `DOTA_ABILITY_BEHAVIOR_BREAK_DISABLES` ---- | `DOTA_ABILITY_BEHAVIOR_CAN_SELF_CAST` ---- | `DOTA_ABILITY_BEHAVIOR_FREE_DRAW_TARGETING` ---- | `DOTA_ABILITY_BEHAVIOR_IGNORE_MUTED` ---- | `DOTA_ABILITY_BEHAVIOR_IGNORE_SILENCE` ---- | `DOTA_ABILITY_BEHAVIOR_NONE` ---- | `DOTA_ABILITY_BEHAVIOR_OVERSHOOT` ---- | `DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES` ---- | `DOTA_ABILITY_BEHAVIOR_SUPPRESS_ASSOCIATED_CONSUMABLE` ---- | `DOTA_ABILITY_BEHAVIOR_UNLOCKED_BY_EFFECT_INDEX` ---- | `DOTA_ABILITY_BEHAVIOR_HIDDEN` ---- | `DOTA_ABILITY_BEHAVIOR_PASSIVE` ---- | `DOTA_ABILITY_BEHAVIOR_NO_TARGET` ---- | `DOTA_ABILITY_BEHAVIOR_UNIT_TARGET` ---- | `DOTA_ABILITY_BEHAVIOR_POINT` ---- | `DOTA_ABILITY_BEHAVIOR_AOE` ---- | `DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE` ---- | `DOTA_ABILITY_BEHAVIOR_CHANNELLED` ---- | `DOTA_ABILITY_BEHAVIOR_ITEM` ---- | `DOTA_ABILITY_BEHAVIOR_TOGGLE` ---- | `DOTA_ABILITY_BEHAVIOR_DIRECTIONAL` ---- | `DOTA_ABILITY_BEHAVIOR_IMMEDIATE` ---- | `DOTA_ABILITY_BEHAVIOR_AUTOCAST` ---- | `DOTA_ABILITY_BEHAVIOR_OPTIONAL_UNIT_TARGET` ---- | `DOTA_ABILITY_BEHAVIOR_OPTIONAL_POINT` ---- | `DOTA_ABILITY_BEHAVIOR_OPTIONAL_NO_TARGET` ---- | `DOTA_ABILITY_BEHAVIOR_AURA` ---- | `DOTA_ABILITY_BEHAVIOR_ATTACK` ---- | `DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT` ---- | `DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES` ---- | `DOTA_ABILITY_BEHAVIOR_UNRESTRICTED` ---- | `DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE` ---- | `DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL` ---- | `DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT` ---- | `DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET` ---- | `DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK` ---- | `DOTA_ABILITY_BEHAVIOR_NORMAL_WHEN_STOLEN` ---- | `DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING` ---- | `DOTA_ABILITY_BEHAVIOR_RUNE_TARGET` ---- | `DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_CHANNEL` ---- | `DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING` - ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_LAST_RESORT_POINT = -2147483648 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_ALT_CASTABLE = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_BREAK_DISABLES = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_CAN_SELF_CAST = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_FREE_DRAW_TARGETING = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_IGNORE_MUTED = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_IGNORE_SILENCE = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_NONE = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_OVERSHOOT = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_SUPPRESS_ASSOCIATED_CONSUMABLE = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_UNLOCKED_BY_EFFECT_INDEX = 0 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_HIDDEN = 1 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_PASSIVE = 2 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_NO_TARGET = 4 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_UNIT_TARGET = 8 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_POINT = 16 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_AOE = 32 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE = 64 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_CHANNELLED = 128 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_ITEM = 256 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_TOGGLE = 512 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_DIRECTIONAL = 1024 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_IMMEDIATE = 2048 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_AUTOCAST = 4096 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_OPTIONAL_UNIT_TARGET = 8192 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_OPTIONAL_POINT = 16384 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_OPTIONAL_NO_TARGET = 32768 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_AURA = 65536 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_ATTACK = 131072 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT = 262144 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES = 524288 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_UNRESTRICTED = 1048576 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE = 2097152 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL = 4194304 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT = 8388608 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET = 16777216 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK = 33554432 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_NORMAL_WHEN_STOLEN = 67108864 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING = 134217728 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_RUNE_TARGET = 268435456 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_CHANNEL = 536870912 ---- @type DOTA_ABILITY_BEHAVIOR -DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING = 1073741824 +--- @enum DOTA_ABILITY_BEHAVIOR +--- @field DOTA_ABILITY_BEHAVIOR_LAST_RESORT_POINT -2147483648 +--- @field DOTA_ABILITY_BEHAVIOR_AFFECTED_BY_MUTE 0 +--- @field DOTA_ABILITY_BEHAVIOR_ALT_CASTABLE 0 +--- @field DOTA_ABILITY_BEHAVIOR_CAN_SELF_CAST 0 +--- @field DOTA_ABILITY_BEHAVIOR_DONT_PROC_OTHER_ABILITIES 0 +--- @field DOTA_ABILITY_BEHAVIOR_FREE_DRAW_TARGETING 0 +--- @field DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE 0 +--- @field DOTA_ABILITY_BEHAVIOR_IGNORE_MUTED 0 +--- @field DOTA_ABILITY_BEHAVIOR_IGNORE_SILENCE 0 +--- @field DOTA_ABILITY_BEHAVIOR_INNATE_UI 0 +--- @field DOTA_ABILITY_BEHAVIOR_IS_FAKE_ITEM 0 +--- @field DOTA_ABILITY_BEHAVIOR_NONE 0 +--- @field DOTA_ABILITY_BEHAVIOR_OVERSHOOT 0 +--- @field DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES 0 +--- @field DOTA_ABILITY_BEHAVIOR_SKIP_FOR_KEYBINDS 0 +--- @field DOTA_ABILITY_BEHAVIOR_SUPPRESS_ASSOCIATED_CONSUMABLE 0 +--- @field DOTA_ABILITY_BEHAVIOR_UNLOCKED_BY_EFFECT_INDEX 0 +--- @field DOTA_ABILITY_BEHAVIOR_UNSWAPPABLE 0 +--- @field DOTA_ABILITY_BEHAVIOR_HIDDEN 1 +--- @field DOTA_ABILITY_BEHAVIOR_PASSIVE 2 +--- @field DOTA_ABILITY_BEHAVIOR_NO_TARGET 4 +--- @field DOTA_ABILITY_BEHAVIOR_UNIT_TARGET 8 +--- @field DOTA_ABILITY_BEHAVIOR_POINT 16 +--- @field DOTA_ABILITY_BEHAVIOR_AOE 32 +--- @field DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE 64 +--- @field DOTA_ABILITY_BEHAVIOR_CHANNELLED 128 +--- @field DOTA_ABILITY_BEHAVIOR_ITEM 256 +--- @field DOTA_ABILITY_BEHAVIOR_TOGGLE 512 +--- @field DOTA_ABILITY_BEHAVIOR_DIRECTIONAL 1024 +--- @field DOTA_ABILITY_BEHAVIOR_IMMEDIATE 2048 +--- @field DOTA_ABILITY_BEHAVIOR_AUTOCAST 4096 +--- @field DOTA_ABILITY_BEHAVIOR_OPTIONAL_UNIT_TARGET 8192 +--- @field DOTA_ABILITY_BEHAVIOR_OPTIONAL_POINT 16384 +--- @field DOTA_ABILITY_BEHAVIOR_OPTIONAL_NO_TARGET 32768 +--- @field DOTA_ABILITY_BEHAVIOR_AURA 65536 +--- @field DOTA_ABILITY_BEHAVIOR_ATTACK 131072 +--- @field DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT 262144 +--- @field DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES 524288 +--- @field DOTA_ABILITY_BEHAVIOR_UNRESTRICTED 1048576 +--- @field DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE 2097152 +--- @field DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL 4194304 +--- @field DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT 8388608 +--- @field DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET 16777216 +--- @field DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK 33554432 +--- @field DOTA_ABILITY_BEHAVIOR_NORMAL_WHEN_STOLEN 67108864 +--- @field DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING 134217728 +--- @field DOTA_ABILITY_BEHAVIOR_RUNE_TARGET 268435456 +--- @field DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_CHANNEL 536870912 +--- @field DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING 1073741824 +local DOTA_ABILITY_BEHAVIOR = {} +DOTA_ABILITY_BEHAVIOR_LAST_RESORT_POINT = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_LAST_RESORT_POINT +DOTA_ABILITY_BEHAVIOR_AFFECTED_BY_MUTE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_AFFECTED_BY_MUTE +DOTA_ABILITY_BEHAVIOR_ALT_CASTABLE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_ALT_CASTABLE +DOTA_ABILITY_BEHAVIOR_CAN_SELF_CAST = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_CAN_SELF_CAST +DOTA_ABILITY_BEHAVIOR_DONT_PROC_OTHER_ABILITIES = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DONT_PROC_OTHER_ABILITIES +DOTA_ABILITY_BEHAVIOR_FREE_DRAW_TARGETING = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_FREE_DRAW_TARGETING +DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE +DOTA_ABILITY_BEHAVIOR_IGNORE_MUTED = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IGNORE_MUTED +DOTA_ABILITY_BEHAVIOR_IGNORE_SILENCE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IGNORE_SILENCE +DOTA_ABILITY_BEHAVIOR_INNATE_UI = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_INNATE_UI +DOTA_ABILITY_BEHAVIOR_IS_FAKE_ITEM = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IS_FAKE_ITEM +DOTA_ABILITY_BEHAVIOR_NONE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_NONE +DOTA_ABILITY_BEHAVIOR_OVERSHOOT = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_OVERSHOOT +DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES +DOTA_ABILITY_BEHAVIOR_SKIP_FOR_KEYBINDS = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_SKIP_FOR_KEYBINDS +DOTA_ABILITY_BEHAVIOR_SUPPRESS_ASSOCIATED_CONSUMABLE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_SUPPRESS_ASSOCIATED_CONSUMABLE +DOTA_ABILITY_BEHAVIOR_UNLOCKED_BY_EFFECT_INDEX = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_UNLOCKED_BY_EFFECT_INDEX +DOTA_ABILITY_BEHAVIOR_UNSWAPPABLE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_UNSWAPPABLE +DOTA_ABILITY_BEHAVIOR_HIDDEN = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_HIDDEN +DOTA_ABILITY_BEHAVIOR_PASSIVE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_PASSIVE +DOTA_ABILITY_BEHAVIOR_NO_TARGET = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_NO_TARGET +DOTA_ABILITY_BEHAVIOR_UNIT_TARGET = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_UNIT_TARGET +DOTA_ABILITY_BEHAVIOR_POINT = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_POINT +DOTA_ABILITY_BEHAVIOR_AOE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_AOE +DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE +DOTA_ABILITY_BEHAVIOR_CHANNELLED = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_CHANNELLED +DOTA_ABILITY_BEHAVIOR_ITEM = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_ITEM +DOTA_ABILITY_BEHAVIOR_TOGGLE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_TOGGLE +DOTA_ABILITY_BEHAVIOR_DIRECTIONAL = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DIRECTIONAL +DOTA_ABILITY_BEHAVIOR_IMMEDIATE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IMMEDIATE +DOTA_ABILITY_BEHAVIOR_AUTOCAST = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_AUTOCAST +DOTA_ABILITY_BEHAVIOR_OPTIONAL_UNIT_TARGET = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_OPTIONAL_UNIT_TARGET +DOTA_ABILITY_BEHAVIOR_OPTIONAL_POINT = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_OPTIONAL_POINT +DOTA_ABILITY_BEHAVIOR_OPTIONAL_NO_TARGET = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_OPTIONAL_NO_TARGET +DOTA_ABILITY_BEHAVIOR_AURA = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_AURA +DOTA_ABILITY_BEHAVIOR_ATTACK = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_ATTACK +DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT +DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_ROOT_DISABLES +DOTA_ABILITY_BEHAVIOR_UNRESTRICTED = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_UNRESTRICTED +DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE +DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL +DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT +DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DONT_ALERT_TARGET +DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK +DOTA_ABILITY_BEHAVIOR_NORMAL_WHEN_STOLEN = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_NORMAL_WHEN_STOLEN +DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING +DOTA_ABILITY_BEHAVIOR_RUNE_TARGET = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_RUNE_TARGET +DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_CHANNEL = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_CHANNEL +DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING = DOTA_ABILITY_BEHAVIOR.DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING --- (availability: server) ---- @alias DOTA_GameState ---- | `DOTA_GAMERULES_STATE_INIT` ---- | `DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD` ---- | `DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP` ---- | `DOTA_GAMERULES_STATE_PLAYER_DRAFT` ---- | `DOTA_GAMERULES_STATE_HERO_SELECTION` ---- | `DOTA_GAMERULES_STATE_STRATEGY_TIME` ---- | `DOTA_GAMERULES_STATE_TEAM_SHOWCASE` ---- | `DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD` ---- | `DOTA_GAMERULES_STATE_PRE_GAME` ---- | `DOTA_GAMERULES_STATE_SCENARIO_SETUP` ---- | `DOTA_GAMERULES_STATE_GAME_IN_PROGRESS` ---- | `DOTA_GAMERULES_STATE_POST_GAME` ---- | `DOTA_GAMERULES_STATE_DISCONNECT` - ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_INIT = 0 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD = 1 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP = 2 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_PLAYER_DRAFT = 3 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_HERO_SELECTION = 4 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_STRATEGY_TIME = 5 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_TEAM_SHOWCASE = 6 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD = 7 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_PRE_GAME = 8 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_SCENARIO_SETUP = 9 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_GAME_IN_PROGRESS = 10 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_POST_GAME = 11 ---- @type DOTA_GameState -DOTA_GAMERULES_STATE_DISCONNECT = 12 +--- @enum DOTA_GameState +--- @field DOTA_GAMERULES_STATE_INIT 0 +--- @field DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD 1 +--- @field DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP 2 +--- @field DOTA_GAMERULES_STATE_PLAYER_DRAFT 3 +--- @field DOTA_GAMERULES_STATE_HERO_SELECTION 4 +--- @field DOTA_GAMERULES_STATE_STRATEGY_TIME 5 +--- @field DOTA_GAMERULES_STATE_TEAM_SHOWCASE 6 +--- @field DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD 7 +--- @field DOTA_GAMERULES_STATE_PRE_GAME 8 +--- @field DOTA_GAMERULES_STATE_SCENARIO_SETUP 9 +--- @field DOTA_GAMERULES_STATE_GAME_IN_PROGRESS 10 +--- @field DOTA_GAMERULES_STATE_POST_GAME 11 +--- @field DOTA_GAMERULES_STATE_DISCONNECT 12 +local DOTA_GameState = {} +DOTA_GAMERULES_STATE_INIT = DOTA_GameState.DOTA_GAMERULES_STATE_INIT +DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD = DOTA_GameState.DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS_TO_LOAD +DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP = DOTA_GameState.DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP +DOTA_GAMERULES_STATE_PLAYER_DRAFT = DOTA_GameState.DOTA_GAMERULES_STATE_PLAYER_DRAFT +DOTA_GAMERULES_STATE_HERO_SELECTION = DOTA_GameState.DOTA_GAMERULES_STATE_HERO_SELECTION +DOTA_GAMERULES_STATE_STRATEGY_TIME = DOTA_GameState.DOTA_GAMERULES_STATE_STRATEGY_TIME +DOTA_GAMERULES_STATE_TEAM_SHOWCASE = DOTA_GameState.DOTA_GAMERULES_STATE_TEAM_SHOWCASE +DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD = DOTA_GameState.DOTA_GAMERULES_STATE_WAIT_FOR_MAP_TO_LOAD +DOTA_GAMERULES_STATE_PRE_GAME = DOTA_GameState.DOTA_GAMERULES_STATE_PRE_GAME +DOTA_GAMERULES_STATE_SCENARIO_SETUP = DOTA_GameState.DOTA_GAMERULES_STATE_SCENARIO_SETUP +DOTA_GAMERULES_STATE_GAME_IN_PROGRESS = DOTA_GameState.DOTA_GAMERULES_STATE_GAME_IN_PROGRESS +DOTA_GAMERULES_STATE_POST_GAME = DOTA_GameState.DOTA_GAMERULES_STATE_POST_GAME +DOTA_GAMERULES_STATE_DISCONNECT = DOTA_GameState.DOTA_GAMERULES_STATE_DISCONNECT --- (availability: server) ---- @alias DOTA_GC_TEAM ---- | `DOTA_GC_TEAM_GOOD_GUYS` ---- | `DOTA_GC_TEAM_BAD_GUYS` ---- | `DOTA_GC_TEAM_BROADCASTER` ---- | `DOTA_GC_TEAM_SPECTATOR` ---- | `DOTA_GC_TEAM_PLAYER_POOL` ---- | `DOTA_GC_TEAM_NOTEAM` ---- | `DOTA_GC_TEAM_CUSTOM_1` ---- | `DOTA_GC_TEAM_CUSTOM_2` ---- | `DOTA_GC_TEAM_CUSTOM_3` ---- | `DOTA_GC_TEAM_CUSTOM_4` ---- | `DOTA_GC_TEAM_CUSTOM_5` ---- | `DOTA_GC_TEAM_CUSTOM_6` ---- | `DOTA_GC_TEAM_CUSTOM_7` ---- | `DOTA_GC_TEAM_CUSTOM_8` ---- | `DOTA_GC_TEAM_NEUTRALS` - ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_GOOD_GUYS = 0 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_BAD_GUYS = 1 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_BROADCASTER = 2 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_SPECTATOR = 3 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_PLAYER_POOL = 4 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_NOTEAM = 5 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_1 = 6 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_2 = 7 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_3 = 8 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_4 = 9 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_5 = 10 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_6 = 11 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_7 = 12 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_CUSTOM_8 = 13 ---- @type DOTA_GC_TEAM -DOTA_GC_TEAM_NEUTRALS = 14 +--- @enum DOTA_GC_TEAM +--- @field DOTA_GC_TEAM_GOOD_GUYS 0 +--- @field DOTA_GC_TEAM_BAD_GUYS 1 +--- @field DOTA_GC_TEAM_BROADCASTER 2 +--- @field DOTA_GC_TEAM_SPECTATOR 3 +--- @field DOTA_GC_TEAM_PLAYER_POOL 4 +--- @field DOTA_GC_TEAM_NOTEAM 5 +--- @field DOTA_GC_TEAM_CUSTOM_1 6 +--- @field DOTA_GC_TEAM_CUSTOM_2 7 +--- @field DOTA_GC_TEAM_CUSTOM_3 8 +--- @field DOTA_GC_TEAM_CUSTOM_4 9 +--- @field DOTA_GC_TEAM_CUSTOM_5 10 +--- @field DOTA_GC_TEAM_CUSTOM_6 11 +--- @field DOTA_GC_TEAM_CUSTOM_7 12 +--- @field DOTA_GC_TEAM_CUSTOM_8 13 +--- @field DOTA_GC_TEAM_NEUTRALS 14 +local DOTA_GC_TEAM = {} +DOTA_GC_TEAM_GOOD_GUYS = DOTA_GC_TEAM.DOTA_GC_TEAM_GOOD_GUYS +DOTA_GC_TEAM_BAD_GUYS = DOTA_GC_TEAM.DOTA_GC_TEAM_BAD_GUYS +DOTA_GC_TEAM_BROADCASTER = DOTA_GC_TEAM.DOTA_GC_TEAM_BROADCASTER +DOTA_GC_TEAM_SPECTATOR = DOTA_GC_TEAM.DOTA_GC_TEAM_SPECTATOR +DOTA_GC_TEAM_PLAYER_POOL = DOTA_GC_TEAM.DOTA_GC_TEAM_PLAYER_POOL +DOTA_GC_TEAM_NOTEAM = DOTA_GC_TEAM.DOTA_GC_TEAM_NOTEAM +DOTA_GC_TEAM_CUSTOM_1 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_1 +DOTA_GC_TEAM_CUSTOM_2 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_2 +DOTA_GC_TEAM_CUSTOM_3 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_3 +DOTA_GC_TEAM_CUSTOM_4 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_4 +DOTA_GC_TEAM_CUSTOM_5 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_5 +DOTA_GC_TEAM_CUSTOM_6 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_6 +DOTA_GC_TEAM_CUSTOM_7 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_7 +DOTA_GC_TEAM_CUSTOM_8 = DOTA_GC_TEAM.DOTA_GC_TEAM_CUSTOM_8 +DOTA_GC_TEAM_NEUTRALS = DOTA_GC_TEAM.DOTA_GC_TEAM_NEUTRALS --- (availability: server & client) ---- @alias DOTA_HeroPickState ---- | `DOTA_HEROPICK_STATE_NONE` ---- | `DOTA_HEROPICK_STATE_AP_SELECT` ---- | `DOTA_HEROPICK_STATE_SD_SELECT` ---- | `DOTA_HEROPICK_STATE_INTRO_SELECT_UNUSED` ---- | `DOTA_HEROPICK_STATE_RD_SELECT_UNUSED` ---- | `DOTA_HEROPICK_STATE_CM_INTRO` ---- | `DOTA_HEROPICK_STATE_CM_CAPTAINPICK` ---- | `DOTA_HEROPICK_STATE_CM_BAN1` ---- | `DOTA_HEROPICK_STATE_CM_BAN2` ---- | `DOTA_HEROPICK_STATE_CM_BAN3` ---- | `DOTA_HEROPICK_STATE_CM_BAN4` ---- | `DOTA_HEROPICK_STATE_CM_BAN5` ---- | `DOTA_HEROPICK_STATE_CM_BAN6` ---- | `DOTA_HEROPICK_STATE_CM_BAN7` ---- | `DOTA_HEROPICK_STATE_CM_BAN8` ---- | `DOTA_HEROPICK_STATE_CM_BAN9` ---- | `DOTA_HEROPICK_STATE_CM_BAN10` ---- | `DOTA_HEROPICK_STATE_CM_BAN11` ---- | `DOTA_HEROPICK_STATE_CM_BAN12` ---- | `DOTA_HEROPICK_STATE_CM_BAN13` ---- | `DOTA_HEROPICK_STATE_CM_BAN14` ---- | `DOTA_HEROPICK_STATE_CM_SELECT1` ---- | `DOTA_HEROPICK_STATE_CM_SELECT2` ---- | `DOTA_HEROPICK_STATE_CM_SELECT3` ---- | `DOTA_HEROPICK_STATE_CM_SELECT4` ---- | `DOTA_HEROPICK_STATE_CM_SELECT5` ---- | `DOTA_HEROPICK_STATE_CM_SELECT6` ---- | `DOTA_HEROPICK_STATE_CM_SELECT7` ---- | `DOTA_HEROPICK_STATE_CM_SELECT8` ---- | `DOTA_HEROPICK_STATE_CM_SELECT9` ---- | `DOTA_HEROPICK_STATE_CM_SELECT10` ---- | `DOTA_HEROPICK_STATE_CM_PICK` ---- | `DOTA_HEROPICK_STATE_AR_SELECT` ---- | `DOTA_HEROPICK_STATE_MO_SELECT` ---- | `DOTA_HEROPICK_STATE_FH_SELECT` ---- | `DOTA_HEROPICK_STATE_CD_INTRO` ---- | `DOTA_HEROPICK_STATE_CD_CAPTAINPICK` ---- | `DOTA_HEROPICK_STATE_CD_BAN1` ---- | `DOTA_HEROPICK_STATE_CD_BAN2` ---- | `DOTA_HEROPICK_STATE_CD_BAN3` ---- | `DOTA_HEROPICK_STATE_CD_BAN4` ---- | `DOTA_HEROPICK_STATE_CD_BAN5` ---- | `DOTA_HEROPICK_STATE_CD_BAN6` ---- | `DOTA_HEROPICK_STATE_CD_SELECT1` ---- | `DOTA_HEROPICK_STATE_CD_SELECT2` ---- | `DOTA_HEROPICK_STATE_CD_SELECT3` ---- | `DOTA_HEROPICK_STATE_CD_SELECT4` ---- | `DOTA_HEROPICK_STATE_CD_SELECT5` ---- | `DOTA_HEROPICK_STATE_CD_SELECT6` ---- | `DOTA_HEROPICK_STATE_CD_SELECT7` ---- | `DOTA_HEROPICK_STATE_CD_SELECT8` ---- | `DOTA_HEROPICK_STATE_CD_SELECT9` ---- | `DOTA_HEROPICK_STATE_CD_SELECT10` ---- | `DOTA_HEROPICK_STATE_CD_PICK` ---- | `DOTA_HEROPICK_STATE_BD_SELECT` ---- | `DOTA_HERO_PICK_STATE_ABILITY_DRAFT_SELECT` ---- | `DOTA_HERO_PICK_STATE_ARDM_SELECT` ---- | `DOTA_HEROPICK_STATE_ALL_DRAFT_SELECT` ---- | `DOTA_HERO_PICK_STATE_CUSTOMGAME_SELECT` ---- | `DOTA_HEROPICK_STATE_SELECT_PENALTY` ---- | `DOTA_HEROPICK_STATE_CUSTOM_PICK_RULES` ---- | `DOTA_HEROPICK_STATE_SCENARIO_PICK` ---- | `DOTA_HEROPICK_STATE_COUNT` - ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_NONE = 0 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_AP_SELECT = 1 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_SD_SELECT = 2 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_INTRO_SELECT_UNUSED = 3 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_RD_SELECT_UNUSED = 4 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_INTRO = 5 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_CAPTAINPICK = 6 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN1 = 7 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN2 = 8 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN3 = 9 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN4 = 10 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN5 = 11 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN6 = 12 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN7 = 13 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN8 = 14 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN9 = 15 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN10 = 16 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN11 = 17 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN12 = 18 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN13 = 19 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_BAN14 = 20 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT1 = 21 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT2 = 22 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT3 = 23 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT4 = 24 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT5 = 25 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT6 = 26 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT7 = 27 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT8 = 28 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT9 = 29 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_SELECT10 = 30 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CM_PICK = 31 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_AR_SELECT = 32 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_MO_SELECT = 33 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_FH_SELECT = 34 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_INTRO = 35 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_CAPTAINPICK = 36 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_BAN1 = 37 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_BAN2 = 38 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_BAN3 = 39 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_BAN4 = 40 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_BAN5 = 41 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_BAN6 = 42 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT1 = 43 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT2 = 44 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT3 = 45 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT4 = 46 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT5 = 47 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT6 = 48 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT7 = 49 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT8 = 50 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT9 = 51 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_SELECT10 = 52 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CD_PICK = 53 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_BD_SELECT = 54 ---- @type DOTA_HeroPickState -DOTA_HERO_PICK_STATE_ABILITY_DRAFT_SELECT = 55 ---- @type DOTA_HeroPickState -DOTA_HERO_PICK_STATE_ARDM_SELECT = 56 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_ALL_DRAFT_SELECT = 57 ---- @type DOTA_HeroPickState -DOTA_HERO_PICK_STATE_CUSTOMGAME_SELECT = 58 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_SELECT_PENALTY = 59 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_CUSTOM_PICK_RULES = 60 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_SCENARIO_PICK = 61 ---- @type DOTA_HeroPickState -DOTA_HEROPICK_STATE_COUNT = 62 +--- @enum DOTA_HeroPickState +--- @field DOTA_HEROPICK_STATE_NONE 0 +--- @field DOTA_HEROPICK_STATE_AP_SELECT 1 +--- @field DOTA_HEROPICK_STATE_SD_SELECT 2 +--- @field DOTA_HEROPICK_STATE_INTRO_SELECT_UNUSED 3 +--- @field DOTA_HEROPICK_STATE_RD_SELECT_UNUSED 4 +--- @field DOTA_HEROPICK_STATE_CM_INTRO 5 +--- @field DOTA_HEROPICK_STATE_CM_CAPTAINPICK 6 +--- @field DOTA_HEROPICK_STATE_CM_BAN1 7 +--- @field DOTA_HEROPICK_STATE_CM_BAN2 8 +--- @field DOTA_HEROPICK_STATE_CM_BAN3 9 +--- @field DOTA_HEROPICK_STATE_CM_BAN4 10 +--- @field DOTA_HEROPICK_STATE_CM_BAN5 11 +--- @field DOTA_HEROPICK_STATE_CM_BAN6 12 +--- @field DOTA_HEROPICK_STATE_CM_BAN7 13 +--- @field DOTA_HEROPICK_STATE_CM_BAN8 14 +--- @field DOTA_HEROPICK_STATE_CM_BAN9 15 +--- @field DOTA_HEROPICK_STATE_CM_BAN10 16 +--- @field DOTA_HEROPICK_STATE_CM_BAN11 17 +--- @field DOTA_HEROPICK_STATE_CM_BAN12 18 +--- @field DOTA_HEROPICK_STATE_CM_BAN13 19 +--- @field DOTA_HEROPICK_STATE_CM_BAN14 20 +--- @field DOTA_HEROPICK_STATE_CM_SELECT1 21 +--- @field DOTA_HEROPICK_STATE_CM_SELECT2 22 +--- @field DOTA_HEROPICK_STATE_CM_SELECT3 23 +--- @field DOTA_HEROPICK_STATE_CM_SELECT4 24 +--- @field DOTA_HEROPICK_STATE_CM_SELECT5 25 +--- @field DOTA_HEROPICK_STATE_CM_SELECT6 26 +--- @field DOTA_HEROPICK_STATE_CM_SELECT7 27 +--- @field DOTA_HEROPICK_STATE_CM_SELECT8 28 +--- @field DOTA_HEROPICK_STATE_CM_SELECT9 29 +--- @field DOTA_HEROPICK_STATE_CM_SELECT10 30 +--- @field DOTA_HEROPICK_STATE_CM_PICK 31 +--- @field DOTA_HEROPICK_STATE_AR_SELECT 32 +--- @field DOTA_HEROPICK_STATE_MO_SELECT 33 +--- @field DOTA_HEROPICK_STATE_FH_SELECT 34 +--- @field DOTA_HEROPICK_STATE_CD_INTRO 35 +--- @field DOTA_HEROPICK_STATE_CD_CAPTAINPICK 36 +--- @field DOTA_HEROPICK_STATE_CD_BAN1 37 +--- @field DOTA_HEROPICK_STATE_CD_BAN2 38 +--- @field DOTA_HEROPICK_STATE_CD_BAN3 39 +--- @field DOTA_HEROPICK_STATE_CD_BAN4 40 +--- @field DOTA_HEROPICK_STATE_CD_BAN5 41 +--- @field DOTA_HEROPICK_STATE_CD_BAN6 42 +--- @field DOTA_HEROPICK_STATE_CD_SELECT1 43 +--- @field DOTA_HEROPICK_STATE_CD_SELECT2 44 +--- @field DOTA_HEROPICK_STATE_CD_SELECT3 45 +--- @field DOTA_HEROPICK_STATE_CD_SELECT4 46 +--- @field DOTA_HEROPICK_STATE_CD_SELECT5 47 +--- @field DOTA_HEROPICK_STATE_CD_SELECT6 48 +--- @field DOTA_HEROPICK_STATE_CD_SELECT7 49 +--- @field DOTA_HEROPICK_STATE_CD_SELECT8 50 +--- @field DOTA_HEROPICK_STATE_CD_SELECT9 51 +--- @field DOTA_HEROPICK_STATE_CD_SELECT10 52 +--- @field DOTA_HEROPICK_STATE_CD_PICK 53 +--- @field DOTA_HEROPICK_STATE_BD_SELECT 54 +--- @field DOTA_HERO_PICK_STATE_ABILITY_DRAFT_SELECT 55 +--- @field DOTA_HERO_PICK_STATE_ARDM_SELECT 56 +--- @field DOTA_HEROPICK_STATE_ALL_DRAFT_SELECT 57 +--- @field DOTA_HERO_PICK_STATE_CUSTOMGAME_SELECT 58 +--- @field DOTA_HEROPICK_STATE_SELECT_PENALTY 59 +--- @field DOTA_HEROPICK_STATE_CUSTOM_PICK_RULES 60 +--- @field DOTA_HEROPICK_STATE_SCENARIO_PICK 61 +--- @field DOTA_HEROPICK_STATE_COUNT 62 +local DOTA_HeroPickState = {} +DOTA_HEROPICK_STATE_NONE = DOTA_HeroPickState.DOTA_HEROPICK_STATE_NONE +DOTA_HEROPICK_STATE_AP_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_AP_SELECT +DOTA_HEROPICK_STATE_SD_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_SD_SELECT +DOTA_HEROPICK_STATE_INTRO_SELECT_UNUSED = DOTA_HeroPickState.DOTA_HEROPICK_STATE_INTRO_SELECT_UNUSED +DOTA_HEROPICK_STATE_RD_SELECT_UNUSED = DOTA_HeroPickState.DOTA_HEROPICK_STATE_RD_SELECT_UNUSED +DOTA_HEROPICK_STATE_CM_INTRO = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_INTRO +DOTA_HEROPICK_STATE_CM_CAPTAINPICK = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_CAPTAINPICK +DOTA_HEROPICK_STATE_CM_BAN1 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN1 +DOTA_HEROPICK_STATE_CM_BAN2 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN2 +DOTA_HEROPICK_STATE_CM_BAN3 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN3 +DOTA_HEROPICK_STATE_CM_BAN4 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN4 +DOTA_HEROPICK_STATE_CM_BAN5 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN5 +DOTA_HEROPICK_STATE_CM_BAN6 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN6 +DOTA_HEROPICK_STATE_CM_BAN7 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN7 +DOTA_HEROPICK_STATE_CM_BAN8 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN8 +DOTA_HEROPICK_STATE_CM_BAN9 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN9 +DOTA_HEROPICK_STATE_CM_BAN10 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN10 +DOTA_HEROPICK_STATE_CM_BAN11 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN11 +DOTA_HEROPICK_STATE_CM_BAN12 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN12 +DOTA_HEROPICK_STATE_CM_BAN13 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN13 +DOTA_HEROPICK_STATE_CM_BAN14 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_BAN14 +DOTA_HEROPICK_STATE_CM_SELECT1 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT1 +DOTA_HEROPICK_STATE_CM_SELECT2 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT2 +DOTA_HEROPICK_STATE_CM_SELECT3 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT3 +DOTA_HEROPICK_STATE_CM_SELECT4 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT4 +DOTA_HEROPICK_STATE_CM_SELECT5 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT5 +DOTA_HEROPICK_STATE_CM_SELECT6 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT6 +DOTA_HEROPICK_STATE_CM_SELECT7 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT7 +DOTA_HEROPICK_STATE_CM_SELECT8 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT8 +DOTA_HEROPICK_STATE_CM_SELECT9 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT9 +DOTA_HEROPICK_STATE_CM_SELECT10 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_SELECT10 +DOTA_HEROPICK_STATE_CM_PICK = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CM_PICK +DOTA_HEROPICK_STATE_AR_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_AR_SELECT +DOTA_HEROPICK_STATE_MO_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_MO_SELECT +DOTA_HEROPICK_STATE_FH_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_FH_SELECT +DOTA_HEROPICK_STATE_CD_INTRO = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_INTRO +DOTA_HEROPICK_STATE_CD_CAPTAINPICK = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_CAPTAINPICK +DOTA_HEROPICK_STATE_CD_BAN1 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_BAN1 +DOTA_HEROPICK_STATE_CD_BAN2 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_BAN2 +DOTA_HEROPICK_STATE_CD_BAN3 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_BAN3 +DOTA_HEROPICK_STATE_CD_BAN4 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_BAN4 +DOTA_HEROPICK_STATE_CD_BAN5 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_BAN5 +DOTA_HEROPICK_STATE_CD_BAN6 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_BAN6 +DOTA_HEROPICK_STATE_CD_SELECT1 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT1 +DOTA_HEROPICK_STATE_CD_SELECT2 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT2 +DOTA_HEROPICK_STATE_CD_SELECT3 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT3 +DOTA_HEROPICK_STATE_CD_SELECT4 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT4 +DOTA_HEROPICK_STATE_CD_SELECT5 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT5 +DOTA_HEROPICK_STATE_CD_SELECT6 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT6 +DOTA_HEROPICK_STATE_CD_SELECT7 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT7 +DOTA_HEROPICK_STATE_CD_SELECT8 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT8 +DOTA_HEROPICK_STATE_CD_SELECT9 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT9 +DOTA_HEROPICK_STATE_CD_SELECT10 = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_SELECT10 +DOTA_HEROPICK_STATE_CD_PICK = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CD_PICK +DOTA_HEROPICK_STATE_BD_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_BD_SELECT +DOTA_HERO_PICK_STATE_ABILITY_DRAFT_SELECT = DOTA_HeroPickState.DOTA_HERO_PICK_STATE_ABILITY_DRAFT_SELECT +DOTA_HERO_PICK_STATE_ARDM_SELECT = DOTA_HeroPickState.DOTA_HERO_PICK_STATE_ARDM_SELECT +DOTA_HEROPICK_STATE_ALL_DRAFT_SELECT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_ALL_DRAFT_SELECT +DOTA_HERO_PICK_STATE_CUSTOMGAME_SELECT = DOTA_HeroPickState.DOTA_HERO_PICK_STATE_CUSTOMGAME_SELECT +DOTA_HEROPICK_STATE_SELECT_PENALTY = DOTA_HeroPickState.DOTA_HEROPICK_STATE_SELECT_PENALTY +DOTA_HEROPICK_STATE_CUSTOM_PICK_RULES = DOTA_HeroPickState.DOTA_HEROPICK_STATE_CUSTOM_PICK_RULES +DOTA_HEROPICK_STATE_SCENARIO_PICK = DOTA_HeroPickState.DOTA_HEROPICK_STATE_SCENARIO_PICK +DOTA_HEROPICK_STATE_COUNT = DOTA_HeroPickState.DOTA_HEROPICK_STATE_COUNT --- (availability: server & client) ---- @alias DOTA_INVALID_ORDERS ---- | `DOTA_ORDER_SUCCESS` ---- | `DOTA_INVALID_ORDER_NOT_CONTROLLABLE_BY_PLAYER` ---- | `DOTA_INVALID_ORDER_UNIT_IS_NOT_NPC` ---- | `DOTA_INVALID_ORDER_BAD_ABILITY_ENTITY` ---- | `DOTA_INVALID_ORDER_UNRECOGNIZED_ORDER` ---- | `DOTA_INVALID_ORDER_ABILITY_REQUIRED` ---- | `DOTA_INVALID_ORDER_NPC_TARGET_REQUIRED` ---- | `DOTA_INVALID_ORDER_TARGET_TREE_INDEX_NOT_A_TREE` ---- | `DOTA_INVALID_ORDER_TARGET_ENTITY_INDEX_OUT_OF_RANGE` ---- | `DOTA_INVALID_ORDER_ABILITY_NOT_AN_ITEM` ---- | `DOTA_INVALID_ORDER_PHYSICAL_ITEM_TARGET_REQUIRED` ---- | `DOTA_INVALID_ORDER_RUNE_TARGET_REQUIRED` ---- | `DOTA_INVALID_ORDER_ABILITY_NOT_OWNED_BY_UNIT` ---- | `DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED` ---- | `DOTA_INVALID_ORDER_NO_POINTS_FOR_ABILITY_UPGRADE` ---- | `DOTA_INVALID_ORDER_NOT_ENOUGH_MANA` ---- | `DOTA_INVALID_ORDER_ABILITY_IN_COOLDOWN` ---- | `DOTA_INVALID_ORDER_ABILITY_NOT_LEARNED` ---- | `DOTA_INVALID_ORDER_CANT_CAST_PASSIVE_ABILITY` ---- | `DOTA_INVALID_ORDER_PHANTOM_TARGET` ---- | `DOTA_INVALID_ORDER_DEAD_TARGET` ---- | `DOTA_INVALID_ORDER_UNIT_IS_DEAD` ---- | `DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ENEMY` ---- | `DOTA_INVALID_ORDER_TARGET_INVULNERABLE` ---- | `DOTA_INVALID_ORDER_TARGET_ATTACK_IMMUNE` ---- | `DOTA_INVALID_ORDER_UNIT_SILENCED` ---- | `DOTA_INVALID_ORDER_ABILITY_CANT_BE_TOGGLED` ---- | `DOTA_INVALID_ORDER_TARGET_CANT_BE_SEEN` ---- | `DOTA_INVALID_ORDER_TARGET_INVISIBLE` ---- | `DOTA_INVALID_ORDER_HERO_CANT_BE_DENIED` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_TEAMMATE` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_ENEMY` ---- | `DOTA_INVALID_ORDER_UNIT_CANT_MOVE` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_ATTACK_IMMUNE` ---- | `DOTA_INVALID_ORDER_PURCHASE_INVALID_ITEM` ---- | `DOTA_INVALID_ORDER_ITEM_NOT_IN_INVENTORY` ---- | `DOTA_INVALID_ORDER_ITEM_NOT_IN_UNIT_INVENTORY` ---- | `DOTA_INVALID_ORDER_TARGET_UNSELECTABLE` ---- | `DOTA_INVALID_ORDER_ITEM_NOT_IN_ACTIVE_INVENTORY` ---- | `DOTA_INVALID_ORDER_UNIT_CANT_PICK_UP_RUNES` ---- | `DOTA_INVALID_ORDER_UNIT_CANT_MANIPULATE_ITEMS` ---- | `DOTA_INVALID_ORDER_UNIT_IS_ILLUSION` ---- | `DOTA_INVALID_ORDER_UNIT_CANT_ATTACK` ---- | `DOTA_INVALID_ORDER_ITEM_CANT_BE_DROPPED` ---- | `DOTA_INVALID_ORDER_TARGET_TREE_NOT_ACTIVE` ---- | `DOTA_INVALID_ORDER_ABILITY_CANT_AUTO_CAST` ---- | `DOTA_INVALID_ORDER_TARGET_POSITION_OFF_MAP` ---- | `DOTA_INVALID_ORDER_UNIT_CANT_MOVE_TARGET_OUT_OF_RANGE` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_HERO` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_OTHER` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_BUILDING` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_ANCIENT` ---- | `DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_STASH` ---- | `DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_SLOT` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_MECHANICAL` ---- | `DOTA_INVALID_ORDER_CANT_ACCEPT_ATTACK_TARGET` ---- | `DOTA_INVALID_ORDER_CANT_CAST_NO_CHARGES` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_CREEP` ---- | `DOTA_INVALID_ORDER_TARGET_CANT_TAKE_ITEMS` ---- | `DOTA_INVALID_ORDER_CANT_GIVE_ITEM_TO_ENEMY` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_COURIER` ---- | `DOTA_INVALID_ORDER_ABILITY_IS_HIDDEN` ---- | `DOTA_INVALID_ORDER_ITEM_IN_COOLDOWN` ---- | `DOTA_INVALID_ORDER_SECRET_SHOP_NOT_IN_RANGE` ---- | `DOTA_INVALID_ORDER_NOT_ENOUGH_GOLD` ---- | `DOTA_INVALID_ORDER_PURCHASE_AUTOCOMBINE_RECIPE` ---- | `DOTA_INVALID_ORDER_CANT_DENY_HEALTH_TOO_HIGH` ---- | `DOTA_INVALID_ORDER_SIDE_SHOP_NOT_IN_RANGE` ---- | `DOTA_INVALID_ORDER_HOME_SHOP_NOT_IN_RANGE` ---- | `DOTA_INVALID_ORDER_CANT_PICK_UP_ITEM` ---- | `DOTA_INVALID_ORDER_CANT_SELL_NO_SHOP_IN_RANGE` ---- | `DOTA_INVALID_ORDER_CANT_SELL_ITEM` ---- | `DOTA_INVALID_ORDER_CANT_SELL_ITEM_WHILE_DEAD` ---- | `DOTA_INVALID_ORDER_TARGET_CANT_BE_DENIED` ---- | `DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_ROOT` ---- | `DOTA_INVALID_ORDER_UNIT_COMMAND_RESTRICTED` ---- | `DOTA_INVALID_ORDER_UNIT_MUTED` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_SUMMONED` ---- | `DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ALLY` ---- | `DOTA_INVALID_ORDER_CANT_PURCHASE_DISALLOWED_ITEM` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_DOMINATED` ---- | `DOTA_INVALID_ORDER_CAST_CUSTOM` ---- | `DOTA_INVALID_ORDER_ITEM_NOT_DISASSEMBLABLE` ---- | `DOTA_INVALID_ORDER_ITEM_OUT_OF_STOCK` ---- | `DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED_AT_MAX` ---- | `DOTA_INVALID_ORDER_ABILITY_INACTIVE` ---- | `DOTA_INVALID_ORDER_ITEM_NOT_IN_MAIN_INVENTORY` ---- | `DOTA_INVALID_ORDER_CANT_GLYPH` ---- | `DOTA_INVALID_ORDER_CANT_DRAG_CHANNELING_ITEM` ---- | `DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_A_HERO` ---- | `DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_DEAD` ---- | `DOTA_INVALID_ORDER_CANT_BUYBACK_NOT_ENOUGH_GOLD` ---- | `DOTA_INVALID_ORDER_CANT_BUYBACK_IN_COOLDOWN` ---- | `DOTA_INVALID_ORDER_CANT_DISASSEMBLE_STASH_OUT_OF_RANGE` ---- | `DOTA_INVALID_ORDER_CANT_EJECT_ITEM_NOT_IN_STASH` ---- | `DOTA_INVALID_ORDER_GAME_IS_PAUSED` ---- | `DOTA_INVALID_ORDER_CANT_CAST_ON_CONSIDERED_HERO` ---- | `DOTA_INVALID_ORDER_CANT_SHOP_AUTO_BUY_ENABLED` ---- | `DOTA_INVALID_ORDER_ONLY_DELIBERATE_CHANNELING_CANCEL` ---- | `DOTA_INVALID_ORDER_CANT_BUYBACK_REAPERS_SCYTHE` ---- | `DOTA_INVALID_ORDER_CANT_BUYBACK_DISABLED_BY_GAME_MODE` ---- | `DOTA_INVALID_ORDER_CANT_ABILITY_PING_BAD_TEAM` ---- | `DOTA_INVALID_ORDER_ABILITY_NOT_POSITIONED` ---- | `DOTA_INVALID_ORDER_ABILITY_NOT_TARGETTED` ---- | `DOTA_INVALID_ORDER_ABILITY_REQUIRES_TARGET` ---- | `DOTA_INVALID_ORDER_CANT_RADAR` ---- | `DOTA_INVALID_ORDER_NO_COURIER` ---- | `DOTA_INVALID_ORDER_CUSTOM_SHOP_NOT_IN_RANGE` ---- | `DOTA_INVALID_ORDER_CANT_CAST_RIVER_PAINT` ---- | `DOTA_INVALID_ORDER_UNIT_OBSTRUCTED` ---- | `DOTA_INVALID_ORDER_CANT_CAST_DRAG_REQUIRED` ---- | `DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_TETHER` ---- | `DOTA_INVALID_ORDER_ABILITY_NOT_UNLOCKED` ---- | `DOTA_INVALID_ORDER_CANT_FOUNTAIN_DROP_UNIT_NOT_DEAD` ---- | `DOTA_INVALID_ORDER_ITEM_NOT_IN_NEUTRAL_ITEM_STASH` ---- | `DOTA_INVALID_ORDER_ITEM_ALREADY_PURCHASED` ---- | `DOTA_INVALID_ORDER_BEYOND_PHYSICAL_ITEM_LIMIT` ---- | `DOTA_INVALID_ORDER_ABILITY_PING_DEAD_ALLY` ---- | `DOTA_INVALID_ORDER_CANT_LOCKCOMBINE_NEUTRAL_ITEMS` ---- | `DOTA_INVALID_ORDER_ABILITY_CANT_ALT_CAST` ---- | `DOTA_INVALID_ORDER_COUNT` - ---- @type DOTA_INVALID_ORDERS -DOTA_ORDER_SUCCESS = -1 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_NOT_CONTROLLABLE_BY_PLAYER = 0 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_IS_NOT_NPC = 1 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_BAD_ABILITY_ENTITY = 2 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNRECOGNIZED_ORDER = 3 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_REQUIRED = 4 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_NPC_TARGET_REQUIRED = 5 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_TREE_INDEX_NOT_A_TREE = 6 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_ENTITY_INDEX_OUT_OF_RANGE = 7 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_NOT_AN_ITEM = 8 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_PHYSICAL_ITEM_TARGET_REQUIRED = 9 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_RUNE_TARGET_REQUIRED = 10 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_NOT_OWNED_BY_UNIT = 11 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED = 12 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_NO_POINTS_FOR_ABILITY_UPGRADE = 13 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_NOT_ENOUGH_MANA = 14 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_IN_COOLDOWN = 15 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_NOT_LEARNED = 16 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_PASSIVE_ABILITY = 17 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_PHANTOM_TARGET = 18 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_DEAD_TARGET = 19 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_IS_DEAD = 20 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ENEMY = 21 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_INVULNERABLE = 22 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_ATTACK_IMMUNE = 23 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_SILENCED = 24 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_CANT_BE_TOGGLED = 25 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_CANT_BE_SEEN = 26 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_INVISIBLE = 27 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_HERO_CANT_BE_DENIED = 28 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_TEAMMATE = 29 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_ENEMY = 30 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_CANT_MOVE = 31 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_ATTACK_IMMUNE = 32 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_PURCHASE_INVALID_ITEM = 33 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_NOT_IN_INVENTORY = 34 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_NOT_IN_UNIT_INVENTORY = 35 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_UNSELECTABLE = 36 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_NOT_IN_ACTIVE_INVENTORY = 37 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_CANT_PICK_UP_RUNES = 38 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_CANT_MANIPULATE_ITEMS = 39 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_IS_ILLUSION = 40 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_CANT_ATTACK = 41 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_CANT_BE_DROPPED = 42 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_TREE_NOT_ACTIVE = 43 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_CANT_AUTO_CAST = 44 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_POSITION_OFF_MAP = 45 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_CANT_MOVE_TARGET_OUT_OF_RANGE = 46 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_HERO = 47 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_OTHER = 48 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_BUILDING = 49 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_ANCIENT = 50 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_STASH = 51 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_SLOT = 52 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_MECHANICAL = 53 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_ACCEPT_ATTACK_TARGET = 54 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_NO_CHARGES = 55 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_CREEP = 56 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_CANT_TAKE_ITEMS = 57 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_GIVE_ITEM_TO_ENEMY = 58 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_COURIER = 59 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_IS_HIDDEN = 60 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_IN_COOLDOWN = 61 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_SECRET_SHOP_NOT_IN_RANGE = 62 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_NOT_ENOUGH_GOLD = 63 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_PURCHASE_AUTOCOMBINE_RECIPE = 64 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_DENY_HEALTH_TOO_HIGH = 65 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_SIDE_SHOP_NOT_IN_RANGE = 66 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_HOME_SHOP_NOT_IN_RANGE = 67 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_PICK_UP_ITEM = 68 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_SELL_NO_SHOP_IN_RANGE = 69 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_SELL_ITEM = 70 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_SELL_ITEM_WHILE_DEAD = 71 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_CANT_BE_DENIED = 72 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_ROOT = 73 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_COMMAND_RESTRICTED = 74 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_MUTED = 75 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_SUMMONED = 76 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ALLY = 77 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_PURCHASE_DISALLOWED_ITEM = 78 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_DOMINATED = 79 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CAST_CUSTOM = 80 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_NOT_DISASSEMBLABLE = 81 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_OUT_OF_STOCK = 82 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED_AT_MAX = 83 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_INACTIVE = 84 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_NOT_IN_MAIN_INVENTORY = 85 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_GLYPH = 86 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_DRAG_CHANNELING_ITEM = 87 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_A_HERO = 88 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_DEAD = 89 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_BUYBACK_NOT_ENOUGH_GOLD = 90 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_BUYBACK_IN_COOLDOWN = 91 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_DISASSEMBLE_STASH_OUT_OF_RANGE = 92 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_EJECT_ITEM_NOT_IN_STASH = 93 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_GAME_IS_PAUSED = 94 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_ON_CONSIDERED_HERO = 95 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_SHOP_AUTO_BUY_ENABLED = 96 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ONLY_DELIBERATE_CHANNELING_CANCEL = 97 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_BUYBACK_REAPERS_SCYTHE = 98 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_BUYBACK_DISABLED_BY_GAME_MODE = 99 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_ABILITY_PING_BAD_TEAM = 100 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_NOT_POSITIONED = 101 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_NOT_TARGETTED = 102 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_REQUIRES_TARGET = 103 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_RADAR = 104 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_NO_COURIER = 105 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CUSTOM_SHOP_NOT_IN_RANGE = 106 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_RIVER_PAINT = 107 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_UNIT_OBSTRUCTED = 108 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_CAST_DRAG_REQUIRED = 109 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_TETHER = 110 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_NOT_UNLOCKED = 111 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_FOUNTAIN_DROP_UNIT_NOT_DEAD = 112 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_NOT_IN_NEUTRAL_ITEM_STASH = 113 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ITEM_ALREADY_PURCHASED = 114 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_BEYOND_PHYSICAL_ITEM_LIMIT = 115 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_PING_DEAD_ALLY = 116 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_CANT_LOCKCOMBINE_NEUTRAL_ITEMS = 117 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_ABILITY_CANT_ALT_CAST = 118 ---- @type DOTA_INVALID_ORDERS -DOTA_INVALID_ORDER_COUNT = 119 +--- @enum DOTA_INVALID_ORDERS +--- @field DOTA_ORDER_SUCCESS -1 +--- @field DOTA_INVALID_ORDER_NOT_CONTROLLABLE_BY_PLAYER 0 +--- @field DOTA_INVALID_ORDER_UNIT_IS_NOT_NPC 1 +--- @field DOTA_INVALID_ORDER_BAD_ABILITY_ENTITY 2 +--- @field DOTA_INVALID_ORDER_UNRECOGNIZED_ORDER 3 +--- @field DOTA_INVALID_ORDER_ABILITY_REQUIRED 4 +--- @field DOTA_INVALID_ORDER_NPC_TARGET_REQUIRED 5 +--- @field DOTA_INVALID_ORDER_TARGET_TREE_INDEX_NOT_A_TREE 6 +--- @field DOTA_INVALID_ORDER_TARGET_ENTITY_INDEX_OUT_OF_RANGE 7 +--- @field DOTA_INVALID_ORDER_ABILITY_NOT_AN_ITEM 8 +--- @field DOTA_INVALID_ORDER_PHYSICAL_ITEM_TARGET_REQUIRED 9 +--- @field DOTA_INVALID_ORDER_RUNE_TARGET_REQUIRED 10 +--- @field DOTA_INVALID_ORDER_ABILITY_NOT_OWNED_BY_UNIT 11 +--- @field DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED 12 +--- @field DOTA_INVALID_ORDER_NO_POINTS_FOR_ABILITY_UPGRADE 13 +--- @field DOTA_INVALID_ORDER_NOT_ENOUGH_MANA 14 +--- @field DOTA_INVALID_ORDER_ABILITY_IN_COOLDOWN 15 +--- @field DOTA_INVALID_ORDER_ABILITY_NOT_LEARNED 16 +--- @field DOTA_INVALID_ORDER_CANT_CAST_PASSIVE_ABILITY 17 +--- @field DOTA_INVALID_ORDER_PHANTOM_TARGET 18 +--- @field DOTA_INVALID_ORDER_DEAD_TARGET 19 +--- @field DOTA_INVALID_ORDER_UNIT_IS_DEAD 20 +--- @field DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ENEMY 21 +--- @field DOTA_INVALID_ORDER_TARGET_INVULNERABLE 22 +--- @field DOTA_INVALID_ORDER_TARGET_ATTACK_IMMUNE 23 +--- @field DOTA_INVALID_ORDER_UNIT_SILENCED 24 +--- @field DOTA_INVALID_ORDER_ABILITY_CANT_BE_TOGGLED 25 +--- @field DOTA_INVALID_ORDER_TARGET_CANT_BE_SEEN 26 +--- @field DOTA_INVALID_ORDER_TARGET_INVISIBLE 27 +--- @field DOTA_INVALID_ORDER_HERO_CANT_BE_DENIED 28 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_TEAMMATE 29 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_ENEMY 30 +--- @field DOTA_INVALID_ORDER_UNIT_CANT_MOVE 31 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_ATTACK_IMMUNE 32 +--- @field DOTA_INVALID_ORDER_PURCHASE_INVALID_ITEM 33 +--- @field DOTA_INVALID_ORDER_ITEM_NOT_IN_INVENTORY 34 +--- @field DOTA_INVALID_ORDER_ITEM_NOT_IN_UNIT_INVENTORY 35 +--- @field DOTA_INVALID_ORDER_TARGET_UNSELECTABLE 36 +--- @field DOTA_INVALID_ORDER_ITEM_NOT_IN_ACTIVE_INVENTORY 37 +--- @field DOTA_INVALID_ORDER_UNIT_CANT_PICK_UP_RUNES 38 +--- @field DOTA_INVALID_ORDER_UNIT_CANT_MANIPULATE_ITEMS 39 +--- @field DOTA_INVALID_ORDER_UNIT_IS_ILLUSION 40 +--- @field DOTA_INVALID_ORDER_UNIT_CANT_ATTACK 41 +--- @field DOTA_INVALID_ORDER_ITEM_CANT_BE_DROPPED 42 +--- @field DOTA_INVALID_ORDER_TARGET_TREE_NOT_ACTIVE 43 +--- @field DOTA_INVALID_ORDER_ABILITY_CANT_AUTO_CAST 44 +--- @field DOTA_INVALID_ORDER_TARGET_POSITION_OFF_MAP 45 +--- @field DOTA_INVALID_ORDER_UNIT_CANT_MOVE_TARGET_OUT_OF_RANGE 46 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_HERO 47 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_OTHER 48 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_BUILDING 49 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_ANCIENT 50 +--- @field DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_STASH 51 +--- @field DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_SLOT 52 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_MECHANICAL 53 +--- @field DOTA_INVALID_ORDER_CANT_ACCEPT_ATTACK_TARGET 54 +--- @field DOTA_INVALID_ORDER_CANT_CAST_NO_CHARGES 55 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_CREEP 56 +--- @field DOTA_INVALID_ORDER_TARGET_CANT_TAKE_ITEMS 57 +--- @field DOTA_INVALID_ORDER_CANT_GIVE_ITEM_TO_ENEMY 58 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_COURIER 59 +--- @field DOTA_INVALID_ORDER_ABILITY_IS_HIDDEN 60 +--- @field DOTA_INVALID_ORDER_ITEM_IN_COOLDOWN 61 +--- @field DOTA_INVALID_ORDER_SECRET_SHOP_NOT_IN_RANGE 62 +--- @field DOTA_INVALID_ORDER_NOT_ENOUGH_GOLD 63 +--- @field DOTA_INVALID_ORDER_PURCHASE_AUTOCOMBINE_RECIPE 64 +--- @field DOTA_INVALID_ORDER_CANT_DENY_HEALTH_TOO_HIGH 65 +--- @field DOTA_INVALID_ORDER_SIDE_SHOP_NOT_IN_RANGE 66 +--- @field DOTA_INVALID_ORDER_HOME_SHOP_NOT_IN_RANGE 67 +--- @field DOTA_INVALID_ORDER_CANT_PICK_UP_ITEM 68 +--- @field DOTA_INVALID_ORDER_CANT_SELL_NO_SHOP_IN_RANGE 69 +--- @field DOTA_INVALID_ORDER_CANT_SELL_ITEM 70 +--- @field DOTA_INVALID_ORDER_CANT_SELL_ITEM_WHILE_DEAD 71 +--- @field DOTA_INVALID_ORDER_TARGET_CANT_BE_DENIED 72 +--- @field DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_ROOT 73 +--- @field DOTA_INVALID_ORDER_UNIT_COMMAND_RESTRICTED 74 +--- @field DOTA_INVALID_ORDER_UNIT_MUTED 75 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_SUMMONED 76 +--- @field DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ALLY 77 +--- @field DOTA_INVALID_ORDER_CANT_PURCHASE_DISALLOWED_ITEM 78 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_DOMINATED 79 +--- @field DOTA_INVALID_ORDER_CAST_CUSTOM 80 +--- @field DOTA_INVALID_ORDER_ITEM_NOT_DISASSEMBLABLE 81 +--- @field DOTA_INVALID_ORDER_ITEM_OUT_OF_STOCK 82 +--- @field DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED_AT_MAX 83 +--- @field DOTA_INVALID_ORDER_ABILITY_INACTIVE 84 +--- @field DOTA_INVALID_ORDER_ITEM_NOT_IN_MAIN_INVENTORY 85 +--- @field DOTA_INVALID_ORDER_CANT_GLYPH 86 +--- @field DOTA_INVALID_ORDER_CANT_DRAG_CHANNELING_ITEM 87 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_A_HERO 88 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_DEAD 89 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_NOT_ENOUGH_GOLD 90 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_IN_COOLDOWN 91 +--- @field DOTA_INVALID_ORDER_CANT_DISASSEMBLE_STASH_OUT_OF_RANGE 92 +--- @field DOTA_INVALID_ORDER_CANT_EJECT_ITEM_NOT_IN_STASH 93 +--- @field DOTA_INVALID_ORDER_GAME_IS_PAUSED 94 +--- @field DOTA_INVALID_ORDER_CANT_CAST_ON_CONSIDERED_HERO 95 +--- @field DOTA_INVALID_ORDER_CANT_SHOP_AUTO_BUY_ENABLED 96 +--- @field DOTA_INVALID_ORDER_ONLY_DELIBERATE_CHANNELING_CANCEL 97 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_REAPERS_SCYTHE 98 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_DISABLED_BY_GAME_MODE 99 +--- @field DOTA_INVALID_ORDER_CANT_ABILITY_PING_BAD_TEAM 100 +--- @field DOTA_INVALID_ORDER_ABILITY_NOT_POSITIONED 101 +--- @field DOTA_INVALID_ORDER_ABILITY_NOT_TARGETTED 102 +--- @field DOTA_INVALID_ORDER_ABILITY_REQUIRES_TARGET 103 +--- @field DOTA_INVALID_ORDER_CANT_RADAR 104 +--- @field DOTA_INVALID_ORDER_NO_COURIER 105 +--- @field DOTA_INVALID_ORDER_CUSTOM_SHOP_NOT_IN_RANGE 106 +--- @field DOTA_INVALID_ORDER_CANT_CAST_RIVER_PAINT 107 +--- @field DOTA_INVALID_ORDER_UNIT_OBSTRUCTED 108 +--- @field DOTA_INVALID_ORDER_CANT_CAST_DRAG_REQUIRED 109 +--- @field DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_TETHER 110 +--- @field DOTA_INVALID_ORDER_ABILITY_NOT_UNLOCKED 111 +--- @field DOTA_INVALID_ORDER_CANT_FOUNTAIN_DROP_UNIT_NOT_DEAD 112 +--- @field DOTA_INVALID_ORDER_ITEM_NOT_IN_NEUTRAL_ITEM_STASH 113 +--- @field DOTA_INVALID_ORDER_ITEM_ALREADY_PURCHASED 114 +--- @field DOTA_INVALID_ORDER_BEYOND_PHYSICAL_ITEM_LIMIT 115 +--- @field DOTA_INVALID_ORDER_ABILITY_PING_DEAD_ALLY 116 +--- @field DOTA_INVALID_ORDER_CANT_LOCKCOMBINE_NEUTRAL_ITEMS 117 +--- @field DOTA_INVALID_ORDER_ABILITY_CANT_ALT_CAST 118 +--- @field DOTA_INVALID_ORDER_ITEM_CANNOT_BE_CONSUMED 119 +--- @field DOTA_INVALID_ORDER_CANT_BUYBACK_CEASELESS_DIRGE 120 +--- @field DOTA_INVALID_ORDER_CANT_ATTACK_BUILDINGS 121 +--- @field DOTA_INVALID_ORDER_COUNT 122 +local DOTA_INVALID_ORDERS = {} +DOTA_ORDER_SUCCESS = DOTA_INVALID_ORDERS.DOTA_ORDER_SUCCESS +DOTA_INVALID_ORDER_NOT_CONTROLLABLE_BY_PLAYER = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_NOT_CONTROLLABLE_BY_PLAYER +DOTA_INVALID_ORDER_UNIT_IS_NOT_NPC = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_IS_NOT_NPC +DOTA_INVALID_ORDER_BAD_ABILITY_ENTITY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_BAD_ABILITY_ENTITY +DOTA_INVALID_ORDER_UNRECOGNIZED_ORDER = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNRECOGNIZED_ORDER +DOTA_INVALID_ORDER_ABILITY_REQUIRED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_REQUIRED +DOTA_INVALID_ORDER_NPC_TARGET_REQUIRED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_NPC_TARGET_REQUIRED +DOTA_INVALID_ORDER_TARGET_TREE_INDEX_NOT_A_TREE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_TREE_INDEX_NOT_A_TREE +DOTA_INVALID_ORDER_TARGET_ENTITY_INDEX_OUT_OF_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_ENTITY_INDEX_OUT_OF_RANGE +DOTA_INVALID_ORDER_ABILITY_NOT_AN_ITEM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_NOT_AN_ITEM +DOTA_INVALID_ORDER_PHYSICAL_ITEM_TARGET_REQUIRED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_PHYSICAL_ITEM_TARGET_REQUIRED +DOTA_INVALID_ORDER_RUNE_TARGET_REQUIRED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_RUNE_TARGET_REQUIRED +DOTA_INVALID_ORDER_ABILITY_NOT_OWNED_BY_UNIT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_NOT_OWNED_BY_UNIT +DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED +DOTA_INVALID_ORDER_NO_POINTS_FOR_ABILITY_UPGRADE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_NO_POINTS_FOR_ABILITY_UPGRADE +DOTA_INVALID_ORDER_NOT_ENOUGH_MANA = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_NOT_ENOUGH_MANA +DOTA_INVALID_ORDER_ABILITY_IN_COOLDOWN = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_IN_COOLDOWN +DOTA_INVALID_ORDER_ABILITY_NOT_LEARNED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_NOT_LEARNED +DOTA_INVALID_ORDER_CANT_CAST_PASSIVE_ABILITY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_PASSIVE_ABILITY +DOTA_INVALID_ORDER_PHANTOM_TARGET = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_PHANTOM_TARGET +DOTA_INVALID_ORDER_DEAD_TARGET = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_DEAD_TARGET +DOTA_INVALID_ORDER_UNIT_IS_DEAD = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_IS_DEAD +DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ENEMY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ENEMY +DOTA_INVALID_ORDER_TARGET_INVULNERABLE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_INVULNERABLE +DOTA_INVALID_ORDER_TARGET_ATTACK_IMMUNE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_ATTACK_IMMUNE +DOTA_INVALID_ORDER_UNIT_SILENCED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_SILENCED +DOTA_INVALID_ORDER_ABILITY_CANT_BE_TOGGLED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_CANT_BE_TOGGLED +DOTA_INVALID_ORDER_TARGET_CANT_BE_SEEN = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_CANT_BE_SEEN +DOTA_INVALID_ORDER_TARGET_INVISIBLE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_INVISIBLE +DOTA_INVALID_ORDER_HERO_CANT_BE_DENIED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_HERO_CANT_BE_DENIED +DOTA_INVALID_ORDER_CANT_CAST_ON_TEAMMATE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_TEAMMATE +DOTA_INVALID_ORDER_CANT_CAST_ON_ENEMY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_ENEMY +DOTA_INVALID_ORDER_UNIT_CANT_MOVE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_CANT_MOVE +DOTA_INVALID_ORDER_CANT_CAST_ON_ATTACK_IMMUNE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_ATTACK_IMMUNE +DOTA_INVALID_ORDER_PURCHASE_INVALID_ITEM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_PURCHASE_INVALID_ITEM +DOTA_INVALID_ORDER_ITEM_NOT_IN_INVENTORY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_NOT_IN_INVENTORY +DOTA_INVALID_ORDER_ITEM_NOT_IN_UNIT_INVENTORY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_NOT_IN_UNIT_INVENTORY +DOTA_INVALID_ORDER_TARGET_UNSELECTABLE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_UNSELECTABLE +DOTA_INVALID_ORDER_ITEM_NOT_IN_ACTIVE_INVENTORY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_NOT_IN_ACTIVE_INVENTORY +DOTA_INVALID_ORDER_UNIT_CANT_PICK_UP_RUNES = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_CANT_PICK_UP_RUNES +DOTA_INVALID_ORDER_UNIT_CANT_MANIPULATE_ITEMS = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_CANT_MANIPULATE_ITEMS +DOTA_INVALID_ORDER_UNIT_IS_ILLUSION = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_IS_ILLUSION +DOTA_INVALID_ORDER_UNIT_CANT_ATTACK = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_CANT_ATTACK +DOTA_INVALID_ORDER_ITEM_CANT_BE_DROPPED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_CANT_BE_DROPPED +DOTA_INVALID_ORDER_TARGET_TREE_NOT_ACTIVE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_TREE_NOT_ACTIVE +DOTA_INVALID_ORDER_ABILITY_CANT_AUTO_CAST = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_CANT_AUTO_CAST +DOTA_INVALID_ORDER_TARGET_POSITION_OFF_MAP = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_POSITION_OFF_MAP +DOTA_INVALID_ORDER_UNIT_CANT_MOVE_TARGET_OUT_OF_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_CANT_MOVE_TARGET_OUT_OF_RANGE +DOTA_INVALID_ORDER_CANT_CAST_ON_HERO = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_HERO +DOTA_INVALID_ORDER_CANT_CAST_ON_OTHER = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_OTHER +DOTA_INVALID_ORDER_CANT_CAST_ON_BUILDING = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_BUILDING +DOTA_INVALID_ORDER_CANT_CAST_ON_ANCIENT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_ANCIENT +DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_STASH = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_STASH +DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_SLOT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_SLOT +DOTA_INVALID_ORDER_CANT_CAST_ON_MECHANICAL = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_MECHANICAL +DOTA_INVALID_ORDER_CANT_ACCEPT_ATTACK_TARGET = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_ACCEPT_ATTACK_TARGET +DOTA_INVALID_ORDER_CANT_CAST_NO_CHARGES = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_NO_CHARGES +DOTA_INVALID_ORDER_CANT_CAST_ON_CREEP = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_CREEP +DOTA_INVALID_ORDER_TARGET_CANT_TAKE_ITEMS = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_CANT_TAKE_ITEMS +DOTA_INVALID_ORDER_CANT_GIVE_ITEM_TO_ENEMY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_GIVE_ITEM_TO_ENEMY +DOTA_INVALID_ORDER_CANT_CAST_ON_COURIER = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_COURIER +DOTA_INVALID_ORDER_ABILITY_IS_HIDDEN = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_IS_HIDDEN +DOTA_INVALID_ORDER_ITEM_IN_COOLDOWN = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_IN_COOLDOWN +DOTA_INVALID_ORDER_SECRET_SHOP_NOT_IN_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_SECRET_SHOP_NOT_IN_RANGE +DOTA_INVALID_ORDER_NOT_ENOUGH_GOLD = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_NOT_ENOUGH_GOLD +DOTA_INVALID_ORDER_PURCHASE_AUTOCOMBINE_RECIPE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_PURCHASE_AUTOCOMBINE_RECIPE +DOTA_INVALID_ORDER_CANT_DENY_HEALTH_TOO_HIGH = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_DENY_HEALTH_TOO_HIGH +DOTA_INVALID_ORDER_SIDE_SHOP_NOT_IN_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_SIDE_SHOP_NOT_IN_RANGE +DOTA_INVALID_ORDER_HOME_SHOP_NOT_IN_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_HOME_SHOP_NOT_IN_RANGE +DOTA_INVALID_ORDER_CANT_PICK_UP_ITEM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_PICK_UP_ITEM +DOTA_INVALID_ORDER_CANT_SELL_NO_SHOP_IN_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_SELL_NO_SHOP_IN_RANGE +DOTA_INVALID_ORDER_CANT_SELL_ITEM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_SELL_ITEM +DOTA_INVALID_ORDER_CANT_SELL_ITEM_WHILE_DEAD = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_SELL_ITEM_WHILE_DEAD +DOTA_INVALID_ORDER_TARGET_CANT_BE_DENIED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_CANT_BE_DENIED +DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_ROOT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_ROOT +DOTA_INVALID_ORDER_UNIT_COMMAND_RESTRICTED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_COMMAND_RESTRICTED +DOTA_INVALID_ORDER_UNIT_MUTED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_MUTED +DOTA_INVALID_ORDER_CANT_CAST_ON_SUMMONED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_SUMMONED +DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ALLY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_TARGET_MAGIC_IMMUNE_ALLY +DOTA_INVALID_ORDER_CANT_PURCHASE_DISALLOWED_ITEM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_PURCHASE_DISALLOWED_ITEM +DOTA_INVALID_ORDER_CANT_CAST_ON_DOMINATED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_DOMINATED +DOTA_INVALID_ORDER_CAST_CUSTOM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CAST_CUSTOM +DOTA_INVALID_ORDER_ITEM_NOT_DISASSEMBLABLE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_NOT_DISASSEMBLABLE +DOTA_INVALID_ORDER_ITEM_OUT_OF_STOCK = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_OUT_OF_STOCK +DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED_AT_MAX = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_CANT_BE_UPGRADED_AT_MAX +DOTA_INVALID_ORDER_ABILITY_INACTIVE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_INACTIVE +DOTA_INVALID_ORDER_ITEM_NOT_IN_MAIN_INVENTORY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_NOT_IN_MAIN_INVENTORY +DOTA_INVALID_ORDER_CANT_GLYPH = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_GLYPH +DOTA_INVALID_ORDER_CANT_DRAG_CHANNELING_ITEM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_DRAG_CHANNELING_ITEM +DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_A_HERO = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_A_HERO +DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_DEAD = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_UNIT_NOT_DEAD +DOTA_INVALID_ORDER_CANT_BUYBACK_NOT_ENOUGH_GOLD = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_NOT_ENOUGH_GOLD +DOTA_INVALID_ORDER_CANT_BUYBACK_IN_COOLDOWN = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_IN_COOLDOWN +DOTA_INVALID_ORDER_CANT_DISASSEMBLE_STASH_OUT_OF_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_DISASSEMBLE_STASH_OUT_OF_RANGE +DOTA_INVALID_ORDER_CANT_EJECT_ITEM_NOT_IN_STASH = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_EJECT_ITEM_NOT_IN_STASH +DOTA_INVALID_ORDER_GAME_IS_PAUSED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_GAME_IS_PAUSED +DOTA_INVALID_ORDER_CANT_CAST_ON_CONSIDERED_HERO = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_ON_CONSIDERED_HERO +DOTA_INVALID_ORDER_CANT_SHOP_AUTO_BUY_ENABLED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_SHOP_AUTO_BUY_ENABLED +DOTA_INVALID_ORDER_ONLY_DELIBERATE_CHANNELING_CANCEL = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ONLY_DELIBERATE_CHANNELING_CANCEL +DOTA_INVALID_ORDER_CANT_BUYBACK_REAPERS_SCYTHE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_REAPERS_SCYTHE +DOTA_INVALID_ORDER_CANT_BUYBACK_DISABLED_BY_GAME_MODE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_DISABLED_BY_GAME_MODE +DOTA_INVALID_ORDER_CANT_ABILITY_PING_BAD_TEAM = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_ABILITY_PING_BAD_TEAM +DOTA_INVALID_ORDER_ABILITY_NOT_POSITIONED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_NOT_POSITIONED +DOTA_INVALID_ORDER_ABILITY_NOT_TARGETTED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_NOT_TARGETTED +DOTA_INVALID_ORDER_ABILITY_REQUIRES_TARGET = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_REQUIRES_TARGET +DOTA_INVALID_ORDER_CANT_RADAR = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_RADAR +DOTA_INVALID_ORDER_NO_COURIER = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_NO_COURIER +DOTA_INVALID_ORDER_CUSTOM_SHOP_NOT_IN_RANGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CUSTOM_SHOP_NOT_IN_RANGE +DOTA_INVALID_ORDER_CANT_CAST_RIVER_PAINT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_RIVER_PAINT +DOTA_INVALID_ORDER_UNIT_OBSTRUCTED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_UNIT_OBSTRUCTED +DOTA_INVALID_ORDER_CANT_CAST_DRAG_REQUIRED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_CAST_DRAG_REQUIRED +DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_TETHER = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_DISABLED_BY_TETHER +DOTA_INVALID_ORDER_ABILITY_NOT_UNLOCKED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_NOT_UNLOCKED +DOTA_INVALID_ORDER_CANT_FOUNTAIN_DROP_UNIT_NOT_DEAD = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_FOUNTAIN_DROP_UNIT_NOT_DEAD +DOTA_INVALID_ORDER_ITEM_NOT_IN_NEUTRAL_ITEM_STASH = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_NOT_IN_NEUTRAL_ITEM_STASH +DOTA_INVALID_ORDER_ITEM_ALREADY_PURCHASED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_ALREADY_PURCHASED +DOTA_INVALID_ORDER_BEYOND_PHYSICAL_ITEM_LIMIT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_BEYOND_PHYSICAL_ITEM_LIMIT +DOTA_INVALID_ORDER_ABILITY_PING_DEAD_ALLY = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_PING_DEAD_ALLY +DOTA_INVALID_ORDER_CANT_LOCKCOMBINE_NEUTRAL_ITEMS = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_LOCKCOMBINE_NEUTRAL_ITEMS +DOTA_INVALID_ORDER_ABILITY_CANT_ALT_CAST = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ABILITY_CANT_ALT_CAST +DOTA_INVALID_ORDER_ITEM_CANNOT_BE_CONSUMED = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_ITEM_CANNOT_BE_CONSUMED +DOTA_INVALID_ORDER_CANT_BUYBACK_CEASELESS_DIRGE = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_BUYBACK_CEASELESS_DIRGE +DOTA_INVALID_ORDER_CANT_ATTACK_BUILDINGS = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_CANT_ATTACK_BUILDINGS +DOTA_INVALID_ORDER_COUNT = DOTA_INVALID_ORDERS.DOTA_INVALID_ORDER_COUNT --- (availability: server & client) ---- @alias DOTA_MOTION_CONTROLLER_PRIORITY ---- | `DOTA_MOTION_CONTROLLER_PRIORITY_LOWEST` ---- | `DOTA_MOTION_CONTROLLER_PRIORITY_LOW` ---- | `DOTA_MOTION_CONTROLLER_PRIORITY_MEDIUM` ---- | `DOTA_MOTION_CONTROLLER_PRIORITY_HIGH` ---- | `DOTA_MOTION_CONTROLLER_PRIORITY_HIGHEST` ---- | `DOTA_MOTION_CONTROLLER_PRIORITY_ULTRA` - ---- @type DOTA_MOTION_CONTROLLER_PRIORITY -DOTA_MOTION_CONTROLLER_PRIORITY_LOWEST = 0 ---- @type DOTA_MOTION_CONTROLLER_PRIORITY -DOTA_MOTION_CONTROLLER_PRIORITY_LOW = 1 ---- @type DOTA_MOTION_CONTROLLER_PRIORITY -DOTA_MOTION_CONTROLLER_PRIORITY_MEDIUM = 2 ---- @type DOTA_MOTION_CONTROLLER_PRIORITY -DOTA_MOTION_CONTROLLER_PRIORITY_HIGH = 3 ---- @type DOTA_MOTION_CONTROLLER_PRIORITY -DOTA_MOTION_CONTROLLER_PRIORITY_HIGHEST = 4 ---- @type DOTA_MOTION_CONTROLLER_PRIORITY -DOTA_MOTION_CONTROLLER_PRIORITY_ULTRA = 5 +--- @enum DOTA_MOTION_CONTROLLER_PRIORITY +--- @field DOTA_MOTION_CONTROLLER_PRIORITY_LOWEST 0 +--- @field DOTA_MOTION_CONTROLLER_PRIORITY_LOW 1 +--- @field DOTA_MOTION_CONTROLLER_PRIORITY_MEDIUM 2 +--- @field DOTA_MOTION_CONTROLLER_PRIORITY_HIGH 3 +--- @field DOTA_MOTION_CONTROLLER_PRIORITY_HIGHEST 4 +--- @field DOTA_MOTION_CONTROLLER_PRIORITY_ULTRA 5 +local DOTA_MOTION_CONTROLLER_PRIORITY = {} +DOTA_MOTION_CONTROLLER_PRIORITY_LOWEST = DOTA_MOTION_CONTROLLER_PRIORITY.DOTA_MOTION_CONTROLLER_PRIORITY_LOWEST +DOTA_MOTION_CONTROLLER_PRIORITY_LOW = DOTA_MOTION_CONTROLLER_PRIORITY.DOTA_MOTION_CONTROLLER_PRIORITY_LOW +DOTA_MOTION_CONTROLLER_PRIORITY_MEDIUM = DOTA_MOTION_CONTROLLER_PRIORITY.DOTA_MOTION_CONTROLLER_PRIORITY_MEDIUM +DOTA_MOTION_CONTROLLER_PRIORITY_HIGH = DOTA_MOTION_CONTROLLER_PRIORITY.DOTA_MOTION_CONTROLLER_PRIORITY_HIGH +DOTA_MOTION_CONTROLLER_PRIORITY_HIGHEST = DOTA_MOTION_CONTROLLER_PRIORITY.DOTA_MOTION_CONTROLLER_PRIORITY_HIGHEST +DOTA_MOTION_CONTROLLER_PRIORITY_ULTRA = DOTA_MOTION_CONTROLLER_PRIORITY.DOTA_MOTION_CONTROLLER_PRIORITY_ULTRA --- (availability: server) ---- @alias DOTA_OVERHEAD_ALERT ---- | `OVERHEAD_ALERT_GOLD` ---- | `OVERHEAD_ALERT_DENY` ---- | `OVERHEAD_ALERT_CRITICAL` ---- | `OVERHEAD_ALERT_XP` ---- | `OVERHEAD_ALERT_BONUS_SPELL_DAMAGE` ---- | `OVERHEAD_ALERT_MISS` ---- | `OVERHEAD_ALERT_DAMAGE` ---- | `OVERHEAD_ALERT_EVADE` ---- | `OVERHEAD_ALERT_BLOCK` ---- | `OVERHEAD_ALERT_BONUS_POISON_DAMAGE` ---- | `OVERHEAD_ALERT_HEAL` ---- | `OVERHEAD_ALERT_MANA_ADD` ---- | `OVERHEAD_ALERT_MANA_LOSS` ---- | `OVERHEAD_ALERT_LAST_HIT_EARLY` ---- | `OVERHEAD_ALERT_LAST_HIT_CLOSE` ---- | `OVERHEAD_ALERT_LAST_HIT_MISS` ---- | `OVERHEAD_ALERT_MAGICAL_BLOCK` ---- | `OVERHEAD_ALERT_INCOMING_DAMAGE` ---- | `OVERHEAD_ALERT_OUTGOING_DAMAGE` ---- | `OVERHEAD_ALERT_DISABLE_RESIST` ---- | `OVERHEAD_ALERT_DEATH` ---- | `OVERHEAD_ALERT_BLOCKED` ---- | `OVERHEAD_ALERT_ITEM_RECEIVED` ---- | `OVERHEAD_ALERT_SHARD` ---- | `OVERHEAD_ALERT_DEADLY_BLOW` - ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_GOLD = 0 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_DENY = 1 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_CRITICAL = 2 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_XP = 3 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_BONUS_SPELL_DAMAGE = 4 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_MISS = 5 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_DAMAGE = 6 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_EVADE = 7 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_BLOCK = 8 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_BONUS_POISON_DAMAGE = 9 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_HEAL = 10 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_MANA_ADD = 11 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_MANA_LOSS = 12 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_LAST_HIT_EARLY = 13 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_LAST_HIT_CLOSE = 14 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_LAST_HIT_MISS = 15 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_MAGICAL_BLOCK = 16 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_INCOMING_DAMAGE = 17 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_OUTGOING_DAMAGE = 18 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_DISABLE_RESIST = 19 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_DEATH = 20 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_BLOCKED = 21 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_ITEM_RECEIVED = 22 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_SHARD = 23 ---- @type DOTA_OVERHEAD_ALERT -OVERHEAD_ALERT_DEADLY_BLOW = 24 +--- @enum DOTA_OVERHEAD_ALERT +--- @field OVERHEAD_ALERT_GOLD 0 +--- @field OVERHEAD_ALERT_DENY 1 +--- @field OVERHEAD_ALERT_CRITICAL 2 +--- @field OVERHEAD_ALERT_XP 3 +--- @field OVERHEAD_ALERT_BONUS_SPELL_DAMAGE 4 +--- @field OVERHEAD_ALERT_MISS 5 +--- @field OVERHEAD_ALERT_DAMAGE 6 +--- @field OVERHEAD_ALERT_EVADE 7 +--- @field OVERHEAD_ALERT_BLOCK 8 +--- @field OVERHEAD_ALERT_BONUS_POISON_DAMAGE 9 +--- @field OVERHEAD_ALERT_HEAL 10 +--- @field OVERHEAD_ALERT_MANA_ADD 11 +--- @field OVERHEAD_ALERT_MANA_LOSS 12 +--- @field OVERHEAD_ALERT_MAGICAL_BLOCK 16 +--- @field OVERHEAD_ALERT_INCOMING_DAMAGE 17 +--- @field OVERHEAD_ALERT_OUTGOING_DAMAGE 18 +--- @field OVERHEAD_ALERT_DISABLE_RESIST 19 +--- @field OVERHEAD_ALERT_DEATH 20 +--- @field OVERHEAD_ALERT_BLOCKED 21 +--- @field OVERHEAD_ALERT_ITEM_RECEIVED 22 +--- @field OVERHEAD_ALERT_SHARD 23 +--- @field OVERHEAD_ALERT_DEADLY_BLOW 24 +--- @field OVERHEAD_ALERT_FORCE_MISS 25 +local DOTA_OVERHEAD_ALERT = {} +OVERHEAD_ALERT_GOLD = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_GOLD +OVERHEAD_ALERT_DENY = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_DENY +OVERHEAD_ALERT_CRITICAL = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_CRITICAL +OVERHEAD_ALERT_XP = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_XP +OVERHEAD_ALERT_BONUS_SPELL_DAMAGE = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_BONUS_SPELL_DAMAGE +OVERHEAD_ALERT_MISS = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_MISS +OVERHEAD_ALERT_DAMAGE = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_DAMAGE +OVERHEAD_ALERT_EVADE = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_EVADE +OVERHEAD_ALERT_BLOCK = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_BLOCK +OVERHEAD_ALERT_BONUS_POISON_DAMAGE = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_BONUS_POISON_DAMAGE +OVERHEAD_ALERT_HEAL = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_HEAL +OVERHEAD_ALERT_MANA_ADD = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_MANA_ADD +OVERHEAD_ALERT_MANA_LOSS = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_MANA_LOSS +OVERHEAD_ALERT_MAGICAL_BLOCK = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_MAGICAL_BLOCK +OVERHEAD_ALERT_INCOMING_DAMAGE = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_INCOMING_DAMAGE +OVERHEAD_ALERT_OUTGOING_DAMAGE = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_OUTGOING_DAMAGE +OVERHEAD_ALERT_DISABLE_RESIST = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_DISABLE_RESIST +OVERHEAD_ALERT_DEATH = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_DEATH +OVERHEAD_ALERT_BLOCKED = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_BLOCKED +OVERHEAD_ALERT_ITEM_RECEIVED = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_ITEM_RECEIVED +OVERHEAD_ALERT_SHARD = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_SHARD +OVERHEAD_ALERT_DEADLY_BLOW = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_DEADLY_BLOW +OVERHEAD_ALERT_FORCE_MISS = DOTA_OVERHEAD_ALERT.OVERHEAD_ALERT_FORCE_MISS --- (availability: server & client) ---- @alias DOTA_RUNES ---- | `DOTA_RUNE_INVALID` ---- | `DOTA_RUNE_DOUBLEDAMAGE` ---- | `DOTA_RUNE_HASTE` ---- | `DOTA_RUNE_ILLUSION` ---- | `DOTA_RUNE_INVISIBILITY` ---- | `DOTA_RUNE_REGENERATION` ---- | `DOTA_RUNE_BOUNTY` ---- | `DOTA_RUNE_ARCANE` ---- | `DOTA_RUNE_WATER` ---- | `DOTA_RUNE_XP` ---- | `DOTA_RUNE_SHIELD` ---- | `DOTA_RUNE_COUNT` - ---- @type DOTA_RUNES -DOTA_RUNE_INVALID = -1 ---- @type DOTA_RUNES -DOTA_RUNE_DOUBLEDAMAGE = 0 ---- @type DOTA_RUNES -DOTA_RUNE_HASTE = 1 ---- @type DOTA_RUNES -DOTA_RUNE_ILLUSION = 2 ---- @type DOTA_RUNES -DOTA_RUNE_INVISIBILITY = 3 ---- @type DOTA_RUNES -DOTA_RUNE_REGENERATION = 4 ---- @type DOTA_RUNES -DOTA_RUNE_BOUNTY = 5 ---- @type DOTA_RUNES -DOTA_RUNE_ARCANE = 6 ---- @type DOTA_RUNES -DOTA_RUNE_WATER = 7 ---- @type DOTA_RUNES -DOTA_RUNE_XP = 8 ---- @type DOTA_RUNES -DOTA_RUNE_SHIELD = 9 ---- @type DOTA_RUNES -DOTA_RUNE_COUNT = 10 +--- @enum DOTA_RUNES +--- @field DOTA_RUNE_INVALID -1 +--- @field DOTA_RUNE_DOUBLEDAMAGE 0 +--- @field DOTA_RUNE_HASTE 1 +--- @field DOTA_RUNE_ILLUSION 2 +--- @field DOTA_RUNE_INVISIBILITY 3 +--- @field DOTA_RUNE_REGENERATION 4 +--- @field DOTA_RUNE_BOUNTY 5 +--- @field DOTA_RUNE_ARCANE 6 +--- @field DOTA_RUNE_WATER 7 +--- @field DOTA_RUNE_XP 8 +--- @field DOTA_RUNE_SHIELD 9 +--- @field DOTA_RUNE_COUNT 10 +local DOTA_RUNES = {} +DOTA_RUNE_INVALID = DOTA_RUNES.DOTA_RUNE_INVALID +DOTA_RUNE_DOUBLEDAMAGE = DOTA_RUNES.DOTA_RUNE_DOUBLEDAMAGE +DOTA_RUNE_HASTE = DOTA_RUNES.DOTA_RUNE_HASTE +DOTA_RUNE_ILLUSION = DOTA_RUNES.DOTA_RUNE_ILLUSION +DOTA_RUNE_INVISIBILITY = DOTA_RUNES.DOTA_RUNE_INVISIBILITY +DOTA_RUNE_REGENERATION = DOTA_RUNES.DOTA_RUNE_REGENERATION +DOTA_RUNE_BOUNTY = DOTA_RUNES.DOTA_RUNE_BOUNTY +DOTA_RUNE_ARCANE = DOTA_RUNES.DOTA_RUNE_ARCANE +DOTA_RUNE_WATER = DOTA_RUNES.DOTA_RUNE_WATER +DOTA_RUNE_XP = DOTA_RUNES.DOTA_RUNE_XP +DOTA_RUNE_SHIELD = DOTA_RUNES.DOTA_RUNE_SHIELD +DOTA_RUNE_COUNT = DOTA_RUNES.DOTA_RUNE_COUNT --- (availability: server & client) ---- @alias DOTA_SHOP_TYPE ---- | `DOTA_SHOP_HOME` ---- | `DOTA_SHOP_SIDE` ---- | `DOTA_SHOP_SECRET` ---- | `DOTA_SHOP_GROUND` ---- | `DOTA_SHOP_SIDE2` ---- | `DOTA_SHOP_SECRET2` ---- | `DOTA_SHOP_CUSTOM` ---- | `DOTA_SHOP_NEUTRALS` ---- | `DOTA_SHOP_NONE` - ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_HOME = 0 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_SIDE = 1 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_SECRET = 2 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_GROUND = 3 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_SIDE2 = 4 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_SECRET2 = 5 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_CUSTOM = 6 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_NEUTRALS = 7 ---- @type DOTA_SHOP_TYPE -DOTA_SHOP_NONE = 8 +--- @enum DOTA_SHOP_TYPE +--- @field DOTA_SHOP_HOME 0 +--- @field DOTA_SHOP_SIDE 1 +--- @field DOTA_SHOP_SECRET 2 +--- @field DOTA_SHOP_GROUND 3 +--- @field DOTA_SHOP_SIDE2 4 +--- @field DOTA_SHOP_SECRET2 5 +--- @field DOTA_SHOP_CUSTOM 6 +--- @field DOTA_SHOP_NEUTRALS 7 +--- @field DOTA_SHOP_NONE 8 +local DOTA_SHOP_TYPE = {} +DOTA_SHOP_HOME = DOTA_SHOP_TYPE.DOTA_SHOP_HOME +DOTA_SHOP_SIDE = DOTA_SHOP_TYPE.DOTA_SHOP_SIDE +DOTA_SHOP_SECRET = DOTA_SHOP_TYPE.DOTA_SHOP_SECRET +DOTA_SHOP_GROUND = DOTA_SHOP_TYPE.DOTA_SHOP_GROUND +DOTA_SHOP_SIDE2 = DOTA_SHOP_TYPE.DOTA_SHOP_SIDE2 +DOTA_SHOP_SECRET2 = DOTA_SHOP_TYPE.DOTA_SHOP_SECRET2 +DOTA_SHOP_CUSTOM = DOTA_SHOP_TYPE.DOTA_SHOP_CUSTOM +DOTA_SHOP_NEUTRALS = DOTA_SHOP_TYPE.DOTA_SHOP_NEUTRALS +DOTA_SHOP_NONE = DOTA_SHOP_TYPE.DOTA_SHOP_NONE --- (availability: server & client) ---- @alias DOTA_UNIT_TARGET_FLAGS ---- | `DOTA_UNIT_TARGET_FLAG_NONE` ---- | `DOTA_UNIT_TARGET_FLAG_RANGED_ONLY` ---- | `DOTA_UNIT_TARGET_FLAG_MELEE_ONLY` ---- | `DOTA_UNIT_TARGET_FLAG_DEAD` ---- | `DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES` ---- | `DOTA_UNIT_TARGET_FLAG_INVULNERABLE` ---- | `DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE` ---- | `DOTA_UNIT_TARGET_FLAG_NO_INVIS` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS` ---- | `DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE` ---- | `DOTA_UNIT_TARGET_FLAG_MANA_ONLY` ---- | `DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO` ---- | `DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD` ---- | `DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED` ---- | `DOTA_UNIT_TARGET_FLAG_PREFER_ENEMIES` ---- | `DOTA_UNIT_TARGET_FLAG_RESPECT_OBSTRUCTIONS` - ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NONE = 0 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_RANGED_ONLY = 2 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_MELEE_ONLY = 4 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_DEAD = 8 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES = 16 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES = 32 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_INVULNERABLE = 64 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE = 128 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NO_INVIS = 256 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS = 512 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED = 1024 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED = 2048 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED = 4096 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS = 8192 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE = 16384 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_MANA_ONLY = 32768 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP = 65536 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO = 131072 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD = 262144 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED = 524288 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_PREFER_ENEMIES = 1048576 ---- @type DOTA_UNIT_TARGET_FLAGS -DOTA_UNIT_TARGET_FLAG_RESPECT_OBSTRUCTIONS = 2097152 +--- @enum DOTA_UNIT_TARGET_FLAGS +--- @field DOTA_UNIT_TARGET_FLAG_NONE 0 +--- @field DOTA_UNIT_TARGET_FLAG_RANGED_ONLY 2 +--- @field DOTA_UNIT_TARGET_FLAG_MELEE_ONLY 4 +--- @field DOTA_UNIT_TARGET_FLAG_DEAD 8 +--- @field DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES 16 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES 32 +--- @field DOTA_UNIT_TARGET_FLAG_INVULNERABLE 64 +--- @field DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE 128 +--- @field DOTA_UNIT_TARGET_FLAG_NO_INVIS 256 +--- @field DOTA_UNIT_TARGET_FLAG_CAN_BE_SEEN 384 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS 512 +--- @field DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED 1024 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED 2048 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED 4096 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS 8192 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE 16384 +--- @field DOTA_UNIT_TARGET_FLAG_MANA_ONLY 32768 +--- @field DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP 65536 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO 131072 +--- @field DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD 262144 +--- @field DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED 524288 +--- @field DOTA_UNIT_TARGET_FLAG_PREFER_ENEMIES 1048576 +--- @field DOTA_UNIT_TARGET_FLAG_RESPECT_OBSTRUCTIONS 2097152 +local DOTA_UNIT_TARGET_FLAGS = {} +DOTA_UNIT_TARGET_FLAG_NONE = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NONE +DOTA_UNIT_TARGET_FLAG_RANGED_ONLY = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_RANGED_ONLY +DOTA_UNIT_TARGET_FLAG_MELEE_ONLY = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_MELEE_ONLY +DOTA_UNIT_TARGET_FLAG_DEAD = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_DEAD +DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES +DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_MAGIC_IMMUNE_ALLIES +DOTA_UNIT_TARGET_FLAG_INVULNERABLE = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_INVULNERABLE +DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE +DOTA_UNIT_TARGET_FLAG_NO_INVIS = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NO_INVIS +DOTA_UNIT_TARGET_FLAG_CAN_BE_SEEN = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_CAN_BE_SEEN +DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_ANCIENTS +DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_PLAYER_CONTROLLED +DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_DOMINATED +DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_SUMMONED +DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_ILLUSIONS +DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_ATTACK_IMMUNE +DOTA_UNIT_TARGET_FLAG_MANA_ONLY = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_MANA_ONLY +DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP +DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO +DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_OUT_OF_WORLD +DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NOT_NIGHTMARED +DOTA_UNIT_TARGET_FLAG_PREFER_ENEMIES = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_PREFER_ENEMIES +DOTA_UNIT_TARGET_FLAG_RESPECT_OBSTRUCTIONS = DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_RESPECT_OBSTRUCTIONS --- (availability: server & client) ---- @alias DOTA_UNIT_TARGET_TEAM ---- | `DOTA_UNIT_TARGET_TEAM_NONE` ---- | `DOTA_UNIT_TARGET_TEAM_FRIENDLY` ---- | `DOTA_UNIT_TARGET_TEAM_ENEMY` ---- | `DOTA_UNIT_TARGET_TEAM_BOTH` ---- | `DOTA_UNIT_TARGET_TEAM_CUSTOM` - ---- @type DOTA_UNIT_TARGET_TEAM -DOTA_UNIT_TARGET_TEAM_NONE = 0 ---- @type DOTA_UNIT_TARGET_TEAM -DOTA_UNIT_TARGET_TEAM_FRIENDLY = 1 ---- @type DOTA_UNIT_TARGET_TEAM -DOTA_UNIT_TARGET_TEAM_ENEMY = 2 ---- @type DOTA_UNIT_TARGET_TEAM -DOTA_UNIT_TARGET_TEAM_BOTH = 3 ---- @type DOTA_UNIT_TARGET_TEAM -DOTA_UNIT_TARGET_TEAM_CUSTOM = 4 +--- @enum DOTA_UNIT_TARGET_TEAM +--- @field DOTA_UNIT_TARGET_TEAM_NONE 0 +--- @field DOTA_UNIT_TARGET_TEAM_FRIENDLY 1 +--- @field DOTA_UNIT_TARGET_TEAM_ENEMY 2 +--- @field DOTA_UNIT_TARGET_TEAM_BOTH 3 +--- @field DOTA_UNIT_TARGET_TEAM_CUSTOM 4 +local DOTA_UNIT_TARGET_TEAM = {} +DOTA_UNIT_TARGET_TEAM_NONE = DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_NONE +DOTA_UNIT_TARGET_TEAM_FRIENDLY = DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_FRIENDLY +DOTA_UNIT_TARGET_TEAM_ENEMY = DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_ENEMY +DOTA_UNIT_TARGET_TEAM_BOTH = DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_BOTH +DOTA_UNIT_TARGET_TEAM_CUSTOM = DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_CUSTOM --- (availability: server & client) ---- @alias DOTA_UNIT_TARGET_TYPE ---- | `DOTA_UNIT_TARGET_NONE` ---- | `DOTA_UNIT_TARGET_HERO` ---- | `DOTA_UNIT_TARGET_CREEP` ---- | `DOTA_UNIT_TARGET_BUILDING` ---- | `DOTA_UNIT_TARGET_COURIER` ---- | `DOTA_UNIT_TARGET_BASIC` ---- | `DOTA_UNIT_TARGET_OTHER` ---- | `DOTA_UNIT_TARGET_ALL` ---- | `DOTA_UNIT_TARGET_TREE` ---- | `DOTA_UNIT_TARGET_CUSTOM` ---- | `DOTA_UNIT_TARGET_SELF` - ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_NONE = 0 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_HERO = 1 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_CREEP = 2 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_BUILDING = 4 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_COURIER = 16 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_BASIC = 18 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_OTHER = 32 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_ALL = 55 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_TREE = 64 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_CUSTOM = 128 ---- @type DOTA_UNIT_TARGET_TYPE -DOTA_UNIT_TARGET_SELF = 256 +--- @enum DOTA_UNIT_TARGET_TYPE +--- @field DOTA_UNIT_TARGET_NONE 0 +--- @field DOTA_UNIT_TARGET_HERO 1 +--- @field DOTA_UNIT_TARGET_CREEP 2 +--- @field DOTA_UNIT_TARGET_BUILDING 4 +--- @field DOTA_UNIT_TARGET_COURIER 16 +--- @field DOTA_UNIT_TARGET_BASIC 18 +--- @field DOTA_UNIT_TARGET_HEROES_AND_CREEPS 19 +--- @field DOTA_UNIT_TARGET_OTHER 32 +--- @field DOTA_UNIT_TARGET_ALL 55 +--- @field DOTA_UNIT_TARGET_TREE 64 +--- @field DOTA_UNIT_TARGET_CUSTOM 128 +--- @field DOTA_UNIT_TARGET_SELF 256 +local DOTA_UNIT_TARGET_TYPE = {} +DOTA_UNIT_TARGET_NONE = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_NONE +DOTA_UNIT_TARGET_HERO = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_HERO +DOTA_UNIT_TARGET_CREEP = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_CREEP +DOTA_UNIT_TARGET_BUILDING = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_BUILDING +DOTA_UNIT_TARGET_COURIER = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_COURIER +DOTA_UNIT_TARGET_BASIC = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_BASIC +DOTA_UNIT_TARGET_HEROES_AND_CREEPS = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_HEROES_AND_CREEPS +DOTA_UNIT_TARGET_OTHER = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_OTHER +DOTA_UNIT_TARGET_ALL = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_ALL +DOTA_UNIT_TARGET_TREE = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_TREE +DOTA_UNIT_TARGET_CUSTOM = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_CUSTOM +DOTA_UNIT_TARGET_SELF = DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_SELF --- (availability: server & client) ---- @alias DOTAAbilitySpeakTrigger_t ---- | `DOTA_ABILITY_SPEAK_START_ACTION_PHASE` ---- | `DOTA_ABILITY_SPEAK_CAST` - ---- @type DOTAAbilitySpeakTrigger_t -DOTA_ABILITY_SPEAK_START_ACTION_PHASE = 0 ---- @type DOTAAbilitySpeakTrigger_t -DOTA_ABILITY_SPEAK_CAST = 1 +--- @enum DOTAAbilitySpeakTrigger_t +--- @field DOTA_ABILITY_SPEAK_START_ACTION_PHASE 0 +--- @field DOTA_ABILITY_SPEAK_CAST 1 +local DOTAAbilitySpeakTrigger_t = {} +DOTA_ABILITY_SPEAK_START_ACTION_PHASE = DOTAAbilitySpeakTrigger_t.DOTA_ABILITY_SPEAK_START_ACTION_PHASE +DOTA_ABILITY_SPEAK_CAST = DOTAAbilitySpeakTrigger_t.DOTA_ABILITY_SPEAK_CAST --- (availability: server) ---- @alias DOTAConnectionState_t ---- | `DOTA_CONNECTION_STATE_UNKNOWN` ---- | `DOTA_CONNECTION_STATE_NOT_YET_CONNECTED` ---- | `DOTA_CONNECTION_STATE_CONNECTED` ---- | `DOTA_CONNECTION_STATE_DISCONNECTED` ---- | `DOTA_CONNECTION_STATE_ABANDONED` ---- | `DOTA_CONNECTION_STATE_LOADING` ---- | `DOTA_CONNECTION_STATE_FAILED` +--- @enum DOTAConnectionState_t +--- @field DOTA_CONNECTION_STATE_UNKNOWN 0 +--- @field DOTA_CONNECTION_STATE_NOT_YET_CONNECTED 1 +--- @field DOTA_CONNECTION_STATE_CONNECTED 2 +--- @field DOTA_CONNECTION_STATE_DISCONNECTED 3 +--- @field DOTA_CONNECTION_STATE_ABANDONED 4 +--- @field DOTA_CONNECTION_STATE_LOADING 5 +--- @field DOTA_CONNECTION_STATE_FAILED 6 +local DOTAConnectionState_t = {} +DOTA_CONNECTION_STATE_UNKNOWN = DOTAConnectionState_t.DOTA_CONNECTION_STATE_UNKNOWN +DOTA_CONNECTION_STATE_NOT_YET_CONNECTED = DOTAConnectionState_t.DOTA_CONNECTION_STATE_NOT_YET_CONNECTED +DOTA_CONNECTION_STATE_CONNECTED = DOTAConnectionState_t.DOTA_CONNECTION_STATE_CONNECTED +DOTA_CONNECTION_STATE_DISCONNECTED = DOTAConnectionState_t.DOTA_CONNECTION_STATE_DISCONNECTED +DOTA_CONNECTION_STATE_ABANDONED = DOTAConnectionState_t.DOTA_CONNECTION_STATE_ABANDONED +DOTA_CONNECTION_STATE_LOADING = DOTAConnectionState_t.DOTA_CONNECTION_STATE_LOADING +DOTA_CONNECTION_STATE_FAILED = DOTAConnectionState_t.DOTA_CONNECTION_STATE_FAILED ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_UNKNOWN = 0 ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_NOT_YET_CONNECTED = 1 ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_CONNECTED = 2 ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_DISCONNECTED = 3 ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_ABANDONED = 4 ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_LOADING = 5 ---- @type DOTAConnectionState_t -DOTA_CONNECTION_STATE_FAILED = 6 +--- (availability: server & client) +--- @enum DOTACustomCameraEventFlags_t +--- @field k_ECustomCameraEventFlags_Zoom 1 +--- @field k_ECustomCameraEventFlags_Position 2 +--- @field k_ECustomCameraEventFlags_PositionPlayerHero 4 +--- @field k_ECustomCameraEventFlags_Pitch 8 +--- @field k_ECustomCameraEventFlags_Yaw 16 +--- @field k_ECustomCameraEventFlags_Lock 32 +--- @field k_ECustomCameraEventFlags_Unlock 64 +--- @field k_ECustomCameraEventFlags_ResetDefault 128 +--- @field k_ECustomCameraEventFlags_SpecificPlayer 256 +--- @field k_ECustomCameraEventFlags_FadeOut 512 +--- @field k_ECustomCameraEventFlags_FadeIn 1024 +--- @field k_ECustomCameraEventFlags_LetterboxOn 2048 +--- @field k_ECustomCameraEventFlags_LetterboxOff 4096 +local DOTACustomCameraEventFlags_t = {} +k_ECustomCameraEventFlags_Zoom = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_Zoom +k_ECustomCameraEventFlags_Position = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_Position +k_ECustomCameraEventFlags_PositionPlayerHero = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_PositionPlayerHero +k_ECustomCameraEventFlags_Pitch = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_Pitch +k_ECustomCameraEventFlags_Yaw = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_Yaw +k_ECustomCameraEventFlags_Lock = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_Lock +k_ECustomCameraEventFlags_Unlock = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_Unlock +k_ECustomCameraEventFlags_ResetDefault = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_ResetDefault +k_ECustomCameraEventFlags_SpecificPlayer = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_SpecificPlayer +k_ECustomCameraEventFlags_FadeOut = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_FadeOut +k_ECustomCameraEventFlags_FadeIn = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_FadeIn +k_ECustomCameraEventFlags_LetterboxOn = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_LetterboxOn +k_ECustomCameraEventFlags_LetterboxOff = DOTACustomCameraEventFlags_t.k_ECustomCameraEventFlags_LetterboxOff --- (availability: server) ---- @alias DOTADamageFlag_t ---- | `DOTA_DAMAGE_FLAG_NONE` ---- | `DOTA_DAMAGE_FLAG_IGNORES_MAGIC_ARMOR` ---- | `DOTA_DAMAGE_FLAG_IGNORES_PHYSICAL_ARMOR` ---- | `DOTA_DAMAGE_FLAG_BYPASSES_INVULNERABILITY` ---- | `DOTA_DAMAGE_FLAG_BYPASSES_BLOCK` ---- | `DOTA_DAMAGE_FLAG_REFLECTION` ---- | `DOTA_DAMAGE_FLAG_HPLOSS` ---- | `DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT` ---- | `DOTA_DAMAGE_FLAG_NON_LETHAL` ---- | `DOTA_DAMAGE_FLAG_NO_DAMAGE_MULTIPLIERS` ---- | `DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION` ---- | `DOTA_DAMAGE_FLAG_DONT_DISPLAY_DAMAGE_IF_SOURCE_HIDDEN` ---- | `DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL` ---- | `DOTA_DAMAGE_FLAG_PROPERTY_FIRE` ---- | `DOTA_DAMAGE_FLAG_IGNORES_BASE_PHYSICAL_ARMOR` ---- | `DOTA_DAMAGE_FLAG_SECONDARY_PROJECTILE_ATTACK` ---- | `DOTA_DAMAGE_FLAG_FORCE_SPELL_AMPLIFICATION` ---- | `DOTA_DAMAGE_FLAG_MAGIC_AUTO_ATTACK` ---- | `DOTA_DAMAGE_FLAG_ATTACK_MODIFIER` - ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_NONE = 0 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_IGNORES_MAGIC_ARMOR = 1 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_IGNORES_PHYSICAL_ARMOR = 2 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_BYPASSES_INVULNERABILITY = 4 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_BYPASSES_BLOCK = 8 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_REFLECTION = 16 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_HPLOSS = 32 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT = 64 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_NON_LETHAL = 128 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_NO_DAMAGE_MULTIPLIERS = 512 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION = 1024 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_DONT_DISPLAY_DAMAGE_IF_SOURCE_HIDDEN = 2048 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL = 4096 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_PROPERTY_FIRE = 8192 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_IGNORES_BASE_PHYSICAL_ARMOR = 16384 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_SECONDARY_PROJECTILE_ATTACK = 32768 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_FORCE_SPELL_AMPLIFICATION = 65536 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_MAGIC_AUTO_ATTACK = 131072 ---- @type DOTADamageFlag_t -DOTA_DAMAGE_FLAG_ATTACK_MODIFIER = 262144 +--- @enum DOTADamageFlag_t +--- @field DOTA_DAMAGE_FLAG_NONE 0 +--- @field DOTA_DAMAGE_FLAG_IGNORES_MAGIC_ARMOR 1 +--- @field DOTA_DAMAGE_FLAG_IGNORES_PHYSICAL_ARMOR 2 +--- @field DOTA_DAMAGE_FLAG_BYPASSES_INVULNERABILITY 4 +--- @field DOTA_DAMAGE_FLAG_BYPASSES_PHYSICAL_BLOCK 8 +--- @field DOTA_DAMAGE_FLAG_REFLECTION 16 +--- @field DOTA_DAMAGE_FLAG_HPLOSS 32 +--- @field DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT 64 +--- @field DOTA_DAMAGE_FLAG_NON_LETHAL 128 +--- @field DOTA_DAMAGE_FLAG_NO_DAMAGE_MULTIPLIERS 512 +--- @field DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION 1024 +--- @field DOTA_DAMAGE_FLAG_DONT_DISPLAY_DAMAGE_IF_SOURCE_HIDDEN 2048 +--- @field DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL 4096 +--- @field DOTA_DAMAGE_FLAG_PROPERTY_FIRE 8192 +--- @field DOTA_DAMAGE_FLAG_IGNORES_BASE_PHYSICAL_ARMOR 16384 +--- @field DOTA_DAMAGE_FLAG_SECONDARY_PROJECTILE_ATTACK 32768 +--- @field DOTA_DAMAGE_FLAG_FORCE_SPELL_AMPLIFICATION 65536 +--- @field DOTA_DAMAGE_FLAG_MAGIC_AUTO_ATTACK 131072 +--- @field DOTA_DAMAGE_FLAG_ATTACK_MODIFIER 262144 +--- @field DOTA_DAMAGE_FLAG_BYPASSES_ALL_BLOCK 524288 +--- @field DOTA_DAMAGE_FLAG_NO_REFLECTION 1048576 +local DOTADamageFlag_t = {} +DOTA_DAMAGE_FLAG_NONE = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NONE +DOTA_DAMAGE_FLAG_IGNORES_MAGIC_ARMOR = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_IGNORES_MAGIC_ARMOR +DOTA_DAMAGE_FLAG_IGNORES_PHYSICAL_ARMOR = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_IGNORES_PHYSICAL_ARMOR +DOTA_DAMAGE_FLAG_BYPASSES_INVULNERABILITY = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_BYPASSES_INVULNERABILITY +DOTA_DAMAGE_FLAG_BYPASSES_PHYSICAL_BLOCK = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_BYPASSES_PHYSICAL_BLOCK +DOTA_DAMAGE_FLAG_REFLECTION = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_REFLECTION +DOTA_DAMAGE_FLAG_HPLOSS = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_HPLOSS +DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT +DOTA_DAMAGE_FLAG_NON_LETHAL = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NON_LETHAL +DOTA_DAMAGE_FLAG_NO_DAMAGE_MULTIPLIERS = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NO_DAMAGE_MULTIPLIERS +DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION +DOTA_DAMAGE_FLAG_DONT_DISPLAY_DAMAGE_IF_SOURCE_HIDDEN = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_DONT_DISPLAY_DAMAGE_IF_SOURCE_HIDDEN +DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL +DOTA_DAMAGE_FLAG_PROPERTY_FIRE = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_PROPERTY_FIRE +DOTA_DAMAGE_FLAG_IGNORES_BASE_PHYSICAL_ARMOR = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_IGNORES_BASE_PHYSICAL_ARMOR +DOTA_DAMAGE_FLAG_SECONDARY_PROJECTILE_ATTACK = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_SECONDARY_PROJECTILE_ATTACK +DOTA_DAMAGE_FLAG_FORCE_SPELL_AMPLIFICATION = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_FORCE_SPELL_AMPLIFICATION +DOTA_DAMAGE_FLAG_MAGIC_AUTO_ATTACK = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_MAGIC_AUTO_ATTACK +DOTA_DAMAGE_FLAG_ATTACK_MODIFIER = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_ATTACK_MODIFIER +DOTA_DAMAGE_FLAG_BYPASSES_ALL_BLOCK = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_BYPASSES_ALL_BLOCK +DOTA_DAMAGE_FLAG_NO_REFLECTION = DOTADamageFlag_t.DOTA_DAMAGE_FLAG_NO_REFLECTION --- (availability: server) ---- @alias DotaDefaultUIElement_t ---- | `DOTA_DEFAULT_UI_INVALID` ---- | `DOTA_DEFAULT_UI_TOP_TIMEOFDAY` ---- | `DOTA_DEFAULT_UI_TOP_HEROES` ---- | `DOTA_DEFAULT_UI_FLYOUT_SCOREBOARD` ---- | `DOTA_DEFAULT_UI_ACTION_PANEL` ---- | `DOTA_DEFAULT_UI_ACTION_MINIMAP` ---- | `DOTA_DEFAULT_UI_INVENTORY_PANEL` ---- | `DOTA_DEFAULT_UI_INVENTORY_SHOP` ---- | `DOTA_DEFAULT_UI_INVENTORY_ITEMS` ---- | `DOTA_DEFAULT_UI_INVENTORY_QUICKBUY` ---- | `DOTA_DEFAULT_UI_INVENTORY_COURIER` ---- | `DOTA_DEFAULT_UI_INVENTORY_PROTECT` ---- | `DOTA_DEFAULT_UI_INVENTORY_GOLD` ---- | `DOTA_DEFAULT_UI_SHOP_SUGGESTEDITEMS` ---- | `DOTA_DEFAULT_UI_SHOP_COMMONITEMS` ---- | `DOTA_DEFAULT_UI_HERO_SELECTION_TEAMS` ---- | `DOTA_DEFAULT_UI_HERO_SELECTION_GAME_NAME` ---- | `DOTA_DEFAULT_UI_HERO_SELECTION_CLOCK` ---- | `DOTA_DEFAULT_UI_HERO_SELECTION_HEADER` ---- | `DOTA_DEFAULT_UI_TOP_MENU_BUTTONS` ---- | `DOTA_DEFAULT_UI_TOP_BAR_BACKGROUND` ---- | `DOTA_DEFAULT_UI_TOP_BAR_RADIANT_TEAM` ---- | `DOTA_DEFAULT_UI_TOP_BAR_DIRE_TEAM` ---- | `DOTA_DEFAULT_UI_TOP_BAR_SCORE` ---- | `DOTA_DEFAULT_UI_ENDGAME` ---- | `DOTA_DEFAULT_UI_ENDGAME_CHAT` ---- | `DOTA_DEFAULT_UI_QUICK_STATS` ---- | `DOTA_DEFAULT_UI_PREGAME_STRATEGYUI` ---- | `DOTA_DEFAULT_UI_KILLCAM` ---- | `DOTA_DEFAULT_UI_FIGHT_RECAP` ---- | `DOTA_DEFAULT_UI_TOP_BAR` ---- | `DOTA_DEFAULT_UI_CUSTOMUI_BEHIND_HUD_ELEMENTS` ---- | `DOTA_DEFAULT_UI_AGHANIMS_STATUS` ---- | `DOTA_DEFAULT_UI_ELEMENT_COUNT` - ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVALID = -1 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_TIMEOFDAY = 0 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_HEROES = 1 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_FLYOUT_SCOREBOARD = 2 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_ACTION_PANEL = 3 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_ACTION_MINIMAP = 4 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_PANEL = 5 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_SHOP = 6 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_ITEMS = 7 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_QUICKBUY = 8 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_COURIER = 9 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_PROTECT = 10 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_INVENTORY_GOLD = 11 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_SHOP_SUGGESTEDITEMS = 12 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_SHOP_COMMONITEMS = 13 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_HERO_SELECTION_TEAMS = 14 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_HERO_SELECTION_GAME_NAME = 15 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_HERO_SELECTION_CLOCK = 16 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_HERO_SELECTION_HEADER = 17 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_MENU_BUTTONS = 18 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_BAR_BACKGROUND = 19 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_BAR_RADIANT_TEAM = 20 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_BAR_DIRE_TEAM = 21 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_BAR_SCORE = 22 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_ENDGAME = 23 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_ENDGAME_CHAT = 24 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_QUICK_STATS = 25 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_PREGAME_STRATEGYUI = 26 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_KILLCAM = 27 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_FIGHT_RECAP = 28 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_TOP_BAR = 29 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_CUSTOMUI_BEHIND_HUD_ELEMENTS = 30 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_AGHANIMS_STATUS = 31 ---- @type DotaDefaultUIElement_t -DOTA_DEFAULT_UI_ELEMENT_COUNT = 32 +--- @enum DotaDefaultUIElement_t +--- @field DOTA_DEFAULT_UI_INVALID -1 +--- @field DOTA_DEFAULT_UI_TOP_TIMEOFDAY 0 +--- @field DOTA_DEFAULT_UI_TOP_HEROES 1 +--- @field DOTA_DEFAULT_UI_FLYOUT_SCOREBOARD 2 +--- @field DOTA_DEFAULT_UI_ACTION_PANEL 3 +--- @field DOTA_DEFAULT_UI_ACTION_MINIMAP 4 +--- @field DOTA_DEFAULT_UI_INVENTORY_PANEL 5 +--- @field DOTA_DEFAULT_UI_INVENTORY_SHOP 6 +--- @field DOTA_DEFAULT_UI_INVENTORY_ITEMS 7 +--- @field DOTA_DEFAULT_UI_INVENTORY_QUICKBUY 8 +--- @field DOTA_DEFAULT_UI_INVENTORY_COURIER 9 +--- @field DOTA_DEFAULT_UI_INVENTORY_PROTECT 10 +--- @field DOTA_DEFAULT_UI_INVENTORY_GOLD 11 +--- @field DOTA_DEFAULT_UI_SHOP_SUGGESTEDITEMS 12 +--- @field DOTA_DEFAULT_UI_SHOP_COMMONITEMS 13 +--- @field DOTA_DEFAULT_UI_HERO_SELECTION_TEAMS 14 +--- @field DOTA_DEFAULT_UI_HERO_SELECTION_GAME_NAME 15 +--- @field DOTA_DEFAULT_UI_HERO_SELECTION_CLOCK 16 +--- @field DOTA_DEFAULT_UI_HERO_SELECTION_HEADER 17 +--- @field DOTA_DEFAULT_UI_TOP_MENU_BUTTONS 18 +--- @field DOTA_DEFAULT_UI_TOP_BAR_BACKGROUND 19 +--- @field DOTA_DEFAULT_UI_TOP_BAR_RADIANT_TEAM 20 +--- @field DOTA_DEFAULT_UI_TOP_BAR_DIRE_TEAM 21 +--- @field DOTA_DEFAULT_UI_TOP_BAR_SCORE 22 +--- @field DOTA_DEFAULT_UI_ENDGAME 23 +--- @field DOTA_DEFAULT_UI_ENDGAME_CHAT 24 +--- @field DOTA_DEFAULT_UI_QUICK_STATS 25 +--- @field DOTA_DEFAULT_UI_PREGAME_STRATEGYUI 26 +--- @field DOTA_DEFAULT_UI_KILLCAM 27 +--- @field DOTA_DEFAULT_UI_FIGHT_RECAP 28 +--- @field DOTA_DEFAULT_UI_TOP_BAR 29 +--- @field DOTA_DEFAULT_UI_CUSTOMUI_BEHIND_HUD_ELEMENTS 30 +--- @field DOTA_DEFAULT_UI_AGHANIMS_STATUS 31 +--- @field DOTA_DEFAULT_UI_ELEMENT_COUNT 32 +local DotaDefaultUIElement_t = {} +DOTA_DEFAULT_UI_INVALID = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVALID +DOTA_DEFAULT_UI_TOP_TIMEOFDAY = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_TIMEOFDAY +DOTA_DEFAULT_UI_TOP_HEROES = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_HEROES +DOTA_DEFAULT_UI_FLYOUT_SCOREBOARD = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_FLYOUT_SCOREBOARD +DOTA_DEFAULT_UI_ACTION_PANEL = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_ACTION_PANEL +DOTA_DEFAULT_UI_ACTION_MINIMAP = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_ACTION_MINIMAP +DOTA_DEFAULT_UI_INVENTORY_PANEL = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_PANEL +DOTA_DEFAULT_UI_INVENTORY_SHOP = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_SHOP +DOTA_DEFAULT_UI_INVENTORY_ITEMS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_ITEMS +DOTA_DEFAULT_UI_INVENTORY_QUICKBUY = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_QUICKBUY +DOTA_DEFAULT_UI_INVENTORY_COURIER = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_COURIER +DOTA_DEFAULT_UI_INVENTORY_PROTECT = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_PROTECT +DOTA_DEFAULT_UI_INVENTORY_GOLD = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_INVENTORY_GOLD +DOTA_DEFAULT_UI_SHOP_SUGGESTEDITEMS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_SHOP_SUGGESTEDITEMS +DOTA_DEFAULT_UI_SHOP_COMMONITEMS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_SHOP_COMMONITEMS +DOTA_DEFAULT_UI_HERO_SELECTION_TEAMS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_HERO_SELECTION_TEAMS +DOTA_DEFAULT_UI_HERO_SELECTION_GAME_NAME = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_HERO_SELECTION_GAME_NAME +DOTA_DEFAULT_UI_HERO_SELECTION_CLOCK = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_HERO_SELECTION_CLOCK +DOTA_DEFAULT_UI_HERO_SELECTION_HEADER = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_HERO_SELECTION_HEADER +DOTA_DEFAULT_UI_TOP_MENU_BUTTONS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_MENU_BUTTONS +DOTA_DEFAULT_UI_TOP_BAR_BACKGROUND = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_BAR_BACKGROUND +DOTA_DEFAULT_UI_TOP_BAR_RADIANT_TEAM = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_BAR_RADIANT_TEAM +DOTA_DEFAULT_UI_TOP_BAR_DIRE_TEAM = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_BAR_DIRE_TEAM +DOTA_DEFAULT_UI_TOP_BAR_SCORE = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_BAR_SCORE +DOTA_DEFAULT_UI_ENDGAME = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_ENDGAME +DOTA_DEFAULT_UI_ENDGAME_CHAT = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_ENDGAME_CHAT +DOTA_DEFAULT_UI_QUICK_STATS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_QUICK_STATS +DOTA_DEFAULT_UI_PREGAME_STRATEGYUI = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_PREGAME_STRATEGYUI +DOTA_DEFAULT_UI_KILLCAM = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_KILLCAM +DOTA_DEFAULT_UI_FIGHT_RECAP = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_FIGHT_RECAP +DOTA_DEFAULT_UI_TOP_BAR = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_BAR +DOTA_DEFAULT_UI_CUSTOMUI_BEHIND_HUD_ELEMENTS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_CUSTOMUI_BEHIND_HUD_ELEMENTS +DOTA_DEFAULT_UI_AGHANIMS_STATUS = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_AGHANIMS_STATUS +DOTA_DEFAULT_UI_ELEMENT_COUNT = DotaDefaultUIElement_t.DOTA_DEFAULT_UI_ELEMENT_COUNT --- (availability: server) ---- @alias DOTAHUDVisibility_t ---- | `DOTA_HUD_VISIBILITY_INVALID` ---- | `DOTA_HUD_VISIBILITY_TOP_TIMEOFDAY` ---- | `DOTA_HUD_VISIBILITY_TOP_HEROES` ---- | `DOTA_HUD_VISIBILITY_TOP_SCOREBOARD` ---- | `DOTA_HUD_VISIBILITY_ACTION_PANEL` ---- | `DOTA_HUD_VISIBILITY_ACTION_MINIMAP` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_PANEL` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_SHOP` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_ITEMS` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_QUICKBUY` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_COURIER` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_PROTECT` ---- | `DOTA_HUD_VISIBILITY_INVENTORY_GOLD` ---- | `DOTA_HUD_VISIBILITY_SHOP_SUGGESTEDITEMS` ---- | `DOTA_HUD_VISIBILITY_SHOP_COMMONITEMS` ---- | `DOTA_HUD_VISIBILITY_HERO_SELECTION_TEAMS` ---- | `DOTA_HUD_VISIBILITY_HERO_SELECTION_GAME_NAME` ---- | `DOTA_HUD_VISIBILITY_HERO_SELECTION_CLOCK` ---- | `DOTA_HUD_VISIBILITY_HERO_SELECTION_HEADER` ---- | `DOTA_HUD_VISIBILITY_TOP_MENU_BUTTONS` ---- | `DOTA_HUD_VISIBILITY_TOP_BAR_BACKGROUND` ---- | `DOTA_HUD_VISIBILITY_TOP_BAR_RADIANT_TEAM` ---- | `DOTA_HUD_VISIBILITY_TOP_BAR_DIRE_TEAM` ---- | `DOTA_HUD_VISIBILITY_TOP_BAR_SCORE` ---- | `DOTA_HUD_VISIBILITY_ENDGAME` ---- | `DOTA_HUD_VISIBILITY_ENDGAME_CHAT` ---- | `DOTA_HUD_VISIBILITY_QUICK_STATS` ---- | `DOTA_HUD_VISIBILITY_PREGAME_STRATEGYUI` ---- | `DOTA_HUD_VISIBILITY_KILLCAM` ---- | `DOTA_HUD_VISIBILITY_FIGHT_RECAP` ---- | `DOTA_HUD_VISIBILITY_TOP_BAR` ---- | `DOTA_HUD_CUSTOMUI_BEHIND_HUD_ELEMENTS` ---- | `DOTA_HUD_VISIBILITY_AGHANIMS_STATUS` ---- | `DOTA_HUD_VISIBILITY_COUNT` - ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVALID = -1 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_TIMEOFDAY = 0 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_HEROES = 1 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_SCOREBOARD = 2 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_ACTION_PANEL = 3 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_ACTION_MINIMAP = 4 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_PANEL = 5 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_SHOP = 6 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_ITEMS = 7 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_QUICKBUY = 8 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_COURIER = 9 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_PROTECT = 10 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_INVENTORY_GOLD = 11 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_SHOP_SUGGESTEDITEMS = 12 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_SHOP_COMMONITEMS = 13 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_HERO_SELECTION_TEAMS = 14 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_HERO_SELECTION_GAME_NAME = 15 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_HERO_SELECTION_CLOCK = 16 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_HERO_SELECTION_HEADER = 17 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_MENU_BUTTONS = 18 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_BAR_BACKGROUND = 19 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_BAR_RADIANT_TEAM = 20 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_BAR_DIRE_TEAM = 21 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_BAR_SCORE = 22 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_ENDGAME = 23 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_ENDGAME_CHAT = 24 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_QUICK_STATS = 25 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_PREGAME_STRATEGYUI = 26 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_KILLCAM = 27 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_FIGHT_RECAP = 28 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_TOP_BAR = 29 ---- @type DOTAHUDVisibility_t -DOTA_HUD_CUSTOMUI_BEHIND_HUD_ELEMENTS = 30 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_AGHANIMS_STATUS = 31 ---- @type DOTAHUDVisibility_t -DOTA_HUD_VISIBILITY_COUNT = 32 +--- @enum DOTAHUDVisibility_t +--- @field DOTA_HUD_VISIBILITY_INVALID -1 +--- @field DOTA_HUD_VISIBILITY_TOP_TIMEOFDAY 0 +--- @field DOTA_HUD_VISIBILITY_TOP_HEROES 1 +--- @field DOTA_HUD_VISIBILITY_TOP_SCOREBOARD 2 +--- @field DOTA_HUD_VISIBILITY_ACTION_PANEL 3 +--- @field DOTA_HUD_VISIBILITY_ACTION_MINIMAP 4 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_PANEL 5 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_SHOP 6 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_ITEMS 7 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_QUICKBUY 8 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_COURIER 9 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_PROTECT 10 +--- @field DOTA_HUD_VISIBILITY_INVENTORY_GOLD 11 +--- @field DOTA_HUD_VISIBILITY_SHOP_SUGGESTEDITEMS 12 +--- @field DOTA_HUD_VISIBILITY_SHOP_COMMONITEMS 13 +--- @field DOTA_HUD_VISIBILITY_HERO_SELECTION_TEAMS 14 +--- @field DOTA_HUD_VISIBILITY_HERO_SELECTION_GAME_NAME 15 +--- @field DOTA_HUD_VISIBILITY_HERO_SELECTION_CLOCK 16 +--- @field DOTA_HUD_VISIBILITY_HERO_SELECTION_HEADER 17 +--- @field DOTA_HUD_VISIBILITY_TOP_MENU_BUTTONS 18 +--- @field DOTA_HUD_VISIBILITY_TOP_BAR_BACKGROUND 19 +--- @field DOTA_HUD_VISIBILITY_TOP_BAR_RADIANT_TEAM 20 +--- @field DOTA_HUD_VISIBILITY_TOP_BAR_DIRE_TEAM 21 +--- @field DOTA_HUD_VISIBILITY_TOP_BAR_SCORE 22 +--- @field DOTA_HUD_VISIBILITY_ENDGAME 23 +--- @field DOTA_HUD_VISIBILITY_ENDGAME_CHAT 24 +--- @field DOTA_HUD_VISIBILITY_QUICK_STATS 25 +--- @field DOTA_HUD_VISIBILITY_PREGAME_STRATEGYUI 26 +--- @field DOTA_HUD_VISIBILITY_KILLCAM 27 +--- @field DOTA_HUD_VISIBILITY_FIGHT_RECAP 28 +--- @field DOTA_HUD_VISIBILITY_TOP_BAR 29 +--- @field DOTA_HUD_CUSTOMUI_BEHIND_HUD_ELEMENTS 30 +--- @field DOTA_HUD_VISIBILITY_AGHANIMS_STATUS 31 +--- @field DOTA_HUD_VISIBILITY_COUNT 32 +local DOTAHUDVisibility_t = {} +DOTA_HUD_VISIBILITY_INVALID = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVALID +DOTA_HUD_VISIBILITY_TOP_TIMEOFDAY = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_TIMEOFDAY +DOTA_HUD_VISIBILITY_TOP_HEROES = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_HEROES +DOTA_HUD_VISIBILITY_TOP_SCOREBOARD = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_SCOREBOARD +DOTA_HUD_VISIBILITY_ACTION_PANEL = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_ACTION_PANEL +DOTA_HUD_VISIBILITY_ACTION_MINIMAP = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_ACTION_MINIMAP +DOTA_HUD_VISIBILITY_INVENTORY_PANEL = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_PANEL +DOTA_HUD_VISIBILITY_INVENTORY_SHOP = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_SHOP +DOTA_HUD_VISIBILITY_INVENTORY_ITEMS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_ITEMS +DOTA_HUD_VISIBILITY_INVENTORY_QUICKBUY = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_QUICKBUY +DOTA_HUD_VISIBILITY_INVENTORY_COURIER = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_COURIER +DOTA_HUD_VISIBILITY_INVENTORY_PROTECT = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_PROTECT +DOTA_HUD_VISIBILITY_INVENTORY_GOLD = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_INVENTORY_GOLD +DOTA_HUD_VISIBILITY_SHOP_SUGGESTEDITEMS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_SHOP_SUGGESTEDITEMS +DOTA_HUD_VISIBILITY_SHOP_COMMONITEMS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_SHOP_COMMONITEMS +DOTA_HUD_VISIBILITY_HERO_SELECTION_TEAMS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_HERO_SELECTION_TEAMS +DOTA_HUD_VISIBILITY_HERO_SELECTION_GAME_NAME = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_HERO_SELECTION_GAME_NAME +DOTA_HUD_VISIBILITY_HERO_SELECTION_CLOCK = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_HERO_SELECTION_CLOCK +DOTA_HUD_VISIBILITY_HERO_SELECTION_HEADER = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_HERO_SELECTION_HEADER +DOTA_HUD_VISIBILITY_TOP_MENU_BUTTONS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_MENU_BUTTONS +DOTA_HUD_VISIBILITY_TOP_BAR_BACKGROUND = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_BAR_BACKGROUND +DOTA_HUD_VISIBILITY_TOP_BAR_RADIANT_TEAM = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_BAR_RADIANT_TEAM +DOTA_HUD_VISIBILITY_TOP_BAR_DIRE_TEAM = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_BAR_DIRE_TEAM +DOTA_HUD_VISIBILITY_TOP_BAR_SCORE = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_BAR_SCORE +DOTA_HUD_VISIBILITY_ENDGAME = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_ENDGAME +DOTA_HUD_VISIBILITY_ENDGAME_CHAT = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_ENDGAME_CHAT +DOTA_HUD_VISIBILITY_QUICK_STATS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_QUICK_STATS +DOTA_HUD_VISIBILITY_PREGAME_STRATEGYUI = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_PREGAME_STRATEGYUI +DOTA_HUD_VISIBILITY_KILLCAM = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_KILLCAM +DOTA_HUD_VISIBILITY_FIGHT_RECAP = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_FIGHT_RECAP +DOTA_HUD_VISIBILITY_TOP_BAR = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_TOP_BAR +DOTA_HUD_CUSTOMUI_BEHIND_HUD_ELEMENTS = DOTAHUDVisibility_t.DOTA_HUD_CUSTOMUI_BEHIND_HUD_ELEMENTS +DOTA_HUD_VISIBILITY_AGHANIMS_STATUS = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_AGHANIMS_STATUS +DOTA_HUD_VISIBILITY_COUNT = DOTAHUDVisibility_t.DOTA_HUD_VISIBILITY_COUNT --- (availability: server) ---- @alias DOTAInventoryFlags_t ---- | `DOTA_INVENTORY_ALLOW_NONE` ---- | `DOTA_INVENTORY_ALLOW_MAIN` ---- | `DOTA_INVENTORY_ALLOW_STASH` ---- | `DOTA_INVENTORY_ALL_ACCESS` ---- | `DOTA_INVENTORY_ALLOW_DROP_ON_GROUND` ---- | `DOTA_INVENTORY_ALLOW_DROP_AT_FOUNTAIN` ---- | `DOTA_INVENTORY_LIMIT_DROP_ON_GROUND` - ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_ALLOW_NONE = 0 ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_ALLOW_MAIN = 1 ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_ALLOW_STASH = 2 ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_ALL_ACCESS = 3 ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_ALLOW_DROP_ON_GROUND = 4 ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_ALLOW_DROP_AT_FOUNTAIN = 8 ---- @type DOTAInventoryFlags_t -DOTA_INVENTORY_LIMIT_DROP_ON_GROUND = 16 +--- @enum DOTAInventoryFlags_t +--- @field DOTA_INVENTORY_ALLOW_NONE 0 +--- @field DOTA_INVENTORY_ALLOW_MAIN 1 +--- @field DOTA_INVENTORY_ALLOW_STASH 2 +--- @field DOTA_INVENTORY_ALL_ACCESS 3 +--- @field DOTA_INVENTORY_ALLOW_DROP_ON_GROUND 4 +--- @field DOTA_INVENTORY_ALLOW_DROP_AT_FOUNTAIN 8 +--- @field DOTA_INVENTORY_LIMIT_DROP_ON_GROUND 16 +local DOTAInventoryFlags_t = {} +DOTA_INVENTORY_ALLOW_NONE = DOTAInventoryFlags_t.DOTA_INVENTORY_ALLOW_NONE +DOTA_INVENTORY_ALLOW_MAIN = DOTAInventoryFlags_t.DOTA_INVENTORY_ALLOW_MAIN +DOTA_INVENTORY_ALLOW_STASH = DOTAInventoryFlags_t.DOTA_INVENTORY_ALLOW_STASH +DOTA_INVENTORY_ALL_ACCESS = DOTAInventoryFlags_t.DOTA_INVENTORY_ALL_ACCESS +DOTA_INVENTORY_ALLOW_DROP_ON_GROUND = DOTAInventoryFlags_t.DOTA_INVENTORY_ALLOW_DROP_ON_GROUND +DOTA_INVENTORY_ALLOW_DROP_AT_FOUNTAIN = DOTAInventoryFlags_t.DOTA_INVENTORY_ALLOW_DROP_AT_FOUNTAIN +DOTA_INVENTORY_LIMIT_DROP_ON_GROUND = DOTAInventoryFlags_t.DOTA_INVENTORY_LIMIT_DROP_ON_GROUND --- (availability: server & client) ---- @alias DOTALimits_t ---- | `DOTA_DEFAULT_MAX_TEAM` # Default number of players per team. ---- | `DOTA_DEFAULT_MAX_TEAM_PLAYERS` # Default number of non-spectator players supported. ---- | `DOTA_MAX_PLAYER_TEAMS` # Max number of player teams supported. ---- | `DOTA_MAX_SPECTATOR_LOBBY_SIZE` # Max number of viewers in a spectator lobby. ---- | `DOTA_MAX_TEAM` # Max number of players per team. ---- | `DOTA_MAX_TEAM_PLAYERS` # Max number of non-spectator players supported. ---- | `DOTA_MAX_SPECTATOR_TEAM_SIZE` # How many spectators can watch. ---- | `DOTA_MAX_PLAYERS` # Max number of players connected to the server including spectators. - ---- @type DOTALimits_t -DOTA_DEFAULT_MAX_TEAM = 5 ---- @type DOTALimits_t -DOTA_DEFAULT_MAX_TEAM_PLAYERS = 10 ---- @type DOTALimits_t -DOTA_MAX_PLAYER_TEAMS = 10 ---- @type DOTALimits_t -DOTA_MAX_SPECTATOR_LOBBY_SIZE = 15 ---- @type DOTALimits_t -DOTA_MAX_TEAM = 24 ---- @type DOTALimits_t -DOTA_MAX_TEAM_PLAYERS = 24 ---- @type DOTALimits_t -DOTA_MAX_SPECTATOR_TEAM_SIZE = 40 ---- @type DOTALimits_t -DOTA_MAX_PLAYERS = 64 +--- @enum DOTALimits_t +--- @field DOTA_DEFAULT_MAX_TEAM 5 Default number of players per team. +--- @field DOTA_DEFAULT_MAX_TEAM_PLAYERS 10 Default number of non-spectator players supported. +--- @field DOTA_MAX_PLAYER_TEAMS 10 Max number of player teams supported. +--- @field DOTA_MAX_SPECTATOR_LOBBY_SIZE 15 Max number of viewers in a spectator lobby. +--- @field DOTA_MAX_TEAM 24 Max number of players per team. +--- @field DOTA_MAX_TEAM_PLAYERS 24 Max number of non-spectator players supported. +--- @field DOTA_MAX_SPECTATOR_TEAM_SIZE 40 How many spectators can watch. +--- @field DOTA_MAX_PLAYERS 64 Max number of players connected to the server including spectators. +local DOTALimits_t = {} +DOTA_DEFAULT_MAX_TEAM = DOTALimits_t.DOTA_DEFAULT_MAX_TEAM +DOTA_DEFAULT_MAX_TEAM_PLAYERS = DOTALimits_t.DOTA_DEFAULT_MAX_TEAM_PLAYERS +DOTA_MAX_PLAYER_TEAMS = DOTALimits_t.DOTA_MAX_PLAYER_TEAMS +DOTA_MAX_SPECTATOR_LOBBY_SIZE = DOTALimits_t.DOTA_MAX_SPECTATOR_LOBBY_SIZE +DOTA_MAX_TEAM = DOTALimits_t.DOTA_MAX_TEAM +DOTA_MAX_TEAM_PLAYERS = DOTALimits_t.DOTA_MAX_TEAM_PLAYERS +DOTA_MAX_SPECTATOR_TEAM_SIZE = DOTALimits_t.DOTA_MAX_SPECTATOR_TEAM_SIZE +DOTA_MAX_PLAYERS = DOTALimits_t.DOTA_MAX_PLAYERS --- (availability: server) ---- @alias DOTAMinimapEvent_t ---- | `DOTA_MINIMAP_EVENT_ANCIENT_UNDER_ATTACK` ---- | `DOTA_MINIMAP_EVENT_BASE_UNDER_ATTACK` ---- | `DOTA_MINIMAP_EVENT_BASE_GLYPHED` ---- | `DOTA_MINIMAP_EVENT_TEAMMATE_UNDER_ATTACK` ---- | `DOTA_MINIMAP_EVENT_TEAMMATE_TELEPORTING` ---- | `DOTA_MINIMAP_EVENT_TEAMMATE_DIED` ---- | `DOTA_MINIMAP_EVENT_TUTORIAL_TASK_ACTIVE` ---- | `DOTA_MINIMAP_EVENT_TUTORIAL_TASK_FINISHED` ---- | `DOTA_MINIMAP_EVENT_HINT_LOCATION` ---- | `DOTA_MINIMAP_EVENT_ENEMY_TELEPORTING` ---- | `DOTA_MINIMAP_EVENT_CANCEL_TELEPORTING` ---- | `DOTA_MINIMAP_EVENT_RADAR` ---- | `DOTA_MINIMAP_EVENT_RADAR_TARGET` ---- | `DOTA_MINIMAP_EVENT_MOVE_TO_TARGET` - ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_ANCIENT_UNDER_ATTACK = 2 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_BASE_UNDER_ATTACK = 4 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_BASE_GLYPHED = 8 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_TEAMMATE_UNDER_ATTACK = 16 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_TEAMMATE_TELEPORTING = 32 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_TEAMMATE_DIED = 64 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_TUTORIAL_TASK_ACTIVE = 128 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_TUTORIAL_TASK_FINISHED = 256 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_HINT_LOCATION = 512 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_ENEMY_TELEPORTING = 1024 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_CANCEL_TELEPORTING = 2048 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_RADAR = 4096 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_RADAR_TARGET = 8192 ---- @type DOTAMinimapEvent_t -DOTA_MINIMAP_EVENT_MOVE_TO_TARGET = 16384 +--- @enum DOTAMinimapEvent_t +--- @field DOTA_MINIMAP_EVENT_ANCIENT_UNDER_ATTACK 2 +--- @field DOTA_MINIMAP_EVENT_BASE_UNDER_ATTACK 4 +--- @field DOTA_MINIMAP_EVENT_BASE_GLYPHED 8 +--- @field DOTA_MINIMAP_EVENT_TEAMMATE_UNDER_ATTACK 16 +--- @field DOTA_MINIMAP_EVENT_TEAMMATE_TELEPORTING 32 +--- @field DOTA_MINIMAP_EVENT_TEAMMATE_DIED 64 +--- @field DOTA_MINIMAP_EVENT_TUTORIAL_TASK_ACTIVE 128 +--- @field DOTA_MINIMAP_EVENT_TUTORIAL_TASK_FINISHED 256 +--- @field DOTA_MINIMAP_EVENT_HINT_LOCATION 512 +--- @field DOTA_MINIMAP_EVENT_ENEMY_TELEPORTING 1024 +--- @field DOTA_MINIMAP_EVENT_CANCEL_TELEPORTING 2048 +--- @field DOTA_MINIMAP_EVENT_RADAR 4096 +--- @field DOTA_MINIMAP_EVENT_RADAR_TARGET 8192 +--- @field DOTA_MINIMAP_EVENT_MOVE_TO_TARGET 16384 +local DOTAMinimapEvent_t = {} +DOTA_MINIMAP_EVENT_ANCIENT_UNDER_ATTACK = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_ANCIENT_UNDER_ATTACK +DOTA_MINIMAP_EVENT_BASE_UNDER_ATTACK = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_BASE_UNDER_ATTACK +DOTA_MINIMAP_EVENT_BASE_GLYPHED = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_BASE_GLYPHED +DOTA_MINIMAP_EVENT_TEAMMATE_UNDER_ATTACK = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_TEAMMATE_UNDER_ATTACK +DOTA_MINIMAP_EVENT_TEAMMATE_TELEPORTING = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_TEAMMATE_TELEPORTING +DOTA_MINIMAP_EVENT_TEAMMATE_DIED = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_TEAMMATE_DIED +DOTA_MINIMAP_EVENT_TUTORIAL_TASK_ACTIVE = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_TUTORIAL_TASK_ACTIVE +DOTA_MINIMAP_EVENT_TUTORIAL_TASK_FINISHED = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_TUTORIAL_TASK_FINISHED +DOTA_MINIMAP_EVENT_HINT_LOCATION = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_HINT_LOCATION +DOTA_MINIMAP_EVENT_ENEMY_TELEPORTING = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_ENEMY_TELEPORTING +DOTA_MINIMAP_EVENT_CANCEL_TELEPORTING = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_CANCEL_TELEPORTING +DOTA_MINIMAP_EVENT_RADAR = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_RADAR +DOTA_MINIMAP_EVENT_RADAR_TARGET = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_RADAR_TARGET +DOTA_MINIMAP_EVENT_MOVE_TO_TARGET = DOTAMinimapEvent_t.DOTA_MINIMAP_EVENT_MOVE_TO_TARGET --- (availability: server & client) ---- @alias DOTAModifierAttribute_t ---- | `MODIFIER_ATTRIBUTE_NONE` ---- | `MODIFIER_ATTRIBUTE_PERMANENT` ---- | `MODIFIER_ATTRIBUTE_MULTIPLE` ---- | `MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE` ---- | `MODIFIER_ATTRIBUTE_AURA_PRIORITY` ---- | `MODIFIER_ATTRIBUTE_IGNORE_DODGE` - ---- @type DOTAModifierAttribute_t -MODIFIER_ATTRIBUTE_NONE = 0 ---- @type DOTAModifierAttribute_t -MODIFIER_ATTRIBUTE_PERMANENT = 1 ---- @type DOTAModifierAttribute_t -MODIFIER_ATTRIBUTE_MULTIPLE = 2 ---- @type DOTAModifierAttribute_t -MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE = 4 ---- @type DOTAModifierAttribute_t -MODIFIER_ATTRIBUTE_AURA_PRIORITY = 8 ---- @type DOTAModifierAttribute_t -MODIFIER_ATTRIBUTE_IGNORE_DODGE = 16 +--- @enum DOTAModifierAttribute_t +--- @field MODIFIER_ATTRIBUTE_NONE 0 +--- @field MODIFIER_ATTRIBUTE_PERMANENT 1 +--- @field MODIFIER_ATTRIBUTE_MULTIPLE 2 +--- @field MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE 4 +--- @field MODIFIER_ATTRIBUTE_AURA_PRIORITY 8 +--- @field MODIFIER_ATTRIBUTE_IGNORE_DODGE 16 +local DOTAModifierAttribute_t = {} +MODIFIER_ATTRIBUTE_NONE = DOTAModifierAttribute_t.MODIFIER_ATTRIBUTE_NONE +MODIFIER_ATTRIBUTE_PERMANENT = DOTAModifierAttribute_t.MODIFIER_ATTRIBUTE_PERMANENT +MODIFIER_ATTRIBUTE_MULTIPLE = DOTAModifierAttribute_t.MODIFIER_ATTRIBUTE_MULTIPLE +MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE = DOTAModifierAttribute_t.MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE +MODIFIER_ATTRIBUTE_AURA_PRIORITY = DOTAModifierAttribute_t.MODIFIER_ATTRIBUTE_AURA_PRIORITY +MODIFIER_ATTRIBUTE_IGNORE_DODGE = DOTAModifierAttribute_t.MODIFIER_ATTRIBUTE_IGNORE_DODGE --- (availability: server) ---- @alias DOTAMusicStatus_t ---- | `DOTA_MUSIC_STATUS_NONE` ---- | `DOTA_MUSIC_STATUS_EXPLORATION` ---- | `DOTA_MUSIC_STATUS_BATTLE` ---- | `DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION` ---- | `DOTA_MUSIC_STATUS_DEAD` ---- | `DOTA_MUSIC_STATUS_LAST` - ---- @type DOTAMusicStatus_t -DOTA_MUSIC_STATUS_NONE = 0 ---- @type DOTAMusicStatus_t -DOTA_MUSIC_STATUS_EXPLORATION = 1 ---- @type DOTAMusicStatus_t -DOTA_MUSIC_STATUS_BATTLE = 2 ---- @type DOTAMusicStatus_t -DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION = 3 ---- @type DOTAMusicStatus_t -DOTA_MUSIC_STATUS_DEAD = 4 ---- @type DOTAMusicStatus_t -DOTA_MUSIC_STATUS_LAST = 5 +--- @enum DOTAMusicStatus_t +--- @field DOTA_MUSIC_STATUS_NONE 0 +--- @field DOTA_MUSIC_STATUS_EXPLORATION 1 +--- @field DOTA_MUSIC_STATUS_BATTLE 2 +--- @field DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION 3 +--- @field DOTA_MUSIC_STATUS_DEAD 4 +--- @field DOTA_MUSIC_STATUS_LAST 5 +local DOTAMusicStatus_t = {} +DOTA_MUSIC_STATUS_NONE = DOTAMusicStatus_t.DOTA_MUSIC_STATUS_NONE +DOTA_MUSIC_STATUS_EXPLORATION = DOTAMusicStatus_t.DOTA_MUSIC_STATUS_EXPLORATION +DOTA_MUSIC_STATUS_BATTLE = DOTAMusicStatus_t.DOTA_MUSIC_STATUS_BATTLE +DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION = DOTAMusicStatus_t.DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION +DOTA_MUSIC_STATUS_DEAD = DOTAMusicStatus_t.DOTA_MUSIC_STATUS_DEAD +DOTA_MUSIC_STATUS_LAST = DOTAMusicStatus_t.DOTA_MUSIC_STATUS_LAST --- (availability: server) ---- @alias DOTAPostGameColumn_t ---- | `DOTA_POST_GAME_COLUMN_LEVEL` ---- | `DOTA_POST_GAME_COLUMN_ITEMS` ---- | `DOTA_POST_GAME_COLUMN_KILLS` ---- | `DOTA_POST_GAME_COLUMN_DEATHS` ---- | `DOTA_POST_GAME_COLUMN_ASSISTS` ---- | `DOTA_POST_GAME_COLUMN_NET_WORTH` ---- | `DOTA_POST_GAME_COLUMN_LAST_HITS` ---- | `DOTA_POST_GAME_COLUMN_DENIES` ---- | `DOTA_POST_GAME_COLUMN_DAMAGE` ---- | `DOTA_POST_GAME_COLUMN_HEALING` ---- | `DOTA_POST_GAME_COLUMN_MAX` - ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_LEVEL = 0 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_ITEMS = 1 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_KILLS = 2 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_DEATHS = 3 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_ASSISTS = 4 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_NET_WORTH = 5 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_LAST_HITS = 6 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_DENIES = 7 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_DAMAGE = 8 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_HEALING = 9 ---- @type DOTAPostGameColumn_t -DOTA_POST_GAME_COLUMN_MAX = 10 +--- @enum DOTAPostGameColumn_t +--- @field DOTA_POST_GAME_COLUMN_LEVEL 0 +--- @field DOTA_POST_GAME_COLUMN_ITEMS 1 +--- @field DOTA_POST_GAME_COLUMN_KILLS 2 +--- @field DOTA_POST_GAME_COLUMN_DEATHS 3 +--- @field DOTA_POST_GAME_COLUMN_ASSISTS 4 +--- @field DOTA_POST_GAME_COLUMN_NET_WORTH 5 +--- @field DOTA_POST_GAME_COLUMN_LAST_HITS 6 +--- @field DOTA_POST_GAME_COLUMN_DENIES 7 +--- @field DOTA_POST_GAME_COLUMN_DAMAGE 8 +--- @field DOTA_POST_GAME_COLUMN_HEALING 9 +--- @field DOTA_POST_GAME_COLUMN_MAX 10 +local DOTAPostGameColumn_t = {} +DOTA_POST_GAME_COLUMN_LEVEL = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_LEVEL +DOTA_POST_GAME_COLUMN_ITEMS = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_ITEMS +DOTA_POST_GAME_COLUMN_KILLS = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_KILLS +DOTA_POST_GAME_COLUMN_DEATHS = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_DEATHS +DOTA_POST_GAME_COLUMN_ASSISTS = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_ASSISTS +DOTA_POST_GAME_COLUMN_NET_WORTH = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_NET_WORTH +DOTA_POST_GAME_COLUMN_LAST_HITS = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_LAST_HITS +DOTA_POST_GAME_COLUMN_DENIES = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_DENIES +DOTA_POST_GAME_COLUMN_DAMAGE = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_DAMAGE +DOTA_POST_GAME_COLUMN_HEALING = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_HEALING +DOTA_POST_GAME_COLUMN_MAX = DOTAPostGameColumn_t.DOTA_POST_GAME_COLUMN_MAX --- (availability: server) ---- @alias DOTAPostGameLayout_t ---- | `DOTA_POST_GAME_LAYOUT_DOUBLE_COLUMN` ---- | `DOTA_POST_GAME_LAYOUT_SINGLE_COLUMN` ---- | `DOTA_POST_GAME_LAYOUT_MAX` - ---- @type DOTAPostGameLayout_t -DOTA_POST_GAME_LAYOUT_DOUBLE_COLUMN = 0 ---- @type DOTAPostGameLayout_t -DOTA_POST_GAME_LAYOUT_SINGLE_COLUMN = 1 ---- @type DOTAPostGameLayout_t -DOTA_POST_GAME_LAYOUT_MAX = 2 +--- @enum DOTAPostGameLayout_t +--- @field DOTA_POST_GAME_LAYOUT_DOUBLE_COLUMN 0 +--- @field DOTA_POST_GAME_LAYOUT_SINGLE_COLUMN 1 +--- @field DOTA_POST_GAME_LAYOUT_MAX 2 +local DOTAPostGameLayout_t = {} +DOTA_POST_GAME_LAYOUT_DOUBLE_COLUMN = DOTAPostGameLayout_t.DOTA_POST_GAME_LAYOUT_DOUBLE_COLUMN +DOTA_POST_GAME_LAYOUT_SINGLE_COLUMN = DOTAPostGameLayout_t.DOTA_POST_GAME_LAYOUT_SINGLE_COLUMN +DOTA_POST_GAME_LAYOUT_MAX = DOTAPostGameLayout_t.DOTA_POST_GAME_LAYOUT_MAX --- (availability: server & client) ---- @alias DOTAProjectileAttachment_t ---- | `DOTA_PROJECTILE_ATTACHMENT_NONE` ---- | `DOTA_PROJECTILE_ATTACHMENT_ATTACK_1` ---- | `DOTA_PROJECTILE_ATTACHMENT_ATTACK_2` ---- | `DOTA_PROJECTILE_ATTACHMENT_HITLOCATION` ---- | `DOTA_PROJECTILE_ATTACHMENT_ATTACK_3` ---- | `DOTA_PROJECTILE_ATTACHMENT_ATTACK_4` ---- | `DOTA_PROJECTILE_ATTACHMENT_LAST` - ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_NONE = 0 ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_ATTACK_1 = 1 ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_ATTACK_2 = 2 ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_HITLOCATION = 3 ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_ATTACK_3 = 4 ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_ATTACK_4 = 5 ---- @type DOTAProjectileAttachment_t -DOTA_PROJECTILE_ATTACHMENT_LAST = 6 +--- @enum DOTAProjectileAttachment_t +--- @field DOTA_PROJECTILE_ATTACHMENT_NONE 0 +--- @field DOTA_PROJECTILE_ATTACHMENT_ATTACK_1 1 +--- @field DOTA_PROJECTILE_ATTACHMENT_ATTACK_2 2 +--- @field DOTA_PROJECTILE_ATTACHMENT_HITLOCATION 3 +--- @field DOTA_PROJECTILE_ATTACHMENT_ATTACK_3 4 +--- @field DOTA_PROJECTILE_ATTACHMENT_ATTACK_4 5 +--- @field DOTA_PROJECTILE_ATTACHMENT_LAST 6 +local DOTAProjectileAttachment_t = {} +DOTA_PROJECTILE_ATTACHMENT_NONE = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_NONE +DOTA_PROJECTILE_ATTACHMENT_ATTACK_1 = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_ATTACK_1 +DOTA_PROJECTILE_ATTACHMENT_ATTACK_2 = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_ATTACK_2 +DOTA_PROJECTILE_ATTACHMENT_HITLOCATION = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_HITLOCATION +DOTA_PROJECTILE_ATTACHMENT_ATTACK_3 = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_ATTACK_3 +DOTA_PROJECTILE_ATTACHMENT_ATTACK_4 = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_ATTACK_4 +DOTA_PROJECTILE_ATTACHMENT_LAST = DOTAProjectileAttachment_t.DOTA_PROJECTILE_ATTACHMENT_LAST --- (availability: server) ---- @alias DOTAScriptInventorySlot_t ---- | `DOTA_ITEM_SLOT_1` ---- | `DOTA_ITEM_SLOT_2` ---- | `DOTA_ITEM_SLOT_3` ---- | `DOTA_ITEM_SLOT_4` ---- | `DOTA_ITEM_SLOT_5` ---- | `DOTA_ITEM_SLOT_6` ---- | `DOTA_ITEM_SLOT_7` ---- | `DOTA_ITEM_SLOT_8` ---- | `DOTA_ITEM_SLOT_9` ---- | `DOTA_STASH_SLOT_1` ---- | `DOTA_STASH_SLOT_2` ---- | `DOTA_STASH_SLOT_3` ---- | `DOTA_STASH_SLOT_4` ---- | `DOTA_STASH_SLOT_5` ---- | `DOTA_STASH_SLOT_6` ---- | `DOTA_ITEM_TP_SCROLL` ---- | `DOTA_ITEM_NEUTRAL_SLOT` ---- | `DOTA_ITEM_TRANSIENT_ITEM` ---- | `DOTA_ITEM_TRANSIENT_RECIPE` ---- | `DOTA_ITEM_TRANSIENT_CAST_ITEM` - ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_1 = 0 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_2 = 1 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_3 = 2 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_4 = 3 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_5 = 4 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_6 = 5 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_7 = 6 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_8 = 7 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_SLOT_9 = 8 ---- @type DOTAScriptInventorySlot_t -DOTA_STASH_SLOT_1 = 9 ---- @type DOTAScriptInventorySlot_t -DOTA_STASH_SLOT_2 = 10 ---- @type DOTAScriptInventorySlot_t -DOTA_STASH_SLOT_3 = 11 ---- @type DOTAScriptInventorySlot_t -DOTA_STASH_SLOT_4 = 12 ---- @type DOTAScriptInventorySlot_t -DOTA_STASH_SLOT_5 = 13 ---- @type DOTAScriptInventorySlot_t -DOTA_STASH_SLOT_6 = 14 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_TP_SCROLL = 15 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_NEUTRAL_SLOT = 16 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_TRANSIENT_ITEM = 17 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_TRANSIENT_RECIPE = 18 ---- @type DOTAScriptInventorySlot_t -DOTA_ITEM_TRANSIENT_CAST_ITEM = 20 +--- @enum DOTAScriptInventorySlot_t +--- @field DOTA_ITEM_SLOT_1 0 +--- @field DOTA_ITEM_SLOT_2 1 +--- @field DOTA_ITEM_SLOT_3 2 +--- @field DOTA_ITEM_SLOT_4 3 +--- @field DOTA_ITEM_SLOT_5 4 +--- @field DOTA_ITEM_SLOT_6 5 +--- @field DOTA_ITEM_SLOT_7 6 +--- @field DOTA_ITEM_SLOT_8 7 +--- @field DOTA_ITEM_SLOT_9 8 +--- @field DOTA_STASH_SLOT_1 9 +--- @field DOTA_STASH_SLOT_2 10 +--- @field DOTA_STASH_SLOT_3 11 +--- @field DOTA_STASH_SLOT_4 12 +--- @field DOTA_STASH_SLOT_5 13 +--- @field DOTA_STASH_SLOT_6 14 +--- @field DOTA_ITEM_TP_SCROLL 15 +--- @field DOTA_ITEM_NEUTRAL_ACTIVE_SLOT 16 +--- @field DOTA_ITEM_NEUTRAL_PASSIVE_SLOT 17 +--- @field DOTA_ITEM_TRANSIENT_ITEM 23 +--- @field DOTA_ITEM_TRANSIENT_RECIPE 24 +--- @field DOTA_ITEM_TRANSIENT_CAST_ITEM 26 +local DOTAScriptInventorySlot_t = {} +DOTA_ITEM_SLOT_1 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_1 +DOTA_ITEM_SLOT_2 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_2 +DOTA_ITEM_SLOT_3 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_3 +DOTA_ITEM_SLOT_4 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_4 +DOTA_ITEM_SLOT_5 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_5 +DOTA_ITEM_SLOT_6 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_6 +DOTA_ITEM_SLOT_7 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_7 +DOTA_ITEM_SLOT_8 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_8 +DOTA_ITEM_SLOT_9 = DOTAScriptInventorySlot_t.DOTA_ITEM_SLOT_9 +DOTA_STASH_SLOT_1 = DOTAScriptInventorySlot_t.DOTA_STASH_SLOT_1 +DOTA_STASH_SLOT_2 = DOTAScriptInventorySlot_t.DOTA_STASH_SLOT_2 +DOTA_STASH_SLOT_3 = DOTAScriptInventorySlot_t.DOTA_STASH_SLOT_3 +DOTA_STASH_SLOT_4 = DOTAScriptInventorySlot_t.DOTA_STASH_SLOT_4 +DOTA_STASH_SLOT_5 = DOTAScriptInventorySlot_t.DOTA_STASH_SLOT_5 +DOTA_STASH_SLOT_6 = DOTAScriptInventorySlot_t.DOTA_STASH_SLOT_6 +DOTA_ITEM_TP_SCROLL = DOTAScriptInventorySlot_t.DOTA_ITEM_TP_SCROLL +DOTA_ITEM_NEUTRAL_ACTIVE_SLOT = DOTAScriptInventorySlot_t.DOTA_ITEM_NEUTRAL_ACTIVE_SLOT +DOTA_ITEM_NEUTRAL_PASSIVE_SLOT = DOTAScriptInventorySlot_t.DOTA_ITEM_NEUTRAL_PASSIVE_SLOT +DOTA_ITEM_TRANSIENT_ITEM = DOTAScriptInventorySlot_t.DOTA_ITEM_TRANSIENT_ITEM +DOTA_ITEM_TRANSIENT_RECIPE = DOTAScriptInventorySlot_t.DOTA_ITEM_TRANSIENT_RECIPE +DOTA_ITEM_TRANSIENT_CAST_ITEM = DOTAScriptInventorySlot_t.DOTA_ITEM_TRANSIENT_CAST_ITEM --- (availability: server) ---- @alias DOTASlotType_t ---- | `DOTA_LOADOUT_TYPE_INVALID` ---- | `DOTA_LOADOUT_TYPE_WEAPON` ---- | `DOTA_LOADOUT_TYPE_OFFHAND_WEAPON` ---- | `DOTA_LOADOUT_TYPE_WEAPON2` ---- | `DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2` ---- | `DOTA_LOADOUT_TYPE_HEAD` ---- | `DOTA_LOADOUT_TYPE_SHOULDER` ---- | `DOTA_LOADOUT_TYPE_ARMS` ---- | `DOTA_LOADOUT_TYPE_ARMOR` ---- | `DOTA_LOADOUT_TYPE_BELT` ---- | `DOTA_LOADOUT_TYPE_NECK` ---- | `DOTA_LOADOUT_TYPE_BACK` ---- | `DOTA_LOADOUT_TYPE_GLOVES` ---- | `DOTA_LOADOUT_TYPE_LEGS` ---- | `DOTA_LOADOUT_TYPE_TAIL` ---- | `DOTA_LOADOUT_TYPE_MISC` ---- | `DOTA_LOADOUT_TYPE_COSTUME` ---- | `DOTA_LOADOUT_TYPE_BODY_HEAD` ---- | `DOTA_LOADOUT_TYPE_MOUNT` ---- | `DOTA_LOADOUT_TYPE_SUMMON` ---- | `DOTA_LOADOUT_TYPE_SHAPESHIFT` ---- | `DOTA_LOADOUT_TYPE_TAUNT` ---- | `DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS` ---- | `DOTA_LOADOUT_TYPE_ABILITY_ATTACK` ---- | `DOTA_LOADOUT_TYPE_ABILITY1` ---- | `DOTA_LOADOUT_TYPE_ABILITY2` ---- | `DOTA_LOADOUT_TYPE_ABILITY3` ---- | `DOTA_LOADOUT_TYPE_ABILITY4` ---- | `DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_2` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_3` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_4` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_5` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_6` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_7` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_8` ---- | `DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_9` ---- | `DOTA_LOADOUT_TYPE_VOICE` ---- | `DOTA_LOADOUT_PERSONA_1_START` ---- | `DOTA_LOADOUT_TYPE_WEAPON_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_OFFHAND_WEAPON_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_WEAPON2_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_HEAD_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_SHOULDER_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ARMS_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ARMOR_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_BELT_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_NECK_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_BACK_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_LEGS_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_GLOVES_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_TAIL_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_MISC_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_BODY_HEAD_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_MOUNT_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_SUMMON_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_SHAPESHIFT_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_TAUNT_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY_ATTACK_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY1_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY2_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY3_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY4_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE_PERSONA_1` ---- | `DOTA_LOADOUT_PERSONA_1_END` ---- | `DOTA_LOADOUT_TYPE_VOICE_PERSONA_1` ---- | `DOTA_LOADOUT_TYPE_PERSONA_SELECTOR` ---- | `DOTA_LOADOUT_TYPE_COURIER` ---- | `DOTA_PLAYER_LOADOUT_START` ---- | `DOTA_LOADOUT_TYPE_ANNOUNCER` ---- | `DOTA_LOADOUT_TYPE_MEGA_KILLS` ---- | `DOTA_LOADOUT_TYPE_MUSIC` ---- | `DOTA_LOADOUT_TYPE_WARD` ---- | `DOTA_LOADOUT_TYPE_HUD_SKIN` ---- | `DOTA_LOADOUT_TYPE_LOADING_SCREEN` ---- | `DOTA_LOADOUT_TYPE_WEATHER` ---- | `DOTA_LOADOUT_TYPE_HEROIC_STATUE` ---- | `DOTA_LOADOUT_TYPE_MULTIKILL_BANNER` ---- | `DOTA_LOADOUT_TYPE_CURSOR_PACK` ---- | `DOTA_LOADOUT_TYPE_TELEPORT_EFFECT` ---- | `DOTA_LOADOUT_TYPE_BLINK_EFFECT` ---- | `DOTA_LOADOUT_TYPE_EMBLEM` ---- | `DOTA_LOADOUT_TYPE_TERRAIN` ---- | `DOTA_LOADOUT_TYPE_RADIANT_CREEPS` ---- | `DOTA_LOADOUT_TYPE_DIRE_CREEPS` ---- | `DOTA_LOADOUT_TYPE_RADIANT_TOWER` ---- | `DOTA_LOADOUT_TYPE_DIRE_TOWER` ---- | `DOTA_LOADOUT_TYPE_VERSUS_SCREEN` ---- | `DOTA_LOADOUT_TYPE_STREAK_EFFECT` ---- | `DOTA_LOADOUT_TYPE_KILL_EFFECT` ---- | `DOTA_LOADOUT_TYPE_DEATH_EFFECT` ---- | `DOTA_LOADOUT_TYPE_HEAD_EFFECT` ---- | `DOTA_LOADOUT_TYPE_MAP_EFFECT` ---- | `DOTA_LOADOUT_TYPE_COURIER_EFFECT` ---- | `DOTA_LOADOUT_TYPE_RADIANT_SIEGE_CREEPS` ---- | `DOTA_LOADOUT_TYPE_DIRE_SIEGE_CREEPS` ---- | `DOTA_LOADOUT_TYPE_ROSHAN` ---- | `DOTA_LOADOUT_TYPE_TORMENTOR` ---- | `DOTA_PLAYER_LOADOUT_END` ---- | `DOTA_LOADOUT_TYPE_NONE` ---- | `DOTA_LOADOUT_TYPE_COUNT` - ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_INVALID = -1 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_WEAPON = 0 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_OFFHAND_WEAPON = 1 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_WEAPON2 = 2 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2 = 3 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_HEAD = 4 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_SHOULDER = 5 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ARMS = 6 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ARMOR = 7 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BELT = 8 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_NECK = 9 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BACK = 10 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_GLOVES = 11 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_LEGS = 12 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TAIL = 13 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MISC = 14 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_COSTUME = 15 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BODY_HEAD = 16 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MOUNT = 17 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_SUMMON = 18 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_SHAPESHIFT = 19 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TAUNT = 20 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS = 21 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_ATTACK = 22 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY1 = 23 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY2 = 24 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY3 = 25 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY4 = 26 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE = 27 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_1 = 28 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_2 = 29 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_3 = 30 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_4 = 31 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_5 = 32 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_6 = 33 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_7 = 34 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_8 = 35 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_9 = 36 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_VOICE = 37 ---- @type DOTASlotType_t -DOTA_LOADOUT_PERSONA_1_START = 38 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_WEAPON_PERSONA_1 = 38 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_OFFHAND_WEAPON_PERSONA_1 = 39 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_WEAPON2_PERSONA_1 = 40 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2_PERSONA_1 = 41 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_HEAD_PERSONA_1 = 42 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_SHOULDER_PERSONA_1 = 43 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ARMS_PERSONA_1 = 44 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ARMOR_PERSONA_1 = 45 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BELT_PERSONA_1 = 46 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_NECK_PERSONA_1 = 47 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BACK_PERSONA_1 = 48 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_LEGS_PERSONA_1 = 49 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_GLOVES_PERSONA_1 = 50 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TAIL_PERSONA_1 = 51 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MISC_PERSONA_1 = 52 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BODY_HEAD_PERSONA_1 = 53 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MOUNT_PERSONA_1 = 54 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_SUMMON_PERSONA_1 = 55 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_SHAPESHIFT_PERSONA_1 = 56 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TAUNT_PERSONA_1 = 57 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS_PERSONA_1 = 58 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_ATTACK_PERSONA_1 = 59 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY1_PERSONA_1 = 60 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY2_PERSONA_1 = 61 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY3_PERSONA_1 = 62 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY4_PERSONA_1 = 63 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE_PERSONA_1 = 64 ---- @type DOTASlotType_t -DOTA_LOADOUT_PERSONA_1_END = 65 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_VOICE_PERSONA_1 = 65 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_PERSONA_SELECTOR = 66 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_COURIER = 67 ---- @type DOTASlotType_t -DOTA_PLAYER_LOADOUT_START = 67 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ANNOUNCER = 68 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MEGA_KILLS = 69 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MUSIC = 70 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_WARD = 71 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_HUD_SKIN = 72 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_LOADING_SCREEN = 73 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_WEATHER = 74 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_HEROIC_STATUE = 75 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MULTIKILL_BANNER = 76 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_CURSOR_PACK = 77 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TELEPORT_EFFECT = 78 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_BLINK_EFFECT = 79 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_EMBLEM = 80 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TERRAIN = 81 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_RADIANT_CREEPS = 82 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_DIRE_CREEPS = 83 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_RADIANT_TOWER = 84 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_DIRE_TOWER = 85 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_VERSUS_SCREEN = 86 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_STREAK_EFFECT = 87 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_KILL_EFFECT = 88 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_DEATH_EFFECT = 89 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_HEAD_EFFECT = 90 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_MAP_EFFECT = 91 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_COURIER_EFFECT = 92 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_RADIANT_SIEGE_CREEPS = 93 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_DIRE_SIEGE_CREEPS = 94 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_ROSHAN = 95 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_TORMENTOR = 96 ---- @type DOTASlotType_t -DOTA_PLAYER_LOADOUT_END = 96 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_NONE = 97 ---- @type DOTASlotType_t -DOTA_LOADOUT_TYPE_COUNT = 98 +--- @enum DOTASlotType_t +--- @field DOTA_LOADOUT_TYPE_INVALID -1 +--- @field DOTA_LOADOUT_TYPE_WEAPON 0 +--- @field DOTA_LOADOUT_TYPE_OFFHAND_WEAPON 1 +--- @field DOTA_LOADOUT_TYPE_WEAPON2 2 +--- @field DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2 3 +--- @field DOTA_LOADOUT_TYPE_HEAD 4 +--- @field DOTA_LOADOUT_TYPE_SHOULDER 5 +--- @field DOTA_LOADOUT_TYPE_ARMS 6 +--- @field DOTA_LOADOUT_TYPE_ARMOR 7 +--- @field DOTA_LOADOUT_TYPE_BELT 8 +--- @field DOTA_LOADOUT_TYPE_NECK 9 +--- @field DOTA_LOADOUT_TYPE_BACK 10 +--- @field DOTA_LOADOUT_TYPE_GLOVES 11 +--- @field DOTA_LOADOUT_TYPE_LEGS 12 +--- @field DOTA_LOADOUT_TYPE_TAIL 13 +--- @field DOTA_LOADOUT_TYPE_MISC 14 +--- @field DOTA_LOADOUT_TYPE_COSTUME 15 +--- @field DOTA_LOADOUT_TYPE_HERO_BASE 16 +--- @field DOTA_LOADOUT_TYPE_BODY_HEAD 17 +--- @field DOTA_LOADOUT_TYPE_MOUNT 18 +--- @field DOTA_LOADOUT_TYPE_SUMMON 19 +--- @field DOTA_LOADOUT_TYPE_SHAPESHIFT 20 +--- @field DOTA_LOADOUT_TYPE_TAUNT 21 +--- @field DOTA_LOADOUT_TYPE_HERO_EFFIGY 22 +--- @field DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS 23 +--- @field DOTA_LOADOUT_TYPE_ABILITY_ATTACK 24 +--- @field DOTA_LOADOUT_TYPE_ABILITY1 25 +--- @field DOTA_LOADOUT_TYPE_ABILITY2 26 +--- @field DOTA_LOADOUT_TYPE_ABILITY3 27 +--- @field DOTA_LOADOUT_TYPE_ABILITY4 28 +--- @field DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE 29 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_1 30 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_2 31 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_3 32 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_4 33 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_5 34 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_6 35 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_7 36 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_8 37 +--- @field DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_9 38 +--- @field DOTA_LOADOUT_TYPE_VOICE 39 +--- @field DOTA_LOADOUT_PERSONA_1_START 40 +--- @field DOTA_LOADOUT_TYPE_WEAPON_PERSONA_1 40 +--- @field DOTA_LOADOUT_TYPE_OFFHAND_WEAPON_PERSONA_1 41 +--- @field DOTA_LOADOUT_TYPE_WEAPON2_PERSONA_1 42 +--- @field DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2_PERSONA_1 43 +--- @field DOTA_LOADOUT_TYPE_HEAD_PERSONA_1 44 +--- @field DOTA_LOADOUT_TYPE_SHOULDER_PERSONA_1 45 +--- @field DOTA_LOADOUT_TYPE_ARMS_PERSONA_1 46 +--- @field DOTA_LOADOUT_TYPE_ARMOR_PERSONA_1 47 +--- @field DOTA_LOADOUT_TYPE_BELT_PERSONA_1 48 +--- @field DOTA_LOADOUT_TYPE_NECK_PERSONA_1 49 +--- @field DOTA_LOADOUT_TYPE_BACK_PERSONA_1 50 +--- @field DOTA_LOADOUT_TYPE_LEGS_PERSONA_1 51 +--- @field DOTA_LOADOUT_TYPE_GLOVES_PERSONA_1 52 +--- @field DOTA_LOADOUT_TYPE_TAIL_PERSONA_1 53 +--- @field DOTA_LOADOUT_TYPE_MISC_PERSONA_1 54 +--- @field DOTA_LOADOUT_TYPE_BODY_HEAD_PERSONA_1 55 +--- @field DOTA_LOADOUT_TYPE_MOUNT_PERSONA_1 56 +--- @field DOTA_LOADOUT_TYPE_SUMMON_PERSONA_1 57 +--- @field DOTA_LOADOUT_TYPE_SHAPESHIFT_PERSONA_1 58 +--- @field DOTA_LOADOUT_TYPE_TAUNT_PERSONA_1 59 +--- @field DOTA_LOADOUT_TYPE_HERO_EFFIGY_PERSONA_1 60 +--- @field DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS_PERSONA_1 61 +--- @field DOTA_LOADOUT_TYPE_ABILITY_ATTACK_PERSONA_1 62 +--- @field DOTA_LOADOUT_TYPE_ABILITY1_PERSONA_1 63 +--- @field DOTA_LOADOUT_TYPE_ABILITY2_PERSONA_1 64 +--- @field DOTA_LOADOUT_TYPE_ABILITY3_PERSONA_1 65 +--- @field DOTA_LOADOUT_TYPE_ABILITY4_PERSONA_1 66 +--- @field DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE_PERSONA_1 67 +--- @field DOTA_LOADOUT_PERSONA_1_END 68 +--- @field DOTA_LOADOUT_TYPE_VOICE_PERSONA_1 68 +--- @field DOTA_LOADOUT_TYPE_PERSONA_SELECTOR 69 +--- @field DOTA_LOADOUT_TYPE_COURIER 70 +--- @field DOTA_PLAYER_LOADOUT_START 70 +--- @field DOTA_LOADOUT_TYPE_ANNOUNCER 71 +--- @field DOTA_LOADOUT_TYPE_MEGA_KILLS 72 +--- @field DOTA_LOADOUT_TYPE_MUSIC 73 +--- @field DOTA_LOADOUT_TYPE_WARD 74 +--- @field DOTA_LOADOUT_TYPE_HUD_SKIN 75 +--- @field DOTA_LOADOUT_TYPE_LOADING_SCREEN 76 +--- @field DOTA_LOADOUT_TYPE_WEATHER 77 +--- @field DOTA_LOADOUT_TYPE_HEROIC_STATUE 78 +--- @field DOTA_LOADOUT_TYPE_MULTIKILL_BANNER 79 +--- @field DOTA_LOADOUT_TYPE_CURSOR_PACK 80 +--- @field DOTA_LOADOUT_TYPE_TELEPORT_EFFECT 81 +--- @field DOTA_LOADOUT_TYPE_BLINK_EFFECT 82 +--- @field DOTA_LOADOUT_TYPE_EMBLEM 83 +--- @field DOTA_LOADOUT_TYPE_TERRAIN 84 +--- @field DOTA_LOADOUT_TYPE_RADIANT_CREEPS 85 +--- @field DOTA_LOADOUT_TYPE_DIRE_CREEPS 86 +--- @field DOTA_LOADOUT_TYPE_RADIANT_TOWER 87 +--- @field DOTA_LOADOUT_TYPE_DIRE_TOWER 88 +--- @field DOTA_LOADOUT_TYPE_VERSUS_SCREEN 89 +--- @field DOTA_LOADOUT_TYPE_STREAK_EFFECT 90 +--- @field DOTA_LOADOUT_TYPE_KILL_EFFECT 91 +--- @field DOTA_LOADOUT_TYPE_DEATH_EFFECT 92 +--- @field DOTA_LOADOUT_TYPE_HEAD_EFFECT 93 +--- @field DOTA_LOADOUT_TYPE_MAP_EFFECT 94 +--- @field DOTA_LOADOUT_TYPE_COURIER_EFFECT 95 +--- @field DOTA_LOADOUT_TYPE_RADIANT_SIEGE_CREEPS 96 +--- @field DOTA_LOADOUT_TYPE_DIRE_SIEGE_CREEPS 97 +--- @field DOTA_LOADOUT_TYPE_ROSHAN 98 +--- @field DOTA_LOADOUT_TYPE_TORMENTOR 99 +--- @field DOTA_LOADOUT_TYPE_ANCIENT 100 +--- @field DOTA_PLAYER_LOADOUT_END 100 +--- @field DOTA_LOADOUT_TYPE_NONE 101 +--- @field DOTA_LOADOUT_TYPE_COUNT 102 +local DOTASlotType_t = {} +DOTA_LOADOUT_TYPE_INVALID = DOTASlotType_t.DOTA_LOADOUT_TYPE_INVALID +DOTA_LOADOUT_TYPE_WEAPON = DOTASlotType_t.DOTA_LOADOUT_TYPE_WEAPON +DOTA_LOADOUT_TYPE_OFFHAND_WEAPON = DOTASlotType_t.DOTA_LOADOUT_TYPE_OFFHAND_WEAPON +DOTA_LOADOUT_TYPE_WEAPON2 = DOTASlotType_t.DOTA_LOADOUT_TYPE_WEAPON2 +DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2 = DOTASlotType_t.DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2 +DOTA_LOADOUT_TYPE_HEAD = DOTASlotType_t.DOTA_LOADOUT_TYPE_HEAD +DOTA_LOADOUT_TYPE_SHOULDER = DOTASlotType_t.DOTA_LOADOUT_TYPE_SHOULDER +DOTA_LOADOUT_TYPE_ARMS = DOTASlotType_t.DOTA_LOADOUT_TYPE_ARMS +DOTA_LOADOUT_TYPE_ARMOR = DOTASlotType_t.DOTA_LOADOUT_TYPE_ARMOR +DOTA_LOADOUT_TYPE_BELT = DOTASlotType_t.DOTA_LOADOUT_TYPE_BELT +DOTA_LOADOUT_TYPE_NECK = DOTASlotType_t.DOTA_LOADOUT_TYPE_NECK +DOTA_LOADOUT_TYPE_BACK = DOTASlotType_t.DOTA_LOADOUT_TYPE_BACK +DOTA_LOADOUT_TYPE_GLOVES = DOTASlotType_t.DOTA_LOADOUT_TYPE_GLOVES +DOTA_LOADOUT_TYPE_LEGS = DOTASlotType_t.DOTA_LOADOUT_TYPE_LEGS +DOTA_LOADOUT_TYPE_TAIL = DOTASlotType_t.DOTA_LOADOUT_TYPE_TAIL +DOTA_LOADOUT_TYPE_MISC = DOTASlotType_t.DOTA_LOADOUT_TYPE_MISC +DOTA_LOADOUT_TYPE_COSTUME = DOTASlotType_t.DOTA_LOADOUT_TYPE_COSTUME +DOTA_LOADOUT_TYPE_HERO_BASE = DOTASlotType_t.DOTA_LOADOUT_TYPE_HERO_BASE +DOTA_LOADOUT_TYPE_BODY_HEAD = DOTASlotType_t.DOTA_LOADOUT_TYPE_BODY_HEAD +DOTA_LOADOUT_TYPE_MOUNT = DOTASlotType_t.DOTA_LOADOUT_TYPE_MOUNT +DOTA_LOADOUT_TYPE_SUMMON = DOTASlotType_t.DOTA_LOADOUT_TYPE_SUMMON +DOTA_LOADOUT_TYPE_SHAPESHIFT = DOTASlotType_t.DOTA_LOADOUT_TYPE_SHAPESHIFT +DOTA_LOADOUT_TYPE_TAUNT = DOTASlotType_t.DOTA_LOADOUT_TYPE_TAUNT +DOTA_LOADOUT_TYPE_HERO_EFFIGY = DOTASlotType_t.DOTA_LOADOUT_TYPE_HERO_EFFIGY +DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS = DOTASlotType_t.DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS +DOTA_LOADOUT_TYPE_ABILITY_ATTACK = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_ATTACK +DOTA_LOADOUT_TYPE_ABILITY1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY1 +DOTA_LOADOUT_TYPE_ABILITY2 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY2 +DOTA_LOADOUT_TYPE_ABILITY3 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY3 +DOTA_LOADOUT_TYPE_ABILITY4 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY4 +DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_1 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_2 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_2 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_3 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_3 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_4 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_4 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_5 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_5 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_6 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_6 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_7 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_7 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_8 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_8 +DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_9 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_EFFECTS_9 +DOTA_LOADOUT_TYPE_VOICE = DOTASlotType_t.DOTA_LOADOUT_TYPE_VOICE +DOTA_LOADOUT_PERSONA_1_START = DOTASlotType_t.DOTA_LOADOUT_PERSONA_1_START +DOTA_LOADOUT_TYPE_WEAPON_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_WEAPON_PERSONA_1 +DOTA_LOADOUT_TYPE_OFFHAND_WEAPON_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_OFFHAND_WEAPON_PERSONA_1 +DOTA_LOADOUT_TYPE_WEAPON2_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_WEAPON2_PERSONA_1 +DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_OFFHAND_WEAPON2_PERSONA_1 +DOTA_LOADOUT_TYPE_HEAD_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_HEAD_PERSONA_1 +DOTA_LOADOUT_TYPE_SHOULDER_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_SHOULDER_PERSONA_1 +DOTA_LOADOUT_TYPE_ARMS_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ARMS_PERSONA_1 +DOTA_LOADOUT_TYPE_ARMOR_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ARMOR_PERSONA_1 +DOTA_LOADOUT_TYPE_BELT_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_BELT_PERSONA_1 +DOTA_LOADOUT_TYPE_NECK_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_NECK_PERSONA_1 +DOTA_LOADOUT_TYPE_BACK_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_BACK_PERSONA_1 +DOTA_LOADOUT_TYPE_LEGS_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_LEGS_PERSONA_1 +DOTA_LOADOUT_TYPE_GLOVES_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_GLOVES_PERSONA_1 +DOTA_LOADOUT_TYPE_TAIL_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_TAIL_PERSONA_1 +DOTA_LOADOUT_TYPE_MISC_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_MISC_PERSONA_1 +DOTA_LOADOUT_TYPE_BODY_HEAD_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_BODY_HEAD_PERSONA_1 +DOTA_LOADOUT_TYPE_MOUNT_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_MOUNT_PERSONA_1 +DOTA_LOADOUT_TYPE_SUMMON_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_SUMMON_PERSONA_1 +DOTA_LOADOUT_TYPE_SHAPESHIFT_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_SHAPESHIFT_PERSONA_1 +DOTA_LOADOUT_TYPE_TAUNT_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_TAUNT_PERSONA_1 +DOTA_LOADOUT_TYPE_HERO_EFFIGY_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_HERO_EFFIGY_PERSONA_1 +DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS_PERSONA_1 +DOTA_LOADOUT_TYPE_ABILITY_ATTACK_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_ATTACK_PERSONA_1 +DOTA_LOADOUT_TYPE_ABILITY1_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY1_PERSONA_1 +DOTA_LOADOUT_TYPE_ABILITY2_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY2_PERSONA_1 +DOTA_LOADOUT_TYPE_ABILITY3_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY3_PERSONA_1 +DOTA_LOADOUT_TYPE_ABILITY4_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY4_PERSONA_1 +DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_ABILITY_ULTIMATE_PERSONA_1 +DOTA_LOADOUT_PERSONA_1_END = DOTASlotType_t.DOTA_LOADOUT_PERSONA_1_END +DOTA_LOADOUT_TYPE_VOICE_PERSONA_1 = DOTASlotType_t.DOTA_LOADOUT_TYPE_VOICE_PERSONA_1 +DOTA_LOADOUT_TYPE_PERSONA_SELECTOR = DOTASlotType_t.DOTA_LOADOUT_TYPE_PERSONA_SELECTOR +DOTA_LOADOUT_TYPE_COURIER = DOTASlotType_t.DOTA_LOADOUT_TYPE_COURIER +DOTA_PLAYER_LOADOUT_START = DOTASlotType_t.DOTA_PLAYER_LOADOUT_START +DOTA_LOADOUT_TYPE_ANNOUNCER = DOTASlotType_t.DOTA_LOADOUT_TYPE_ANNOUNCER +DOTA_LOADOUT_TYPE_MEGA_KILLS = DOTASlotType_t.DOTA_LOADOUT_TYPE_MEGA_KILLS +DOTA_LOADOUT_TYPE_MUSIC = DOTASlotType_t.DOTA_LOADOUT_TYPE_MUSIC +DOTA_LOADOUT_TYPE_WARD = DOTASlotType_t.DOTA_LOADOUT_TYPE_WARD +DOTA_LOADOUT_TYPE_HUD_SKIN = DOTASlotType_t.DOTA_LOADOUT_TYPE_HUD_SKIN +DOTA_LOADOUT_TYPE_LOADING_SCREEN = DOTASlotType_t.DOTA_LOADOUT_TYPE_LOADING_SCREEN +DOTA_LOADOUT_TYPE_WEATHER = DOTASlotType_t.DOTA_LOADOUT_TYPE_WEATHER +DOTA_LOADOUT_TYPE_HEROIC_STATUE = DOTASlotType_t.DOTA_LOADOUT_TYPE_HEROIC_STATUE +DOTA_LOADOUT_TYPE_MULTIKILL_BANNER = DOTASlotType_t.DOTA_LOADOUT_TYPE_MULTIKILL_BANNER +DOTA_LOADOUT_TYPE_CURSOR_PACK = DOTASlotType_t.DOTA_LOADOUT_TYPE_CURSOR_PACK +DOTA_LOADOUT_TYPE_TELEPORT_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_TELEPORT_EFFECT +DOTA_LOADOUT_TYPE_BLINK_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_BLINK_EFFECT +DOTA_LOADOUT_TYPE_EMBLEM = DOTASlotType_t.DOTA_LOADOUT_TYPE_EMBLEM +DOTA_LOADOUT_TYPE_TERRAIN = DOTASlotType_t.DOTA_LOADOUT_TYPE_TERRAIN +DOTA_LOADOUT_TYPE_RADIANT_CREEPS = DOTASlotType_t.DOTA_LOADOUT_TYPE_RADIANT_CREEPS +DOTA_LOADOUT_TYPE_DIRE_CREEPS = DOTASlotType_t.DOTA_LOADOUT_TYPE_DIRE_CREEPS +DOTA_LOADOUT_TYPE_RADIANT_TOWER = DOTASlotType_t.DOTA_LOADOUT_TYPE_RADIANT_TOWER +DOTA_LOADOUT_TYPE_DIRE_TOWER = DOTASlotType_t.DOTA_LOADOUT_TYPE_DIRE_TOWER +DOTA_LOADOUT_TYPE_VERSUS_SCREEN = DOTASlotType_t.DOTA_LOADOUT_TYPE_VERSUS_SCREEN +DOTA_LOADOUT_TYPE_STREAK_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_STREAK_EFFECT +DOTA_LOADOUT_TYPE_KILL_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_KILL_EFFECT +DOTA_LOADOUT_TYPE_DEATH_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_DEATH_EFFECT +DOTA_LOADOUT_TYPE_HEAD_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_HEAD_EFFECT +DOTA_LOADOUT_TYPE_MAP_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_MAP_EFFECT +DOTA_LOADOUT_TYPE_COURIER_EFFECT = DOTASlotType_t.DOTA_LOADOUT_TYPE_COURIER_EFFECT +DOTA_LOADOUT_TYPE_RADIANT_SIEGE_CREEPS = DOTASlotType_t.DOTA_LOADOUT_TYPE_RADIANT_SIEGE_CREEPS +DOTA_LOADOUT_TYPE_DIRE_SIEGE_CREEPS = DOTASlotType_t.DOTA_LOADOUT_TYPE_DIRE_SIEGE_CREEPS +DOTA_LOADOUT_TYPE_ROSHAN = DOTASlotType_t.DOTA_LOADOUT_TYPE_ROSHAN +DOTA_LOADOUT_TYPE_TORMENTOR = DOTASlotType_t.DOTA_LOADOUT_TYPE_TORMENTOR +DOTA_LOADOUT_TYPE_ANCIENT = DOTASlotType_t.DOTA_LOADOUT_TYPE_ANCIENT +DOTA_PLAYER_LOADOUT_END = DOTASlotType_t.DOTA_PLAYER_LOADOUT_END +DOTA_LOADOUT_TYPE_NONE = DOTASlotType_t.DOTA_LOADOUT_TYPE_NONE +DOTA_LOADOUT_TYPE_COUNT = DOTASlotType_t.DOTA_LOADOUT_TYPE_COUNT --- (availability: server & client) ---- @alias DOTASpeechType_t ---- | `DOTA_SPEECH_USER_INVALID` ---- | `DOTA_SPEECH_USER_SINGLE` ---- | `DOTA_SPEECH_USER_TEAM` ---- | `DOTA_SPEECH_USER_TEAM_NEARBY` ---- | `DOTA_SPEECH_USER_NEARBY` ---- | `DOTA_SPEECH_USER_ALL` ---- | `DOTA_SPEECH_GOOD_TEAM` ---- | `DOTA_SPEECH_BAD_TEAM` ---- | `DOTA_SPEECH_SPECTATOR` ---- | `DOTA_SPEECH_USER_TEAM_NOSPECTATOR` ---- | `DOTA_SPEECH_RECIPIENT_TYPE_MAX` - ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_INVALID = 0 ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_SINGLE = 1 ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_TEAM = 2 ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_TEAM_NEARBY = 3 ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_NEARBY = 4 ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_ALL = 5 ---- @type DOTASpeechType_t -DOTA_SPEECH_GOOD_TEAM = 6 ---- @type DOTASpeechType_t -DOTA_SPEECH_BAD_TEAM = 7 ---- @type DOTASpeechType_t -DOTA_SPEECH_SPECTATOR = 8 ---- @type DOTASpeechType_t -DOTA_SPEECH_USER_TEAM_NOSPECTATOR = 9 ---- @type DOTASpeechType_t -DOTA_SPEECH_RECIPIENT_TYPE_MAX = 10 +--- @enum DOTASpeechType_t +--- @field DOTA_SPEECH_USER_INVALID 0 +--- @field DOTA_SPEECH_USER_SINGLE 1 +--- @field DOTA_SPEECH_USER_TEAM 2 +--- @field DOTA_SPEECH_USER_TEAM_NEARBY 3 +--- @field DOTA_SPEECH_USER_NEARBY 4 +--- @field DOTA_SPEECH_USER_ALL 5 +--- @field DOTA_SPEECH_GOOD_TEAM 6 +--- @field DOTA_SPEECH_BAD_TEAM 7 +--- @field DOTA_SPEECH_SPECTATOR 8 +--- @field DOTA_SPEECH_USER_TEAM_NOSPECTATOR 9 +--- @field DOTA_SPEECH_RECIPIENT_TYPE_MAX 10 +local DOTASpeechType_t = {} +DOTA_SPEECH_USER_INVALID = DOTASpeechType_t.DOTA_SPEECH_USER_INVALID +DOTA_SPEECH_USER_SINGLE = DOTASpeechType_t.DOTA_SPEECH_USER_SINGLE +DOTA_SPEECH_USER_TEAM = DOTASpeechType_t.DOTA_SPEECH_USER_TEAM +DOTA_SPEECH_USER_TEAM_NEARBY = DOTASpeechType_t.DOTA_SPEECH_USER_TEAM_NEARBY +DOTA_SPEECH_USER_NEARBY = DOTASpeechType_t.DOTA_SPEECH_USER_NEARBY +DOTA_SPEECH_USER_ALL = DOTASpeechType_t.DOTA_SPEECH_USER_ALL +DOTA_SPEECH_GOOD_TEAM = DOTASpeechType_t.DOTA_SPEECH_GOOD_TEAM +DOTA_SPEECH_BAD_TEAM = DOTASpeechType_t.DOTA_SPEECH_BAD_TEAM +DOTA_SPEECH_SPECTATOR = DOTASpeechType_t.DOTA_SPEECH_SPECTATOR +DOTA_SPEECH_USER_TEAM_NOSPECTATOR = DOTASpeechType_t.DOTA_SPEECH_USER_TEAM_NOSPECTATOR +DOTA_SPEECH_RECIPIENT_TYPE_MAX = DOTASpeechType_t.DOTA_SPEECH_RECIPIENT_TYPE_MAX --- (availability: server & client) ---- @alias DOTATeam_t ---- | `DOTA_TEAM_FIRST` ---- | `DOTA_TEAM_GOODGUYS` ---- | `DOTA_TEAM_BADGUYS` ---- | `DOTA_TEAM_NEUTRALS` ---- | `DOTA_TEAM_NOTEAM` ---- | `DOTA_TEAM_CUSTOM_1` ---- | `DOTA_TEAM_CUSTOM_MIN` ---- | `DOTA_TEAM_CUSTOM_2` ---- | `DOTA_TEAM_CUSTOM_3` ---- | `DOTA_TEAM_CUSTOM_COUNT` ---- | `DOTA_TEAM_CUSTOM_4` ---- | `DOTA_TEAM_CUSTOM_5` ---- | `DOTA_TEAM_CUSTOM_6` ---- | `DOTA_TEAM_CUSTOM_7` ---- | `DOTA_TEAM_CUSTOM_8` ---- | `DOTA_TEAM_CUSTOM_MAX` ---- | `DOTA_TEAM_DRAFT_POOL` ---- | `DOTA_TEAM_COUNT` - ---- @type DOTATeam_t -DOTA_TEAM_FIRST = 2 ---- @type DOTATeam_t -DOTA_TEAM_GOODGUYS = 2 ---- @type DOTATeam_t -DOTA_TEAM_BADGUYS = 3 ---- @type DOTATeam_t -DOTA_TEAM_NEUTRALS = 4 ---- @type DOTATeam_t -DOTA_TEAM_NOTEAM = 5 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_1 = 6 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_MIN = 6 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_2 = 7 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_3 = 8 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_COUNT = 8 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_4 = 9 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_5 = 10 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_6 = 11 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_7 = 12 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_8 = 13 ---- @type DOTATeam_t -DOTA_TEAM_CUSTOM_MAX = 13 ---- @type DOTATeam_t -DOTA_TEAM_DRAFT_POOL = 14 ---- @type DOTATeam_t -DOTA_TEAM_COUNT = 15 +--- @enum DOTATeam_t +--- @field DOTA_TEAM_FIRST 2 +--- @field DOTA_TEAM_GOODGUYS 2 +--- @field DOTA_TEAM_BADGUYS 3 +--- @field DOTA_TEAM_NEUTRALS 4 +--- @field DOTA_TEAM_NOTEAM 5 +--- @field DOTA_TEAM_CUSTOM_1 6 +--- @field DOTA_TEAM_CUSTOM_MIN 6 +--- @field DOTA_TEAM_CUSTOM_2 7 +--- @field DOTA_TEAM_CUSTOM_3 8 +--- @field DOTA_TEAM_CUSTOM_COUNT 8 +--- @field DOTA_TEAM_CUSTOM_4 9 +--- @field DOTA_TEAM_CUSTOM_5 10 +--- @field DOTA_TEAM_CUSTOM_6 11 +--- @field DOTA_TEAM_CUSTOM_7 12 +--- @field DOTA_TEAM_CUSTOM_8 13 +--- @field DOTA_TEAM_CUSTOM_MAX 13 +--- @field DOTA_TEAM_DRAFT_POOL 14 +--- @field DOTA_TEAM_COUNT 15 +local DOTATeam_t = {} +DOTA_TEAM_FIRST = DOTATeam_t.DOTA_TEAM_FIRST +DOTA_TEAM_GOODGUYS = DOTATeam_t.DOTA_TEAM_GOODGUYS +DOTA_TEAM_BADGUYS = DOTATeam_t.DOTA_TEAM_BADGUYS +DOTA_TEAM_NEUTRALS = DOTATeam_t.DOTA_TEAM_NEUTRALS +DOTA_TEAM_NOTEAM = DOTATeam_t.DOTA_TEAM_NOTEAM +DOTA_TEAM_CUSTOM_1 = DOTATeam_t.DOTA_TEAM_CUSTOM_1 +DOTA_TEAM_CUSTOM_MIN = DOTATeam_t.DOTA_TEAM_CUSTOM_MIN +DOTA_TEAM_CUSTOM_2 = DOTATeam_t.DOTA_TEAM_CUSTOM_2 +DOTA_TEAM_CUSTOM_3 = DOTATeam_t.DOTA_TEAM_CUSTOM_3 +DOTA_TEAM_CUSTOM_COUNT = DOTATeam_t.DOTA_TEAM_CUSTOM_COUNT +DOTA_TEAM_CUSTOM_4 = DOTATeam_t.DOTA_TEAM_CUSTOM_4 +DOTA_TEAM_CUSTOM_5 = DOTATeam_t.DOTA_TEAM_CUSTOM_5 +DOTA_TEAM_CUSTOM_6 = DOTATeam_t.DOTA_TEAM_CUSTOM_6 +DOTA_TEAM_CUSTOM_7 = DOTATeam_t.DOTA_TEAM_CUSTOM_7 +DOTA_TEAM_CUSTOM_8 = DOTATeam_t.DOTA_TEAM_CUSTOM_8 +DOTA_TEAM_CUSTOM_MAX = DOTATeam_t.DOTA_TEAM_CUSTOM_MAX +DOTA_TEAM_DRAFT_POOL = DOTATeam_t.DOTA_TEAM_DRAFT_POOL +DOTA_TEAM_COUNT = DOTATeam_t.DOTA_TEAM_COUNT --- (availability: server) ---- @alias DOTAUnitAttackCapability_t ---- | `DOTA_UNIT_CAP_NO_ATTACK` ---- | `DOTA_UNIT_CAP_MELEE_ATTACK` ---- | `DOTA_UNIT_CAP_RANGED_ATTACK` ---- | `DOTA_UNIT_ATTACK_CAPABILITY_BIT_COUNT` ---- | `DOTA_UNIT_CAP_RANGED_ATTACK_DIRECTIONAL` - ---- @type DOTAUnitAttackCapability_t -DOTA_UNIT_CAP_NO_ATTACK = 0 ---- @type DOTAUnitAttackCapability_t -DOTA_UNIT_CAP_MELEE_ATTACK = 1 ---- @type DOTAUnitAttackCapability_t -DOTA_UNIT_CAP_RANGED_ATTACK = 2 ---- @type DOTAUnitAttackCapability_t -DOTA_UNIT_ATTACK_CAPABILITY_BIT_COUNT = 3 ---- @type DOTAUnitAttackCapability_t -DOTA_UNIT_CAP_RANGED_ATTACK_DIRECTIONAL = 4 +--- @enum DOTAUnitAttackCapability_t +--- @field DOTA_UNIT_CAP_NO_ATTACK 0 +--- @field DOTA_UNIT_CAP_MELEE_ATTACK 1 +--- @field DOTA_UNIT_CAP_RANGED_ATTACK 2 +--- @field DOTA_UNIT_ATTACK_CAPABILITY_BIT_COUNT 3 +--- @field DOTA_UNIT_CAP_RANGED_ATTACK_DIRECTIONAL 4 +local DOTAUnitAttackCapability_t = {} +DOTA_UNIT_CAP_NO_ATTACK = DOTAUnitAttackCapability_t.DOTA_UNIT_CAP_NO_ATTACK +DOTA_UNIT_CAP_MELEE_ATTACK = DOTAUnitAttackCapability_t.DOTA_UNIT_CAP_MELEE_ATTACK +DOTA_UNIT_CAP_RANGED_ATTACK = DOTAUnitAttackCapability_t.DOTA_UNIT_CAP_RANGED_ATTACK +DOTA_UNIT_ATTACK_CAPABILITY_BIT_COUNT = DOTAUnitAttackCapability_t.DOTA_UNIT_ATTACK_CAPABILITY_BIT_COUNT +DOTA_UNIT_CAP_RANGED_ATTACK_DIRECTIONAL = DOTAUnitAttackCapability_t.DOTA_UNIT_CAP_RANGED_ATTACK_DIRECTIONAL --- (availability: server) ---- @alias DOTAUnitMoveCapability_t ---- | `DOTA_UNIT_CAP_MOVE_NONE` ---- | `DOTA_UNIT_CAP_MOVE_GROUND` ---- | `DOTA_UNIT_CAP_MOVE_FLY` - ---- @type DOTAUnitMoveCapability_t -DOTA_UNIT_CAP_MOVE_NONE = 0 ---- @type DOTAUnitMoveCapability_t -DOTA_UNIT_CAP_MOVE_GROUND = 1 ---- @type DOTAUnitMoveCapability_t -DOTA_UNIT_CAP_MOVE_FLY = 2 +--- @enum DOTAUnitMoveCapability_t +--- @field DOTA_UNIT_CAP_MOVE_NONE 0 +--- @field DOTA_UNIT_CAP_MOVE_GROUND 1 +--- @field DOTA_UNIT_CAP_MOVE_FLY 2 +local DOTAUnitMoveCapability_t = {} +DOTA_UNIT_CAP_MOVE_NONE = DOTAUnitMoveCapability_t.DOTA_UNIT_CAP_MOVE_NONE +DOTA_UNIT_CAP_MOVE_GROUND = DOTAUnitMoveCapability_t.DOTA_UNIT_CAP_MOVE_GROUND +DOTA_UNIT_CAP_MOVE_FLY = DOTAUnitMoveCapability_t.DOTA_UNIT_CAP_MOVE_FLY --- (availability: server) ---- @alias dotaunitorder_t ---- | `DOTA_UNIT_ORDER_NONE` ---- | `DOTA_UNIT_ORDER_MOVE_TO_POSITION` ---- | `DOTA_UNIT_ORDER_MOVE_TO_TARGET` ---- | `DOTA_UNIT_ORDER_ATTACK_MOVE` ---- | `DOTA_UNIT_ORDER_ATTACK_TARGET` ---- | `DOTA_UNIT_ORDER_CAST_POSITION` ---- | `DOTA_UNIT_ORDER_CAST_TARGET` ---- | `DOTA_UNIT_ORDER_CAST_TARGET_TREE` ---- | `DOTA_UNIT_ORDER_CAST_NO_TARGET` ---- | `DOTA_UNIT_ORDER_CAST_TOGGLE` ---- | `DOTA_UNIT_ORDER_HOLD_POSITION` ---- | `DOTA_UNIT_ORDER_TRAIN_ABILITY` ---- | `DOTA_UNIT_ORDER_DROP_ITEM` ---- | `DOTA_UNIT_ORDER_GIVE_ITEM` ---- | `DOTA_UNIT_ORDER_PICKUP_ITEM` ---- | `DOTA_UNIT_ORDER_PICKUP_RUNE` ---- | `DOTA_UNIT_ORDER_PURCHASE_ITEM` ---- | `DOTA_UNIT_ORDER_SELL_ITEM` ---- | `DOTA_UNIT_ORDER_DISASSEMBLE_ITEM` ---- | `DOTA_UNIT_ORDER_MOVE_ITEM` ---- | `DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO` ---- | `DOTA_UNIT_ORDER_STOP` ---- | `DOTA_UNIT_ORDER_TAUNT` ---- | `DOTA_UNIT_ORDER_BUYBACK` ---- | `DOTA_UNIT_ORDER_GLYPH` ---- | `DOTA_UNIT_ORDER_EJECT_ITEM_FROM_STASH` ---- | `DOTA_UNIT_ORDER_CAST_RUNE` ---- | `DOTA_UNIT_ORDER_PING_ABILITY` ---- | `DOTA_UNIT_ORDER_MOVE_TO_DIRECTION` ---- | `DOTA_UNIT_ORDER_PATROL` ---- | `DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION` ---- | `DOTA_UNIT_ORDER_RADAR` ---- | `DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK` ---- | `DOTA_UNIT_ORDER_CONTINUE` ---- | `DOTA_UNIT_ORDER_VECTOR_TARGET_CANCELED` ---- | `DOTA_UNIT_ORDER_CAST_RIVER_PAINT` ---- | `DOTA_UNIT_ORDER_PREGAME_ADJUST_ITEM_ASSIGNMENT` ---- | `DOTA_UNIT_ORDER_DROP_ITEM_AT_FOUNTAIN` ---- | `DOTA_UNIT_ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH` ---- | `DOTA_UNIT_ORDER_MOVE_RELATIVE` ---- | `DOTA_UNIT_ORDER_CAST_TOGGLE_ALT` - ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_NONE = 0 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_MOVE_TO_POSITION = 1 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_MOVE_TO_TARGET = 2 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_ATTACK_MOVE = 3 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_ATTACK_TARGET = 4 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_POSITION = 5 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_TARGET = 6 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_TARGET_TREE = 7 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_NO_TARGET = 8 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_TOGGLE = 9 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_HOLD_POSITION = 10 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_TRAIN_ABILITY = 11 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_DROP_ITEM = 12 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_GIVE_ITEM = 13 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_PICKUP_ITEM = 14 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_PICKUP_RUNE = 15 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_PURCHASE_ITEM = 16 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_SELL_ITEM = 17 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_DISASSEMBLE_ITEM = 18 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_MOVE_ITEM = 19 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO = 20 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_STOP = 21 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_TAUNT = 22 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_BUYBACK = 23 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_GLYPH = 24 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_EJECT_ITEM_FROM_STASH = 25 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_RUNE = 26 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_PING_ABILITY = 27 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_MOVE_TO_DIRECTION = 28 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_PATROL = 29 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION = 30 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_RADAR = 31 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK = 32 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CONTINUE = 33 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_VECTOR_TARGET_CANCELED = 34 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_RIVER_PAINT = 35 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_PREGAME_ADJUST_ITEM_ASSIGNMENT = 36 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_DROP_ITEM_AT_FOUNTAIN = 37 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH = 38 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_MOVE_RELATIVE = 39 ---- @type dotaunitorder_t -DOTA_UNIT_ORDER_CAST_TOGGLE_ALT = 40 +--- @enum dotaunitorder_t +--- @field DOTA_UNIT_ORDER_NONE 0 +--- @field DOTA_UNIT_ORDER_MOVE_TO_POSITION 1 +--- @field DOTA_UNIT_ORDER_MOVE_TO_TARGET 2 +--- @field DOTA_UNIT_ORDER_ATTACK_MOVE 3 +--- @field DOTA_UNIT_ORDER_ATTACK_TARGET 4 +--- @field DOTA_UNIT_ORDER_CAST_POSITION 5 +--- @field DOTA_UNIT_ORDER_CAST_TARGET 6 +--- @field DOTA_UNIT_ORDER_CAST_TARGET_TREE 7 +--- @field DOTA_UNIT_ORDER_CAST_NO_TARGET 8 +--- @field DOTA_UNIT_ORDER_CAST_TOGGLE 9 +--- @field DOTA_UNIT_ORDER_HOLD_POSITION 10 +--- @field DOTA_UNIT_ORDER_TRAIN_ABILITY 11 +--- @field DOTA_UNIT_ORDER_DROP_ITEM 12 +--- @field DOTA_UNIT_ORDER_GIVE_ITEM 13 +--- @field DOTA_UNIT_ORDER_PICKUP_ITEM 14 +--- @field DOTA_UNIT_ORDER_PICKUP_RUNE 15 +--- @field DOTA_UNIT_ORDER_PURCHASE_ITEM 16 +--- @field DOTA_UNIT_ORDER_SELL_ITEM 17 +--- @field DOTA_UNIT_ORDER_DISASSEMBLE_ITEM 18 +--- @field DOTA_UNIT_ORDER_MOVE_ITEM 19 +--- @field DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO 20 +--- @field DOTA_UNIT_ORDER_STOP 21 +--- @field DOTA_UNIT_ORDER_TAUNT 22 +--- @field DOTA_UNIT_ORDER_BUYBACK 23 +--- @field DOTA_UNIT_ORDER_GLYPH 24 +--- @field DOTA_UNIT_ORDER_EJECT_ITEM_FROM_STASH 25 +--- @field DOTA_UNIT_ORDER_CAST_RUNE 26 +--- @field DOTA_UNIT_ORDER_PING_ABILITY 27 +--- @field DOTA_UNIT_ORDER_MOVE_TO_DIRECTION 28 +--- @field DOTA_UNIT_ORDER_PATROL 29 +--- @field DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION 30 +--- @field DOTA_UNIT_ORDER_RADAR 31 +--- @field DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK 32 +--- @field DOTA_UNIT_ORDER_CONTINUE 33 +--- @field DOTA_UNIT_ORDER_VECTOR_TARGET_CANCELED 34 +--- @field DOTA_UNIT_ORDER_CAST_RIVER_PAINT 35 +--- @field DOTA_UNIT_ORDER_PREGAME_ADJUST_ITEM_ASSIGNMENT 36 +--- @field DOTA_UNIT_ORDER_DROP_ITEM_AT_FOUNTAIN 37 +--- @field DOTA_UNIT_ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH 38 +--- @field DOTA_UNIT_ORDER_MOVE_RELATIVE 39 +--- @field DOTA_UNIT_ORDER_CAST_TOGGLE_ALT 40 +--- @field DOTA_UNIT_ORDER_CONSUME_ITEM 41 +--- @field DOTA_UNIT_ORDER_SET_ITEM_MARK_FOR_SELL 42 +local dotaunitorder_t = {} +DOTA_UNIT_ORDER_NONE = dotaunitorder_t.DOTA_UNIT_ORDER_NONE +DOTA_UNIT_ORDER_MOVE_TO_POSITION = dotaunitorder_t.DOTA_UNIT_ORDER_MOVE_TO_POSITION +DOTA_UNIT_ORDER_MOVE_TO_TARGET = dotaunitorder_t.DOTA_UNIT_ORDER_MOVE_TO_TARGET +DOTA_UNIT_ORDER_ATTACK_MOVE = dotaunitorder_t.DOTA_UNIT_ORDER_ATTACK_MOVE +DOTA_UNIT_ORDER_ATTACK_TARGET = dotaunitorder_t.DOTA_UNIT_ORDER_ATTACK_TARGET +DOTA_UNIT_ORDER_CAST_POSITION = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_POSITION +DOTA_UNIT_ORDER_CAST_TARGET = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_TARGET +DOTA_UNIT_ORDER_CAST_TARGET_TREE = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_TARGET_TREE +DOTA_UNIT_ORDER_CAST_NO_TARGET = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_NO_TARGET +DOTA_UNIT_ORDER_CAST_TOGGLE = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_TOGGLE +DOTA_UNIT_ORDER_HOLD_POSITION = dotaunitorder_t.DOTA_UNIT_ORDER_HOLD_POSITION +DOTA_UNIT_ORDER_TRAIN_ABILITY = dotaunitorder_t.DOTA_UNIT_ORDER_TRAIN_ABILITY +DOTA_UNIT_ORDER_DROP_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_DROP_ITEM +DOTA_UNIT_ORDER_GIVE_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_GIVE_ITEM +DOTA_UNIT_ORDER_PICKUP_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_PICKUP_ITEM +DOTA_UNIT_ORDER_PICKUP_RUNE = dotaunitorder_t.DOTA_UNIT_ORDER_PICKUP_RUNE +DOTA_UNIT_ORDER_PURCHASE_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_PURCHASE_ITEM +DOTA_UNIT_ORDER_SELL_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_SELL_ITEM +DOTA_UNIT_ORDER_DISASSEMBLE_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_DISASSEMBLE_ITEM +DOTA_UNIT_ORDER_MOVE_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_MOVE_ITEM +DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO +DOTA_UNIT_ORDER_STOP = dotaunitorder_t.DOTA_UNIT_ORDER_STOP +DOTA_UNIT_ORDER_TAUNT = dotaunitorder_t.DOTA_UNIT_ORDER_TAUNT +DOTA_UNIT_ORDER_BUYBACK = dotaunitorder_t.DOTA_UNIT_ORDER_BUYBACK +DOTA_UNIT_ORDER_GLYPH = dotaunitorder_t.DOTA_UNIT_ORDER_GLYPH +DOTA_UNIT_ORDER_EJECT_ITEM_FROM_STASH = dotaunitorder_t.DOTA_UNIT_ORDER_EJECT_ITEM_FROM_STASH +DOTA_UNIT_ORDER_CAST_RUNE = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_RUNE +DOTA_UNIT_ORDER_PING_ABILITY = dotaunitorder_t.DOTA_UNIT_ORDER_PING_ABILITY +DOTA_UNIT_ORDER_MOVE_TO_DIRECTION = dotaunitorder_t.DOTA_UNIT_ORDER_MOVE_TO_DIRECTION +DOTA_UNIT_ORDER_PATROL = dotaunitorder_t.DOTA_UNIT_ORDER_PATROL +DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION = dotaunitorder_t.DOTA_UNIT_ORDER_VECTOR_TARGET_POSITION +DOTA_UNIT_ORDER_RADAR = dotaunitorder_t.DOTA_UNIT_ORDER_RADAR +DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK = dotaunitorder_t.DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK +DOTA_UNIT_ORDER_CONTINUE = dotaunitorder_t.DOTA_UNIT_ORDER_CONTINUE +DOTA_UNIT_ORDER_VECTOR_TARGET_CANCELED = dotaunitorder_t.DOTA_UNIT_ORDER_VECTOR_TARGET_CANCELED +DOTA_UNIT_ORDER_CAST_RIVER_PAINT = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_RIVER_PAINT +DOTA_UNIT_ORDER_PREGAME_ADJUST_ITEM_ASSIGNMENT = dotaunitorder_t.DOTA_UNIT_ORDER_PREGAME_ADJUST_ITEM_ASSIGNMENT +DOTA_UNIT_ORDER_DROP_ITEM_AT_FOUNTAIN = dotaunitorder_t.DOTA_UNIT_ORDER_DROP_ITEM_AT_FOUNTAIN +DOTA_UNIT_ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH = dotaunitorder_t.DOTA_UNIT_ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH +DOTA_UNIT_ORDER_MOVE_RELATIVE = dotaunitorder_t.DOTA_UNIT_ORDER_MOVE_RELATIVE +DOTA_UNIT_ORDER_CAST_TOGGLE_ALT = dotaunitorder_t.DOTA_UNIT_ORDER_CAST_TOGGLE_ALT +DOTA_UNIT_ORDER_CONSUME_ITEM = dotaunitorder_t.DOTA_UNIT_ORDER_CONSUME_ITEM +DOTA_UNIT_ORDER_SET_ITEM_MARK_FOR_SELL = dotaunitorder_t.DOTA_UNIT_ORDER_SET_ITEM_MARK_FOR_SELL --- (availability: server) ---- @alias EDOTA_ModifyGold_Reason ---- | `DOTA_ModifyGold_Unspecified` ---- | `DOTA_ModifyGold_Death` ---- | `DOTA_ModifyGold_Buyback` ---- | `DOTA_ModifyGold_PurchaseConsumable` ---- | `DOTA_ModifyGold_PurchaseItem` ---- | `DOTA_ModifyGold_AbandonedRedistribute` ---- | `DOTA_ModifyGold_SellItem` ---- | `DOTA_ModifyGold_AbilityCost` ---- | `DOTA_ModifyGold_CheatCommand` ---- | `DOTA_ModifyGold_SelectionPenalty` ---- | `DOTA_ModifyGold_GameTick` ---- | `DOTA_ModifyGold_Building` ---- | `DOTA_ModifyGold_HeroKill` ---- | `DOTA_ModifyGold_CreepKill` ---- | `DOTA_ModifyGold_NeutralKill` ---- | `DOTA_ModifyGold_RoshanKill` ---- | `DOTA_ModifyGold_CourierKill` ---- | `DOTA_ModifyGold_BountyRune` ---- | `DOTA_ModifyGold_SharedGold` ---- | `DOTA_ModifyGold_AbilityGold` ---- | `DOTA_ModifyGold_WardKill` ---- | `DOTA_ModifyGold_CourierKilledByThisPlayer` - ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_Unspecified = 0 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_Death = 1 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_Buyback = 2 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_PurchaseConsumable = 3 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_PurchaseItem = 4 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_AbandonedRedistribute = 5 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_SellItem = 6 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_AbilityCost = 7 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_CheatCommand = 8 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_SelectionPenalty = 9 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_GameTick = 10 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_Building = 11 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_HeroKill = 12 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_CreepKill = 13 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_NeutralKill = 14 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_RoshanKill = 15 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_CourierKill = 16 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_BountyRune = 17 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_SharedGold = 18 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_AbilityGold = 19 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_WardKill = 20 ---- @type EDOTA_ModifyGold_Reason -DOTA_ModifyGold_CourierKilledByThisPlayer = 21 +--- @enum EDOTA_ModifyGold_Reason +--- @field DOTA_ModifyGold_Unspecified 0 +--- @field DOTA_ModifyGold_Death 1 +--- @field DOTA_ModifyGold_Buyback 2 +--- @field DOTA_ModifyGold_PurchaseConsumable 3 +--- @field DOTA_ModifyGold_PurchaseItem 4 +--- @field DOTA_ModifyGold_AbandonedRedistribute 5 +--- @field DOTA_ModifyGold_SellItem 6 +--- @field DOTA_ModifyGold_AbilityCost 7 +--- @field DOTA_ModifyGold_CheatCommand 8 +--- @field DOTA_ModifyGold_SelectionPenalty 9 +--- @field DOTA_ModifyGold_GameTick 10 +--- @field DOTA_ModifyGold_Building 11 +--- @field DOTA_ModifyGold_HeroKill 12 +--- @field DOTA_ModifyGold_CreepKill 13 +--- @field DOTA_ModifyGold_NeutralKill 14 +--- @field DOTA_ModifyGold_RoshanKill 15 +--- @field DOTA_ModifyGold_CourierKill 16 +--- @field DOTA_ModifyGold_BountyRune 17 +--- @field DOTA_ModifyGold_SharedGold 18 +--- @field DOTA_ModifyGold_AbilityGold 19 +--- @field DOTA_ModifyGold_WardKill 20 +--- @field DOTA_ModifyGold_CourierKilledByThisPlayer 21 +local EDOTA_ModifyGold_Reason = {} +DOTA_ModifyGold_Unspecified = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_Unspecified +DOTA_ModifyGold_Death = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_Death +DOTA_ModifyGold_Buyback = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_Buyback +DOTA_ModifyGold_PurchaseConsumable = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_PurchaseConsumable +DOTA_ModifyGold_PurchaseItem = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_PurchaseItem +DOTA_ModifyGold_AbandonedRedistribute = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_AbandonedRedistribute +DOTA_ModifyGold_SellItem = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_SellItem +DOTA_ModifyGold_AbilityCost = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_AbilityCost +DOTA_ModifyGold_CheatCommand = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_CheatCommand +DOTA_ModifyGold_SelectionPenalty = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_SelectionPenalty +DOTA_ModifyGold_GameTick = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_GameTick +DOTA_ModifyGold_Building = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_Building +DOTA_ModifyGold_HeroKill = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_HeroKill +DOTA_ModifyGold_CreepKill = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_CreepKill +DOTA_ModifyGold_NeutralKill = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_NeutralKill +DOTA_ModifyGold_RoshanKill = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_RoshanKill +DOTA_ModifyGold_CourierKill = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_CourierKill +DOTA_ModifyGold_BountyRune = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_BountyRune +DOTA_ModifyGold_SharedGold = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_SharedGold +DOTA_ModifyGold_AbilityGold = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_AbilityGold +DOTA_ModifyGold_WardKill = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_WardKill +DOTA_ModifyGold_CourierKilledByThisPlayer = EDOTA_ModifyGold_Reason.DOTA_ModifyGold_CourierKilledByThisPlayer --- (availability: server) ---- @alias EDOTA_ModifyXP_Reason ---- | `DOTA_ModifyXP_Unspecified` ---- | `DOTA_ModifyXP_HeroKill` ---- | `DOTA_ModifyXP_CreepKill` ---- | `DOTA_ModifyXP_RoshanKill` ---- | `DOTA_ModifyXP_TomeOfKnowledge` ---- | `DOTA_ModifyXP_Outpost` ---- | `DOTA_ModifyXP_MAX` - ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_Unspecified = 0 ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_HeroKill = 1 ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_CreepKill = 2 ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_RoshanKill = 3 ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_TomeOfKnowledge = 4 ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_Outpost = 5 ---- @type EDOTA_ModifyXP_Reason -DOTA_ModifyXP_MAX = 6 +--- @enum EDOTA_ModifyXP_Reason +--- @field DOTA_ModifyXP_Unspecified 0 +--- @field DOTA_ModifyXP_HeroKill 1 +--- @field DOTA_ModifyXP_CreepKill 2 +--- @field DOTA_ModifyXP_RoshanKill 3 +--- @field DOTA_ModifyXP_TomeOfKnowledge 4 +--- @field DOTA_ModifyXP_Outpost 5 +--- @field DOTA_ModifyXP_CatchUp 6 +--- @field DOTA_ModifyXP_HeroAbility 7 +--- @field DOTA_ModifyXP_MAX 8 +local EDOTA_ModifyXP_Reason = {} +DOTA_ModifyXP_Unspecified = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_Unspecified +DOTA_ModifyXP_HeroKill = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_HeroKill +DOTA_ModifyXP_CreepKill = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_CreepKill +DOTA_ModifyXP_RoshanKill = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_RoshanKill +DOTA_ModifyXP_TomeOfKnowledge = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_TomeOfKnowledge +DOTA_ModifyXP_Outpost = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_Outpost +DOTA_ModifyXP_CatchUp = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_CatchUp +DOTA_ModifyXP_HeroAbility = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_HeroAbility +DOTA_ModifyXP_MAX = EDOTA_ModifyXP_Reason.DOTA_ModifyXP_MAX --- (availability: server) ---- @alias EntityEffects ---- | `EF_NODRAW` - ---- @type EntityEffects -EF_NODRAW = 32 +--- @enum EntityEffects +--- @field EF_NODRAW 32 +local EntityEffects = {} +EF_NODRAW = EntityEffects.EF_NODRAW --- (availability: server & client) ---- @alias EntityThinkPhase ---- | `PRESIM` ---- | `PRESENSING` ---- | `POSTSENSING` - ---- @type EntityThinkPhase -PRESIM = 0 ---- @type EntityThinkPhase -PRESENSING = 1 ---- @type EntityThinkPhase -POSTSENSING = 2 +--- @enum EntityThinkPhase +--- @field PRESIM 0 +--- @field PRESENSING 1 +--- @field POSTSENSING 2 +local EntityThinkPhase = {} +PRESIM = EntityThinkPhase.PRESIM +PRESENSING = EntityThinkPhase.PRESENSING +POSTSENSING = EntityThinkPhase.POSTSENSING --- (availability: server) ---- @alias EShareAbility ---- | `ITEM_FULLY_SHAREABLE` ---- | `ITEM_PARTIALLY_SHAREABLE` ---- | `ITEM_NOT_SHAREABLE` - ---- @type EShareAbility -ITEM_FULLY_SHAREABLE = 0 ---- @type EShareAbility -ITEM_PARTIALLY_SHAREABLE = 1 ---- @type EShareAbility -ITEM_NOT_SHAREABLE = 2 +--- @enum EShareAbility +--- @field ITEM_FULLY_SHAREABLE 0 +--- @field ITEM_PARTIALLY_SHAREABLE 1 +--- @field ITEM_NOT_SHAREABLE 2 +local EShareAbility = {} +ITEM_FULLY_SHAREABLE = EShareAbility.ITEM_FULLY_SHAREABLE +ITEM_PARTIALLY_SHAREABLE = EShareAbility.ITEM_PARTIALLY_SHAREABLE +ITEM_NOT_SHAREABLE = EShareAbility.ITEM_NOT_SHAREABLE --- (availability: server & client) ---- @alias FindOrder ---- | `FIND_ANY_ORDER` ---- | `FIND_CLOSEST` ---- | `FIND_FARTHEST` - ---- @type FindOrder -FIND_ANY_ORDER = 0 ---- @type FindOrder -FIND_CLOSEST = 1 ---- @type FindOrder -FIND_FARTHEST = 2 +--- @enum FindOrder +--- @field FIND_ANY_ORDER 0 +--- @field FIND_CLOSEST 1 +--- @field FIND_FARTHEST 2 +local FindOrder = {} +FIND_ANY_ORDER = FindOrder.FIND_ANY_ORDER +FIND_CLOSEST = FindOrder.FIND_CLOSEST +FIND_FARTHEST = FindOrder.FIND_FARTHEST --- (availability: server & client) ---- @alias GameActivity_t ---- | `ACT_RESET` ---- | `ACT_IDLE` ---- | `ACT_TRANSITION` ---- | `ACT_COVER` ---- | `ACT_COVER_MED` ---- | `ACT_COVER_LOW` ---- | `ACT_WALK` ---- | `ACT_WALK_AIM` ---- | `ACT_WALK_CROUCH` ---- | `ACT_WALK_CROUCH_AIM` ---- | `ACT_RUN` ---- | `ACT_RUN_AIM` ---- | `ACT_RUN_CROUCH` ---- | `ACT_RUN_CROUCH_AIM` ---- | `ACT_RUN_PROTECTED` ---- | `ACT_SCRIPT_CUSTOM_MOVE` ---- | `ACT_RANGE_ATTACK1` ---- | `ACT_RANGE_ATTACK2` ---- | `ACT_RANGE_ATTACK1_LOW` ---- | `ACT_RANGE_ATTACK2_LOW` ---- | `ACT_DIESIMPLE` ---- | `ACT_DIEBACKWARD` ---- | `ACT_DIEFORWARD` ---- | `ACT_DIEVIOLENT` ---- | `ACT_DIERAGDOLL` ---- | `ACT_FLY` ---- | `ACT_HOVER` ---- | `ACT_GLIDE` ---- | `ACT_SWIM` ---- | `ACT_JUMP` ---- | `ACT_HOP` ---- | `ACT_LEAP` ---- | `ACT_LAND` ---- | `ACT_CLIMB_UP` ---- | `ACT_CLIMB_DOWN` ---- | `ACT_CLIMB_DISMOUNT` ---- | `ACT_SHIPLADDER_UP` ---- | `ACT_SHIPLADDER_DOWN` ---- | `ACT_STRAFE_LEFT` ---- | `ACT_STRAFE_RIGHT` ---- | `ACT_ROLL_LEFT` ---- | `ACT_ROLL_RIGHT` ---- | `ACT_TURN_LEFT` ---- | `ACT_TURN_RIGHT` ---- | `ACT_CROUCH` ---- | `ACT_CROUCHIDLE` ---- | `ACT_STAND` ---- | `ACT_USE` ---- | `ACT_ALIEN_BURROW_IDLE` ---- | `ACT_ALIEN_BURROW_OUT` ---- | `ACT_SIGNAL1` ---- | `ACT_SIGNAL2` ---- | `ACT_SIGNAL3` ---- | `ACT_SIGNAL_ADVANCE` ---- | `ACT_SIGNAL_FORWARD` ---- | `ACT_SIGNAL_GROUP` ---- | `ACT_SIGNAL_HALT` ---- | `ACT_SIGNAL_LEFT` ---- | `ACT_SIGNAL_RIGHT` ---- | `ACT_SIGNAL_TAKECOVER` ---- | `ACT_LOOKBACK_RIGHT` ---- | `ACT_LOOKBACK_LEFT` ---- | `ACT_COWER` ---- | `ACT_SMALL_FLINCH` ---- | `ACT_BIG_FLINCH` ---- | `ACT_MELEE_ATTACK1` ---- | `ACT_MELEE_ATTACK2` ---- | `ACT_RELOAD` ---- | `ACT_RELOAD_START` ---- | `ACT_RELOAD_FINISH` ---- | `ACT_RELOAD_LOW` ---- | `ACT_ARM` ---- | `ACT_DISARM` ---- | `ACT_DROP_WEAPON` ---- | `ACT_DROP_WEAPON_SHOTGUN` ---- | `ACT_PICKUP_GROUND` ---- | `ACT_PICKUP_RACK` ---- | `ACT_IDLE_ANGRY` ---- | `ACT_IDLE_RELAXED` ---- | `ACT_IDLE_STIMULATED` ---- | `ACT_IDLE_AGITATED` ---- | `ACT_IDLE_STEALTH` ---- | `ACT_IDLE_HURT` ---- | `ACT_WALK_RELAXED` ---- | `ACT_WALK_STIMULATED` ---- | `ACT_WALK_AGITATED` ---- | `ACT_WALK_STEALTH` ---- | `ACT_RUN_RELAXED` ---- | `ACT_RUN_STIMULATED` ---- | `ACT_RUN_AGITATED` ---- | `ACT_RUN_STEALTH` ---- | `ACT_IDLE_AIM_RELAXED` ---- | `ACT_IDLE_AIM_STIMULATED` ---- | `ACT_IDLE_AIM_AGITATED` ---- | `ACT_IDLE_AIM_STEALTH` ---- | `ACT_WALK_AIM_RELAXED` ---- | `ACT_WALK_AIM_STIMULATED` ---- | `ACT_WALK_AIM_AGITATED` ---- | `ACT_WALK_AIM_STEALTH` ---- | `ACT_RUN_AIM_RELAXED` ---- | `ACT_RUN_AIM_STIMULATED` ---- | `ACT_RUN_AIM_AGITATED` ---- | `ACT_RUN_AIM_STEALTH` ---- | `ACT_CROUCHIDLE_STIMULATED` ---- | `ACT_CROUCHIDLE_AIM_STIMULATED` ---- | `ACT_CROUCHIDLE_AGITATED` ---- | `ACT_WALK_HURT` ---- | `ACT_RUN_HURT` ---- | `ACT_SPECIAL_ATTACK1` ---- | `ACT_SPECIAL_ATTACK2` ---- | `ACT_COMBAT_IDLE` ---- | `ACT_WALK_SCARED` ---- | `ACT_RUN_SCARED` ---- | `ACT_VICTORY_DANCE` ---- | `ACT_DIE_HEADSHOT` ---- | `ACT_DIE_CHESTSHOT` ---- | `ACT_DIE_GUTSHOT` ---- | `ACT_DIE_BACKSHOT` ---- | `ACT_FLINCH_HEAD` ---- | `ACT_FLINCH_CHEST` ---- | `ACT_FLINCH_STOMACH` ---- | `ACT_FLINCH_LEFTARM` ---- | `ACT_FLINCH_RIGHTARM` ---- | `ACT_FLINCH_LEFTLEG` ---- | `ACT_FLINCH_RIGHTLEG` ---- | `ACT_FLINCH_PHYSICS` ---- | `ACT_FLINCH_HEAD_BACK` ---- | `ACT_FLINCH_CHEST_BACK` ---- | `ACT_FLINCH_STOMACH_BACK` ---- | `ACT_FLINCH_CROUCH_FRONT` ---- | `ACT_FLINCH_CROUCH_BACK` ---- | `ACT_FLINCH_CROUCH_LEFT` ---- | `ACT_FLINCH_CROUCH_RIGHT` ---- | `ACT_IDLE_ON_FIRE` ---- | `ACT_WALK_ON_FIRE` ---- | `ACT_RUN_ON_FIRE` ---- | `ACT_180_LEFT` ---- | `ACT_180_RIGHT` ---- | `ACT_90_LEFT` ---- | `ACT_90_RIGHT` ---- | `ACT_STEP_LEFT` ---- | `ACT_STEP_RIGHT` ---- | `ACT_STEP_BACK` ---- | `ACT_STEP_FORE` ---- | `ACT_GESTURE_RANGE_ATTACK1` ---- | `ACT_GESTURE_RANGE_ATTACK2` ---- | `ACT_GESTURE_MELEE_ATTACK1` ---- | `ACT_GESTURE_MELEE_ATTACK2` ---- | `ACT_GESTURE_RANGE_ATTACK1_LOW` ---- | `ACT_GESTURE_RANGE_ATTACK2_LOW` ---- | `ACT_MELEE_ATTACK_SWING_GESTURE` ---- | `ACT_GESTURE_SMALL_FLINCH` ---- | `ACT_GESTURE_BIG_FLINCH` ---- | `ACT_GESTURE_FLINCH_BLAST` ---- | `ACT_GESTURE_FLINCH_BLAST_SHOTGUN` ---- | `ACT_GESTURE_FLINCH_BLAST_DAMAGED` ---- | `ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN` ---- | `ACT_GESTURE_FLINCH_HEAD` ---- | `ACT_GESTURE_FLINCH_CHEST` ---- | `ACT_GESTURE_FLINCH_STOMACH` ---- | `ACT_GESTURE_FLINCH_LEFTARM` ---- | `ACT_GESTURE_FLINCH_RIGHTARM` ---- | `ACT_GESTURE_FLINCH_LEFTLEG` ---- | `ACT_GESTURE_FLINCH_RIGHTLEG` ---- | `ACT_GESTURE_TURN_LEFT` ---- | `ACT_GESTURE_TURN_RIGHT` ---- | `ACT_GESTURE_TURN_LEFT45` ---- | `ACT_GESTURE_TURN_RIGHT45` ---- | `ACT_GESTURE_TURN_LEFT90` ---- | `ACT_GESTURE_TURN_RIGHT90` ---- | `ACT_GESTURE_TURN_LEFT45_FLAT` ---- | `ACT_GESTURE_TURN_RIGHT45_FLAT` ---- | `ACT_GESTURE_TURN_LEFT90_FLAT` ---- | `ACT_GESTURE_TURN_RIGHT90_FLAT` ---- | `ACT_BARNACLE_HIT` ---- | `ACT_BARNACLE_PULL` ---- | `ACT_BARNACLE_CHOMP` ---- | `ACT_BARNACLE_CHEW` ---- | `ACT_DO_NOT_DISTURB` ---- | `ACT_SPECIFIC_SEQUENCE` ---- | `ACT_VM_DEPLOY` ---- | `ACT_VM_RELOAD_EMPTY` ---- | `ACT_VM_DRAW` ---- | `ACT_VM_HOLSTER` ---- | `ACT_VM_IDLE` ---- | `ACT_VM_FIDGET` ---- | `ACT_VM_PULLBACK` ---- | `ACT_VM_PULLBACK_HIGH` ---- | `ACT_VM_PULLBACK_LOW` ---- | `ACT_VM_THROW` ---- | `ACT_VM_DROP` ---- | `ACT_VM_PULLPIN` ---- | `ACT_VM_PRIMARYATTACK` ---- | `ACT_VM_SECONDARYATTACK` ---- | `ACT_VM_RELOAD` ---- | `ACT_VM_DRYFIRE` ---- | `ACT_VM_HITLEFT` ---- | `ACT_VM_HITLEFT2` ---- | `ACT_VM_HITRIGHT` ---- | `ACT_VM_HITRIGHT2` ---- | `ACT_VM_HITCENTER` ---- | `ACT_VM_HITCENTER2` ---- | `ACT_VM_MISSLEFT` ---- | `ACT_VM_MISSLEFT2` ---- | `ACT_VM_MISSRIGHT` ---- | `ACT_VM_MISSRIGHT2` ---- | `ACT_VM_MISSCENTER` ---- | `ACT_VM_MISSCENTER2` ---- | `ACT_VM_HAULBACK` ---- | `ACT_VM_SWINGHARD` ---- | `ACT_VM_SWINGMISS` ---- | `ACT_VM_SWINGHIT` ---- | `ACT_VM_IDLE_TO_LOWERED` ---- | `ACT_VM_IDLE_LOWERED` ---- | `ACT_VM_LOWERED_TO_IDLE` ---- | `ACT_VM_RECOIL1` ---- | `ACT_VM_RECOIL2` ---- | `ACT_VM_RECOIL3` ---- | `ACT_VM_PICKUP` ---- | `ACT_VM_RELEASE` ---- | `ACT_VM_MAUL_LOOP` ---- | `ACT_VM_ATTACH_SILENCER` ---- | `ACT_VM_DETACH_SILENCER` ---- | `ACT_SLAM_STICKWALL_IDLE` ---- | `ACT_SLAM_STICKWALL_ND_IDLE` ---- | `ACT_SLAM_STICKWALL_ATTACH` ---- | `ACT_SLAM_STICKWALL_ATTACH2` ---- | `ACT_SLAM_STICKWALL_ND_ATTACH` ---- | `ACT_SLAM_STICKWALL_ND_ATTACH2` ---- | `ACT_SLAM_STICKWALL_DETONATE` ---- | `ACT_SLAM_STICKWALL_DETONATOR_HOLSTER` ---- | `ACT_SLAM_STICKWALL_DRAW` ---- | `ACT_SLAM_STICKWALL_ND_DRAW` ---- | `ACT_SLAM_STICKWALL_TO_THROW` ---- | `ACT_SLAM_STICKWALL_TO_THROW_ND` ---- | `ACT_SLAM_STICKWALL_TO_TRIPMINE_ND` ---- | `ACT_SLAM_THROW_IDLE` ---- | `ACT_SLAM_THROW_ND_IDLE` ---- | `ACT_SLAM_THROW_THROW` ---- | `ACT_SLAM_THROW_THROW2` ---- | `ACT_SLAM_THROW_THROW_ND` ---- | `ACT_SLAM_THROW_THROW_ND2` ---- | `ACT_SLAM_THROW_DRAW` ---- | `ACT_SLAM_THROW_ND_DRAW` ---- | `ACT_SLAM_THROW_TO_STICKWALL` ---- | `ACT_SLAM_THROW_TO_STICKWALL_ND` ---- | `ACT_SLAM_THROW_DETONATE` ---- | `ACT_SLAM_THROW_DETONATOR_HOLSTER` ---- | `ACT_SLAM_THROW_TO_TRIPMINE_ND` ---- | `ACT_SLAM_TRIPMINE_IDLE` ---- | `ACT_SLAM_TRIPMINE_DRAW` ---- | `ACT_SLAM_TRIPMINE_ATTACH` ---- | `ACT_SLAM_TRIPMINE_ATTACH2` ---- | `ACT_SLAM_TRIPMINE_TO_STICKWALL_ND` ---- | `ACT_SLAM_TRIPMINE_TO_THROW_ND` ---- | `ACT_SLAM_DETONATOR_IDLE` ---- | `ACT_SLAM_DETONATOR_DRAW` ---- | `ACT_SLAM_DETONATOR_DETONATE` ---- | `ACT_SLAM_DETONATOR_HOLSTER` ---- | `ACT_SLAM_DETONATOR_STICKWALL_DRAW` ---- | `ACT_SLAM_DETONATOR_THROW_DRAW` ---- | `ACT_SHOTGUN_RELOAD_START` ---- | `ACT_SHOTGUN_RELOAD_FINISH` ---- | `ACT_SHOTGUN_PUMP` ---- | `ACT_SMG2_IDLE2` ---- | `ACT_SMG2_FIRE2` ---- | `ACT_SMG2_DRAW2` ---- | `ACT_SMG2_RELOAD2` ---- | `ACT_SMG2_DRYFIRE2` ---- | `ACT_SMG2_TOAUTO` ---- | `ACT_SMG2_TOBURST` ---- | `ACT_PHYSCANNON_UPGRADE` ---- | `ACT_RANGE_ATTACK_AR1` ---- | `ACT_RANGE_ATTACK_AR2` ---- | `ACT_RANGE_ATTACK_AR2_LOW` ---- | `ACT_RANGE_ATTACK_AR2_GRENADE` ---- | `ACT_RANGE_ATTACK_HMG1` ---- | `ACT_RANGE_ATTACK_ML` ---- | `ACT_RANGE_ATTACK_SMG1` ---- | `ACT_RANGE_ATTACK_SMG1_LOW` ---- | `ACT_RANGE_ATTACK_SMG2` ---- | `ACT_RANGE_ATTACK_SHOTGUN` ---- | `ACT_RANGE_ATTACK_SHOTGUN_LOW` ---- | `ACT_RANGE_ATTACK_PISTOL` ---- | `ACT_RANGE_ATTACK_PISTOL_LOW` ---- | `ACT_RANGE_ATTACK_SLAM` ---- | `ACT_RANGE_ATTACK_TRIPWIRE` ---- | `ACT_RANGE_ATTACK_THROW` ---- | `ACT_RANGE_ATTACK_SNIPER_RIFLE` ---- | `ACT_RANGE_ATTACK_RPG` ---- | `ACT_MELEE_ATTACK_SWING` ---- | `ACT_RANGE_AIM_LOW` ---- | `ACT_RANGE_AIM_SMG1_LOW` ---- | `ACT_RANGE_AIM_PISTOL_LOW` ---- | `ACT_RANGE_AIM_AR2_LOW` ---- | `ACT_COVER_PISTOL_LOW` ---- | `ACT_COVER_SMG1_LOW` ---- | `ACT_GESTURE_RANGE_ATTACK_AR1` ---- | `ACT_GESTURE_RANGE_ATTACK_AR2` ---- | `ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE` ---- | `ACT_GESTURE_RANGE_ATTACK_HMG1` ---- | `ACT_GESTURE_RANGE_ATTACK_ML` ---- | `ACT_GESTURE_RANGE_ATTACK_SMG1` ---- | `ACT_GESTURE_RANGE_ATTACK_SMG1_LOW` ---- | `ACT_GESTURE_RANGE_ATTACK_SMG2` ---- | `ACT_GESTURE_RANGE_ATTACK_SHOTGUN` ---- | `ACT_GESTURE_RANGE_ATTACK_PISTOL` ---- | `ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW` ---- | `ACT_GESTURE_RANGE_ATTACK_SLAM` ---- | `ACT_GESTURE_RANGE_ATTACK_TRIPWIRE` ---- | `ACT_GESTURE_RANGE_ATTACK_THROW` ---- | `ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE` ---- | `ACT_GESTURE_MELEE_ATTACK_SWING` ---- | `ACT_IDLE_RIFLE` ---- | `ACT_IDLE_SMG1` ---- | `ACT_IDLE_ANGRY_SMG1` ---- | `ACT_IDLE_PISTOL` ---- | `ACT_IDLE_ANGRY_PISTOL` ---- | `ACT_IDLE_ANGRY_SHOTGUN` ---- | `ACT_IDLE_STEALTH_PISTOL` ---- | `ACT_IDLE_PACKAGE` ---- | `ACT_WALK_PACKAGE` ---- | `ACT_IDLE_SUITCASE` ---- | `ACT_WALK_SUITCASE` ---- | `ACT_IDLE_SMG1_RELAXED` ---- | `ACT_IDLE_SMG1_STIMULATED` ---- | `ACT_WALK_RIFLE_RELAXED` ---- | `ACT_RUN_RIFLE_RELAXED` ---- | `ACT_WALK_RIFLE_STIMULATED` ---- | `ACT_RUN_RIFLE_STIMULATED` ---- | `ACT_IDLE_AIM_RIFLE_STIMULATED` ---- | `ACT_WALK_AIM_RIFLE_STIMULATED` ---- | `ACT_RUN_AIM_RIFLE_STIMULATED` ---- | `ACT_IDLE_SHOTGUN_RELAXED` ---- | `ACT_IDLE_SHOTGUN_STIMULATED` ---- | `ACT_IDLE_SHOTGUN_AGITATED` ---- | `ACT_WALK_ANGRY` ---- | `ACT_POLICE_HARASS1` ---- | `ACT_POLICE_HARASS2` ---- | `ACT_IDLE_MANNEDGUN` ---- | `ACT_IDLE_MELEE` ---- | `ACT_IDLE_ANGRY_MELEE` ---- | `ACT_IDLE_RPG_RELAXED` ---- | `ACT_IDLE_RPG` ---- | `ACT_IDLE_ANGRY_RPG` ---- | `ACT_COVER_LOW_RPG` ---- | `ACT_WALK_RPG` ---- | `ACT_RUN_RPG` ---- | `ACT_WALK_CROUCH_RPG` ---- | `ACT_RUN_CROUCH_RPG` ---- | `ACT_WALK_RPG_RELAXED` ---- | `ACT_RUN_RPG_RELAXED` ---- | `ACT_WALK_RIFLE` ---- | `ACT_WALK_AIM_RIFLE` ---- | `ACT_WALK_CROUCH_RIFLE` ---- | `ACT_WALK_CROUCH_AIM_RIFLE` ---- | `ACT_RUN_RIFLE` ---- | `ACT_RUN_AIM_RIFLE` ---- | `ACT_RUN_CROUCH_RIFLE` ---- | `ACT_RUN_CROUCH_AIM_RIFLE` ---- | `ACT_RUN_STEALTH_PISTOL` ---- | `ACT_WALK_AIM_SHOTGUN` ---- | `ACT_RUN_AIM_SHOTGUN` ---- | `ACT_WALK_PISTOL` ---- | `ACT_RUN_PISTOL` ---- | `ACT_WALK_AIM_PISTOL` ---- | `ACT_RUN_AIM_PISTOL` ---- | `ACT_WALK_STEALTH_PISTOL` ---- | `ACT_WALK_AIM_STEALTH_PISTOL` ---- | `ACT_RUN_AIM_STEALTH_PISTOL` ---- | `ACT_RELOAD_PISTOL` ---- | `ACT_RELOAD_PISTOL_LOW` ---- | `ACT_RELOAD_SMG1` ---- | `ACT_RELOAD_SMG1_LOW` ---- | `ACT_RELOAD_SHOTGUN` ---- | `ACT_RELOAD_SHOTGUN_LOW` ---- | `ACT_GESTURE_RELOAD` ---- | `ACT_GESTURE_RELOAD_PISTOL` ---- | `ACT_GESTURE_RELOAD_SMG1` ---- | `ACT_GESTURE_RELOAD_SHOTGUN` ---- | `ACT_BUSY_LEAN_LEFT` ---- | `ACT_BUSY_LEAN_LEFT_ENTRY` ---- | `ACT_BUSY_LEAN_LEFT_EXIT` ---- | `ACT_BUSY_LEAN_BACK` ---- | `ACT_BUSY_LEAN_BACK_ENTRY` ---- | `ACT_BUSY_LEAN_BACK_EXIT` ---- | `ACT_BUSY_SIT_GROUND` ---- | `ACT_BUSY_SIT_GROUND_ENTRY` ---- | `ACT_BUSY_SIT_GROUND_EXIT` ---- | `ACT_BUSY_SIT_CHAIR` ---- | `ACT_BUSY_SIT_CHAIR_ENTRY` ---- | `ACT_BUSY_SIT_CHAIR_EXIT` ---- | `ACT_BUSY_STAND` ---- | `ACT_BUSY_QUEUE` ---- | `ACT_DUCK_DODGE` ---- | `ACT_DIE_BARNACLE_SWALLOW` ---- | `ACT_GESTURE_BARNACLE_STRANGLE` ---- | `ACT_DIE_FRONTSIDE` ---- | `ACT_DIE_RIGHTSIDE` ---- | `ACT_DIE_BACKSIDE` ---- | `ACT_DIE_LEFTSIDE` ---- | `ACT_DIE_CROUCH_FRONTSIDE` ---- | `ACT_DIE_CROUCH_RIGHTSIDE` ---- | `ACT_DIE_CROUCH_BACKSIDE` ---- | `ACT_DIE_CROUCH_LEFTSIDE` ---- | `ACT_DIE_INCAP` ---- | `ACT_DIE_STANDING` ---- | `ACT_OPEN_DOOR` ---- | `ACT_DI_ALYX_ZOMBIE_MELEE` ---- | `ACT_DI_ALYX_ZOMBIE_TORSO_MELEE` ---- | `ACT_DI_ALYX_HEADCRAB_MELEE` ---- | `ACT_DI_ALYX_ANTLION` ---- | `ACT_DI_ALYX_ZOMBIE_SHOTGUN64` ---- | `ACT_DI_ALYX_ZOMBIE_SHOTGUN26` ---- | `ACT_READINESS_RELAXED_TO_STIMULATED` ---- | `ACT_READINESS_RELAXED_TO_STIMULATED_WALK` ---- | `ACT_READINESS_AGITATED_TO_STIMULATED` ---- | `ACT_READINESS_STIMULATED_TO_RELAXED` ---- | `ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED` ---- | `ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK` ---- | `ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED` ---- | `ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED` ---- | `ACT_IDLE_CARRY` ---- | `ACT_WALK_CARRY` ---- | `ACT_STARTDYING` ---- | `ACT_DYINGLOOP` ---- | `ACT_DYINGTODEAD` ---- | `ACT_RIDE_MANNED_GUN` ---- | `ACT_VM_SPRINT_ENTER` ---- | `ACT_VM_SPRINT_IDLE` ---- | `ACT_VM_SPRINT_LEAVE` ---- | `ACT_FIRE_START` ---- | `ACT_FIRE_LOOP` ---- | `ACT_FIRE_END` ---- | `ACT_CROUCHING_GRENADEIDLE` ---- | `ACT_CROUCHING_GRENADEREADY` ---- | `ACT_CROUCHING_PRIMARYATTACK` ---- | `ACT_OVERLAY_GRENADEIDLE` ---- | `ACT_OVERLAY_GRENADEREADY` ---- | `ACT_OVERLAY_PRIMARYATTACK` ---- | `ACT_OVERLAY_SHIELD_UP` ---- | `ACT_OVERLAY_SHIELD_DOWN` ---- | `ACT_OVERLAY_SHIELD_UP_IDLE` ---- | `ACT_OVERLAY_SHIELD_ATTACK` ---- | `ACT_OVERLAY_SHIELD_KNOCKBACK` ---- | `ACT_SHIELD_UP` ---- | `ACT_SHIELD_DOWN` ---- | `ACT_SHIELD_UP_IDLE` ---- | `ACT_SHIELD_ATTACK` ---- | `ACT_SHIELD_KNOCKBACK` ---- | `ACT_CROUCHING_SHIELD_UP` ---- | `ACT_CROUCHING_SHIELD_DOWN` ---- | `ACT_CROUCHING_SHIELD_UP_IDLE` ---- | `ACT_CROUCHING_SHIELD_ATTACK` ---- | `ACT_CROUCHING_SHIELD_KNOCKBACK` ---- | `ACT_TURNRIGHT45` ---- | `ACT_TURNLEFT45` ---- | `ACT_TURN` ---- | `ACT_OBJ_ASSEMBLING` ---- | `ACT_OBJ_DISMANTLING` ---- | `ACT_OBJ_STARTUP` ---- | `ACT_OBJ_RUNNING` ---- | `ACT_OBJ_IDLE` ---- | `ACT_OBJ_PLACING` ---- | `ACT_OBJ_DETERIORATING` ---- | `ACT_OBJ_UPGRADING` ---- | `ACT_DEPLOY` ---- | `ACT_DEPLOY_IDLE` ---- | `ACT_UNDEPLOY` ---- | `ACT_CROSSBOW_DRAW_UNLOADED` ---- | `ACT_GAUSS_SPINUP` ---- | `ACT_GAUSS_SPINCYCLE` ---- | `ACT_VM_PRIMARYATTACK_SILENCED` ---- | `ACT_VM_RELOAD_SILENCED` ---- | `ACT_VM_DRYFIRE_SILENCED` ---- | `ACT_VM_IDLE_SILENCED` ---- | `ACT_VM_DRAW_SILENCED` ---- | `ACT_VM_IDLE_EMPTY_LEFT` ---- | `ACT_VM_DRYFIRE_LEFT` ---- | `ACT_VM_IS_DRAW` ---- | `ACT_VM_IS_HOLSTER` ---- | `ACT_VM_IS_IDLE` ---- | `ACT_VM_IS_PRIMARYATTACK` ---- | `ACT_PLAYER_IDLE_FIRE` ---- | `ACT_PLAYER_CROUCH_FIRE` ---- | `ACT_PLAYER_CROUCH_WALK_FIRE` ---- | `ACT_PLAYER_WALK_FIRE` ---- | `ACT_PLAYER_RUN_FIRE` ---- | `ACT_IDLETORUN` ---- | `ACT_RUNTOIDLE` ---- | `ACT_VM_DRAW_DEPLOYED` ---- | `ACT_HL2MP_IDLE_MELEE` ---- | `ACT_HL2MP_RUN_MELEE` ---- | `ACT_HL2MP_IDLE_CROUCH_MELEE` ---- | `ACT_HL2MP_WALK_CROUCH_MELEE` ---- | `ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE` ---- | `ACT_HL2MP_GESTURE_RELOAD_MELEE` ---- | `ACT_HL2MP_JUMP_MELEE` ---- | `ACT_MP_STAND_IDLE` ---- | `ACT_MP_CROUCH_IDLE` ---- | `ACT_MP_CROUCH_DEPLOYED_IDLE` ---- | `ACT_MP_CROUCH_DEPLOYED` ---- | `ACT_MP_DEPLOYED_IDLE` ---- | `ACT_MP_RUN` ---- | `ACT_MP_WALK` ---- | `ACT_MP_AIRWALK` ---- | `ACT_MP_CROUCHWALK` ---- | `ACT_MP_SPRINT` ---- | `ACT_MP_JUMP` ---- | `ACT_MP_JUMP_START` ---- | `ACT_MP_JUMP_FLOAT` ---- | `ACT_MP_JUMP_LAND` ---- | `ACT_MP_DOUBLEJUMP` ---- | `ACT_MP_SWIM` ---- | `ACT_MP_DEPLOYED` ---- | `ACT_MP_SWIM_DEPLOYED` ---- | `ACT_MP_VCD` ---- | `ACT_MP_ATTACK_STAND_PRIMARYFIRE` ---- | `ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED` ---- | `ACT_MP_ATTACK_STAND_SECONDARYFIRE` ---- | `ACT_MP_ATTACK_STAND_GRENADE` ---- | `ACT_MP_ATTACK_CROUCH_PRIMARYFIRE` ---- | `ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED` ---- | `ACT_MP_ATTACK_CROUCH_SECONDARYFIRE` ---- | `ACT_MP_ATTACK_CROUCH_GRENADE` ---- | `ACT_MP_ATTACK_SWIM_PRIMARYFIRE` ---- | `ACT_MP_ATTACK_SWIM_SECONDARYFIRE` ---- | `ACT_MP_ATTACK_SWIM_GRENADE` ---- | `ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE` ---- | `ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE` ---- | `ACT_MP_ATTACK_AIRWALK_GRENADE` ---- | `ACT_MP_RELOAD_STAND` ---- | `ACT_MP_RELOAD_STAND_LOOP` ---- | `ACT_MP_RELOAD_STAND_END` ---- | `ACT_MP_RELOAD_CROUCH` ---- | `ACT_MP_RELOAD_CROUCH_LOOP` ---- | `ACT_MP_RELOAD_CROUCH_END` ---- | `ACT_MP_RELOAD_SWIM` ---- | `ACT_MP_RELOAD_SWIM_LOOP` ---- | `ACT_MP_RELOAD_SWIM_END` ---- | `ACT_MP_RELOAD_AIRWALK` ---- | `ACT_MP_RELOAD_AIRWALK_LOOP` ---- | `ACT_MP_RELOAD_AIRWALK_END` ---- | `ACT_MP_ATTACK_STAND_PREFIRE` ---- | `ACT_MP_ATTACK_STAND_POSTFIRE` ---- | `ACT_MP_ATTACK_STAND_STARTFIRE` ---- | `ACT_MP_ATTACK_CROUCH_PREFIRE` ---- | `ACT_MP_ATTACK_CROUCH_POSTFIRE` ---- | `ACT_MP_ATTACK_SWIM_PREFIRE` ---- | `ACT_MP_ATTACK_SWIM_POSTFIRE` ---- | `ACT_MP_STAND_PRIMARY` ---- | `ACT_MP_CROUCH_PRIMARY` ---- | `ACT_MP_RUN_PRIMARY` ---- | `ACT_MP_WALK_PRIMARY` ---- | `ACT_MP_AIRWALK_PRIMARY` ---- | `ACT_MP_CROUCHWALK_PRIMARY` ---- | `ACT_MP_JUMP_PRIMARY` ---- | `ACT_MP_JUMP_START_PRIMARY` ---- | `ACT_MP_JUMP_FLOAT_PRIMARY` ---- | `ACT_MP_JUMP_LAND_PRIMARY` ---- | `ACT_MP_SWIM_PRIMARY` ---- | `ACT_MP_DEPLOYED_PRIMARY` ---- | `ACT_MP_SWIM_DEPLOYED_PRIMARY` ---- | `ACT_MP_ATTACK_STAND_PRIMARY` ---- | `ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED` ---- | `ACT_MP_ATTACK_CROUCH_PRIMARY` ---- | `ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED` ---- | `ACT_MP_ATTACK_SWIM_PRIMARY` ---- | `ACT_MP_ATTACK_AIRWALK_PRIMARY` ---- | `ACT_MP_RELOAD_STAND_PRIMARY` ---- | `ACT_MP_RELOAD_STAND_PRIMARY_LOOP` ---- | `ACT_MP_RELOAD_STAND_PRIMARY_END` ---- | `ACT_MP_RELOAD_CROUCH_PRIMARY` ---- | `ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP` ---- | `ACT_MP_RELOAD_CROUCH_PRIMARY_END` ---- | `ACT_MP_RELOAD_SWIM_PRIMARY` ---- | `ACT_MP_RELOAD_SWIM_PRIMARY_LOOP` ---- | `ACT_MP_RELOAD_SWIM_PRIMARY_END` ---- | `ACT_MP_RELOAD_AIRWALK_PRIMARY` ---- | `ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP` ---- | `ACT_MP_RELOAD_AIRWALK_PRIMARY_END` ---- | `ACT_MP_ATTACK_STAND_GRENADE_PRIMARY` ---- | `ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY` ---- | `ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY` ---- | `ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY` ---- | `ACT_MP_STAND_SECONDARY` ---- | `ACT_MP_CROUCH_SECONDARY` ---- | `ACT_MP_RUN_SECONDARY` ---- | `ACT_MP_WALK_SECONDARY` ---- | `ACT_MP_AIRWALK_SECONDARY` ---- | `ACT_MP_CROUCHWALK_SECONDARY` ---- | `ACT_MP_JUMP_SECONDARY` ---- | `ACT_MP_JUMP_START_SECONDARY` ---- | `ACT_MP_JUMP_FLOAT_SECONDARY` ---- | `ACT_MP_JUMP_LAND_SECONDARY` ---- | `ACT_MP_SWIM_SECONDARY` ---- | `ACT_MP_ATTACK_STAND_SECONDARY` ---- | `ACT_MP_ATTACK_CROUCH_SECONDARY` ---- | `ACT_MP_ATTACK_SWIM_SECONDARY` ---- | `ACT_MP_ATTACK_AIRWALK_SECONDARY` ---- | `ACT_MP_RELOAD_STAND_SECONDARY` ---- | `ACT_MP_RELOAD_STAND_SECONDARY_LOOP` ---- | `ACT_MP_RELOAD_STAND_SECONDARY_END` ---- | `ACT_MP_RELOAD_CROUCH_SECONDARY` ---- | `ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP` ---- | `ACT_MP_RELOAD_CROUCH_SECONDARY_END` ---- | `ACT_MP_RELOAD_SWIM_SECONDARY` ---- | `ACT_MP_RELOAD_SWIM_SECONDARY_LOOP` ---- | `ACT_MP_RELOAD_SWIM_SECONDARY_END` ---- | `ACT_MP_RELOAD_AIRWALK_SECONDARY` ---- | `ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP` ---- | `ACT_MP_RELOAD_AIRWALK_SECONDARY_END` ---- | `ACT_MP_ATTACK_STAND_GRENADE_SECONDARY` ---- | `ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY` ---- | `ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY` ---- | `ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY` ---- | `ACT_MP_STAND_MELEE` ---- | `ACT_MP_CROUCH_MELEE` ---- | `ACT_MP_RUN_MELEE` ---- | `ACT_MP_WALK_MELEE` ---- | `ACT_MP_AIRWALK_MELEE` ---- | `ACT_MP_CROUCHWALK_MELEE` ---- | `ACT_MP_JUMP_MELEE` ---- | `ACT_MP_JUMP_START_MELEE` ---- | `ACT_MP_JUMP_FLOAT_MELEE` ---- | `ACT_MP_JUMP_LAND_MELEE` ---- | `ACT_MP_SWIM_MELEE` ---- | `ACT_MP_ATTACK_STAND_MELEE` ---- | `ACT_MP_ATTACK_STAND_MELEE_SECONDARY` ---- | `ACT_MP_ATTACK_CROUCH_MELEE` ---- | `ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY` ---- | `ACT_MP_ATTACK_SWIM_MELEE` ---- | `ACT_MP_ATTACK_AIRWALK_MELEE` ---- | `ACT_MP_ATTACK_STAND_GRENADE_MELEE` ---- | `ACT_MP_ATTACK_CROUCH_GRENADE_MELEE` ---- | `ACT_MP_ATTACK_SWIM_GRENADE_MELEE` ---- | `ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE` ---- | `ACT_MP_STAND_ITEM1` ---- | `ACT_MP_CROUCH_ITEM1` ---- | `ACT_MP_RUN_ITEM1` ---- | `ACT_MP_WALK_ITEM1` ---- | `ACT_MP_AIRWALK_ITEM1` ---- | `ACT_MP_CROUCHWALK_ITEM1` ---- | `ACT_MP_JUMP_ITEM1` ---- | `ACT_MP_JUMP_START_ITEM1` ---- | `ACT_MP_JUMP_FLOAT_ITEM1` ---- | `ACT_MP_JUMP_LAND_ITEM1` ---- | `ACT_MP_SWIM_ITEM1` ---- | `ACT_MP_ATTACK_STAND_ITEM1` ---- | `ACT_MP_ATTACK_STAND_ITEM1_SECONDARY` ---- | `ACT_MP_ATTACK_CROUCH_ITEM1` ---- | `ACT_MP_ATTACK_CROUCH_ITEM1_SECONDARY` ---- | `ACT_MP_ATTACK_SWIM_ITEM1` ---- | `ACT_MP_ATTACK_AIRWALK_ITEM1` ---- | `ACT_MP_STAND_ITEM2` ---- | `ACT_MP_CROUCH_ITEM2` ---- | `ACT_MP_RUN_ITEM2` ---- | `ACT_MP_WALK_ITEM2` ---- | `ACT_MP_AIRWALK_ITEM2` ---- | `ACT_MP_CROUCHWALK_ITEM2` ---- | `ACT_MP_JUMP_ITEM2` ---- | `ACT_MP_JUMP_START_ITEM2` ---- | `ACT_MP_JUMP_FLOAT_ITEM2` ---- | `ACT_MP_JUMP_LAND_ITEM2` ---- | `ACT_MP_SWIM_ITEM2` ---- | `ACT_MP_ATTACK_STAND_ITEM2` ---- | `ACT_MP_ATTACK_STAND_ITEM2_SECONDARY` ---- | `ACT_MP_ATTACK_CROUCH_ITEM2` ---- | `ACT_MP_ATTACK_CROUCH_ITEM2_SECONDARY` ---- | `ACT_MP_ATTACK_SWIM_ITEM2` ---- | `ACT_MP_ATTACK_AIRWALK_ITEM2` ---- | `ACT_MP_GESTURE_FLINCH` ---- | `ACT_MP_GESTURE_FLINCH_PRIMARY` ---- | `ACT_MP_GESTURE_FLINCH_SECONDARY` ---- | `ACT_MP_GESTURE_FLINCH_MELEE` ---- | `ACT_MP_GESTURE_FLINCH_ITEM1` ---- | `ACT_MP_GESTURE_FLINCH_ITEM2` ---- | `ACT_MP_GESTURE_FLINCH_HEAD` ---- | `ACT_MP_GESTURE_FLINCH_CHEST` ---- | `ACT_MP_GESTURE_FLINCH_STOMACH` ---- | `ACT_MP_GESTURE_FLINCH_LEFTARM` ---- | `ACT_MP_GESTURE_FLINCH_RIGHTARM` ---- | `ACT_MP_GESTURE_FLINCH_LEFTLEG` ---- | `ACT_MP_GESTURE_FLINCH_RIGHTLEG` ---- | `ACT_MP_GRENADE1_DRAW` ---- | `ACT_MP_GRENADE1_IDLE` ---- | `ACT_MP_GRENADE1_ATTACK` ---- | `ACT_MP_GRENADE2_DRAW` ---- | `ACT_MP_GRENADE2_IDLE` ---- | `ACT_MP_GRENADE2_ATTACK` ---- | `ACT_MP_PRIMARY_GRENADE1_DRAW` ---- | `ACT_MP_PRIMARY_GRENADE1_IDLE` ---- | `ACT_MP_PRIMARY_GRENADE1_ATTACK` ---- | `ACT_MP_PRIMARY_GRENADE2_DRAW` ---- | `ACT_MP_PRIMARY_GRENADE2_IDLE` ---- | `ACT_MP_PRIMARY_GRENADE2_ATTACK` ---- | `ACT_MP_SECONDARY_GRENADE1_DRAW` ---- | `ACT_MP_SECONDARY_GRENADE1_IDLE` ---- | `ACT_MP_SECONDARY_GRENADE1_ATTACK` ---- | `ACT_MP_SECONDARY_GRENADE2_DRAW` ---- | `ACT_MP_SECONDARY_GRENADE2_IDLE` ---- | `ACT_MP_SECONDARY_GRENADE2_ATTACK` ---- | `ACT_MP_MELEE_GRENADE1_DRAW` ---- | `ACT_MP_MELEE_GRENADE1_IDLE` ---- | `ACT_MP_MELEE_GRENADE1_ATTACK` ---- | `ACT_MP_MELEE_GRENADE2_DRAW` ---- | `ACT_MP_MELEE_GRENADE2_IDLE` ---- | `ACT_MP_MELEE_GRENADE2_ATTACK` ---- | `ACT_MP_ITEM1_GRENADE1_DRAW` ---- | `ACT_MP_ITEM1_GRENADE1_IDLE` ---- | `ACT_MP_ITEM1_GRENADE1_ATTACK` ---- | `ACT_MP_ITEM1_GRENADE2_DRAW` ---- | `ACT_MP_ITEM1_GRENADE2_IDLE` ---- | `ACT_MP_ITEM1_GRENADE2_ATTACK` ---- | `ACT_MP_ITEM2_GRENADE1_DRAW` ---- | `ACT_MP_ITEM2_GRENADE1_IDLE` ---- | `ACT_MP_ITEM2_GRENADE1_ATTACK` ---- | `ACT_MP_ITEM2_GRENADE2_DRAW` ---- | `ACT_MP_ITEM2_GRENADE2_IDLE` ---- | `ACT_MP_ITEM2_GRENADE2_ATTACK` ---- | `ACT_MP_STAND_BUILDING` ---- | `ACT_MP_CROUCH_BUILDING` ---- | `ACT_MP_RUN_BUILDING` ---- | `ACT_MP_WALK_BUILDING` ---- | `ACT_MP_AIRWALK_BUILDING` ---- | `ACT_MP_CROUCHWALK_BUILDING` ---- | `ACT_MP_JUMP_BUILDING` ---- | `ACT_MP_JUMP_START_BUILDING` ---- | `ACT_MP_JUMP_FLOAT_BUILDING` ---- | `ACT_MP_JUMP_LAND_BUILDING` ---- | `ACT_MP_SWIM_BUILDING` ---- | `ACT_MP_ATTACK_STAND_BUILDING` ---- | `ACT_MP_ATTACK_CROUCH_BUILDING` ---- | `ACT_MP_ATTACK_SWIM_BUILDING` ---- | `ACT_MP_ATTACK_AIRWALK_BUILDING` ---- | `ACT_MP_ATTACK_STAND_GRENADE_BUILDING` ---- | `ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING` ---- | `ACT_MP_ATTACK_SWIM_GRENADE_BUILDING` ---- | `ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING` ---- | `ACT_MP_STAND_PDA` ---- | `ACT_MP_CROUCH_PDA` ---- | `ACT_MP_RUN_PDA` ---- | `ACT_MP_WALK_PDA` ---- | `ACT_MP_AIRWALK_PDA` ---- | `ACT_MP_CROUCHWALK_PDA` ---- | `ACT_MP_JUMP_PDA` ---- | `ACT_MP_JUMP_START_PDA` ---- | `ACT_MP_JUMP_FLOAT_PDA` ---- | `ACT_MP_JUMP_LAND_PDA` ---- | `ACT_MP_SWIM_PDA` ---- | `ACT_MP_ATTACK_STAND_PDA` ---- | `ACT_MP_ATTACK_SWIM_PDA` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT` ---- | `ACT_MP_GESTURE_VC_FISTPUMP` ---- | `ACT_MP_GESTURE_VC_THUMBSUP` ---- | `ACT_MP_GESTURE_VC_NODYES` ---- | `ACT_MP_GESTURE_VC_NODNO` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY` ---- | `ACT_MP_GESTURE_VC_NODYES_PRIMARY` ---- | `ACT_MP_GESTURE_VC_NODNO_PRIMARY` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY` ---- | `ACT_MP_GESTURE_VC_NODYES_SECONDARY` ---- | `ACT_MP_GESTURE_VC_NODNO_SECONDARY` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_MELEE` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_MELEE` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_MELEE` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_MELEE` ---- | `ACT_MP_GESTURE_VC_NODYES_MELEE` ---- | `ACT_MP_GESTURE_VC_NODNO_MELEE` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_ITEM1` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_ITEM1` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_ITEM1` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_ITEM1` ---- | `ACT_MP_GESTURE_VC_NODYES_ITEM1` ---- | `ACT_MP_GESTURE_VC_NODNO_ITEM1` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_ITEM2` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_ITEM2` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_ITEM2` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_ITEM2` ---- | `ACT_MP_GESTURE_VC_NODYES_ITEM2` ---- | `ACT_MP_GESTURE_VC_NODNO_ITEM2` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_BUILDING` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_BUILDING` ---- | `ACT_MP_GESTURE_VC_NODYES_BUILDING` ---- | `ACT_MP_GESTURE_VC_NODNO_BUILDING` ---- | `ACT_MP_GESTURE_VC_HANDMOUTH_PDA` ---- | `ACT_MP_GESTURE_VC_FINGERPOINT_PDA` ---- | `ACT_MP_GESTURE_VC_FISTPUMP_PDA` ---- | `ACT_MP_GESTURE_VC_THUMBSUP_PDA` ---- | `ACT_MP_GESTURE_VC_NODYES_PDA` ---- | `ACT_MP_GESTURE_VC_NODNO_PDA` ---- | `ACT_VM_UNUSABLE` ---- | `ACT_VM_UNUSABLE_TO_USABLE` ---- | `ACT_VM_USABLE_TO_UNUSABLE` ---- | `ACT_PRIMARY_VM_DRAW` ---- | `ACT_PRIMARY_VM_HOLSTER` ---- | `ACT_PRIMARY_VM_IDLE` ---- | `ACT_PRIMARY_VM_PULLBACK` ---- | `ACT_PRIMARY_VM_PRIMARYATTACK` ---- | `ACT_PRIMARY_VM_SECONDARYATTACK` ---- | `ACT_PRIMARY_VM_RELOAD` ---- | `ACT_PRIMARY_VM_DRYFIRE` ---- | `ACT_PRIMARY_VM_IDLE_TO_LOWERED` ---- | `ACT_PRIMARY_VM_IDLE_LOWERED` ---- | `ACT_PRIMARY_VM_LOWERED_TO_IDLE` ---- | `ACT_SECONDARY_VM_DRAW` ---- | `ACT_SECONDARY_VM_HOLSTER` ---- | `ACT_SECONDARY_VM_IDLE` ---- | `ACT_SECONDARY_VM_PULLBACK` ---- | `ACT_SECONDARY_VM_PRIMARYATTACK` ---- | `ACT_SECONDARY_VM_SECONDARYATTACK` ---- | `ACT_SECONDARY_VM_RELOAD` ---- | `ACT_SECONDARY_VM_DRYFIRE` ---- | `ACT_SECONDARY_VM_IDLE_TO_LOWERED` ---- | `ACT_SECONDARY_VM_IDLE_LOWERED` ---- | `ACT_SECONDARY_VM_LOWERED_TO_IDLE` ---- | `ACT_MELEE_VM_DRAW` ---- | `ACT_MELEE_VM_HOLSTER` ---- | `ACT_MELEE_VM_IDLE` ---- | `ACT_MELEE_VM_PULLBACK` ---- | `ACT_MELEE_VM_PRIMARYATTACK` ---- | `ACT_MELEE_VM_SECONDARYATTACK` ---- | `ACT_MELEE_VM_RELOAD` ---- | `ACT_MELEE_VM_DRYFIRE` ---- | `ACT_MELEE_VM_IDLE_TO_LOWERED` ---- | `ACT_MELEE_VM_IDLE_LOWERED` ---- | `ACT_MELEE_VM_LOWERED_TO_IDLE` ---- | `ACT_PDA_VM_DRAW` ---- | `ACT_PDA_VM_HOLSTER` ---- | `ACT_PDA_VM_IDLE` ---- | `ACT_PDA_VM_PULLBACK` ---- | `ACT_PDA_VM_PRIMARYATTACK` ---- | `ACT_PDA_VM_SECONDARYATTACK` ---- | `ACT_PDA_VM_RELOAD` ---- | `ACT_PDA_VM_DRYFIRE` ---- | `ACT_PDA_VM_IDLE_TO_LOWERED` ---- | `ACT_PDA_VM_IDLE_LOWERED` ---- | `ACT_PDA_VM_LOWERED_TO_IDLE` ---- | `ACT_ITEM1_VM_DRAW` ---- | `ACT_ITEM1_VM_HOLSTER` ---- | `ACT_ITEM1_VM_IDLE` ---- | `ACT_ITEM1_VM_PULLBACK` ---- | `ACT_ITEM1_VM_PRIMARYATTACK` ---- | `ACT_ITEM1_VM_SECONDARYATTACK` ---- | `ACT_ITEM1_VM_RELOAD` ---- | `ACT_ITEM1_VM_DRYFIRE` ---- | `ACT_ITEM1_VM_IDLE_TO_LOWERED` ---- | `ACT_ITEM1_VM_IDLE_LOWERED` ---- | `ACT_ITEM1_VM_LOWERED_TO_IDLE` ---- | `ACT_ITEM2_VM_DRAW` ---- | `ACT_ITEM2_VM_HOLSTER` ---- | `ACT_ITEM2_VM_IDLE` ---- | `ACT_ITEM2_VM_PULLBACK` ---- | `ACT_ITEM2_VM_PRIMARYATTACK` ---- | `ACT_ITEM2_VM_SECONDARYATTACK` ---- | `ACT_ITEM2_VM_RELOAD` ---- | `ACT_ITEM2_VM_DRYFIRE` ---- | `ACT_ITEM2_VM_IDLE_TO_LOWERED` ---- | `ACT_ITEM2_VM_IDLE_LOWERED` ---- | `ACT_ITEM2_VM_LOWERED_TO_IDLE` ---- | `ACT_RELOAD_SUCCEED` ---- | `ACT_RELOAD_FAIL` ---- | `ACT_WALK_AIM_AUTOGUN` ---- | `ACT_RUN_AIM_AUTOGUN` ---- | `ACT_IDLE_AUTOGUN` ---- | `ACT_IDLE_AIM_AUTOGUN` ---- | `ACT_RELOAD_AUTOGUN` ---- | `ACT_CROUCH_IDLE_AUTOGUN` ---- | `ACT_RANGE_ATTACK_AUTOGUN` ---- | `ACT_JUMP_AUTOGUN` ---- | `ACT_IDLE_AIM_PISTOL` ---- | `ACT_WALK_AIM_DUAL` ---- | `ACT_RUN_AIM_DUAL` ---- | `ACT_IDLE_DUAL` ---- | `ACT_IDLE_AIM_DUAL` ---- | `ACT_RELOAD_DUAL` ---- | `ACT_CROUCH_IDLE_DUAL` ---- | `ACT_RANGE_ATTACK_DUAL` ---- | `ACT_JUMP_DUAL` ---- | `ACT_IDLE_AIM_SHOTGUN` ---- | `ACT_CROUCH_IDLE_SHOTGUN` ---- | `ACT_IDLE_AIM_RIFLE` ---- | `ACT_CROUCH_IDLE_RIFLE` ---- | `ACT_RANGE_ATTACK_RIFLE` ---- | `ACT_SLEEP` ---- | `ACT_WAKE` ---- | `ACT_FLICK_LEFT` ---- | `ACT_FLICK_LEFT_MIDDLE` ---- | `ACT_FLICK_RIGHT_MIDDLE` ---- | `ACT_FLICK_RIGHT` ---- | `ACT_SPINAROUND` ---- | `ACT_PREP_TO_FIRE` ---- | `ACT_FIRE` ---- | `ACT_FIRE_RECOVER` ---- | `ACT_SPRAY` ---- | `ACT_PREP_EXPLODE` ---- | `ACT_EXPLODE` ---- | `ACT_SCRIPT_CUSTOM_0` ---- | `ACT_SCRIPT_CUSTOM_1` ---- | `ACT_SCRIPT_CUSTOM_2` ---- | `ACT_SCRIPT_CUSTOM_3` ---- | `ACT_SCRIPT_CUSTOM_4` ---- | `ACT_SCRIPT_CUSTOM_5` ---- | `ACT_SCRIPT_CUSTOM_6` ---- | `ACT_SCRIPT_CUSTOM_7` ---- | `ACT_SCRIPT_CUSTOM_8` ---- | `ACT_SCRIPT_CUSTOM_9` ---- | `ACT_SCRIPT_CUSTOM_10` ---- | `ACT_SCRIPT_CUSTOM_11` ---- | `ACT_SCRIPT_CUSTOM_12` ---- | `ACT_SCRIPT_CUSTOM_13` ---- | `ACT_SCRIPT_CUSTOM_14` ---- | `ACT_SCRIPT_CUSTOM_15` ---- | `ACT_SCRIPT_CUSTOM_16` ---- | `ACT_SCRIPT_CUSTOM_17` ---- | `ACT_SCRIPT_CUSTOM_18` ---- | `ACT_SCRIPT_CUSTOM_19` ---- | `ACT_SCRIPT_CUSTOM_20` ---- | `ACT_SCRIPT_CUSTOM_21` ---- | `ACT_SCRIPT_CUSTOM_22` ---- | `ACT_SCRIPT_CUSTOM_23` ---- | `ACT_SCRIPT_CUSTOM_24` ---- | `ACT_SCRIPT_CUSTOM_25` ---- | `ACT_SCRIPT_CUSTOM_26` ---- | `ACT_SCRIPT_CUSTOM_27` ---- | `ACT_SCRIPT_CUSTOM_28` ---- | `ACT_SCRIPT_CUSTOM_29` ---- | `ACT_SCRIPT_CUSTOM_30` ---- | `ACT_SCRIPT_CUSTOM_31` ---- | `ACT_VR_PISTOL_LAST_SHOT` ---- | `ACT_VR_PISTOL_SLIDE_RELEASE` ---- | `ACT_VR_PISTOL_CLIP_OUT_CHAMBERED` ---- | `ACT_VR_PISTOL_CLIP_OUT_SLIDE_BACK` ---- | `ACT_VR_PISTOL_CLIP_IN_CHAMBERED` ---- | `ACT_VR_PISTOL_CLIP_IN_SLIDE_BACK` ---- | `ACT_VR_PISTOL_IDLE_SLIDE_BACK` ---- | `ACT_VR_PISTOL_IDLE_SLIDE_BACK_CLIP_READY` ---- | `ACT_RAGDOLL_RECOVERY_FRONT` ---- | `ACT_RAGDOLL_RECOVERY_BACK` ---- | `ACT_RAGDOLL_RECOVERY_LEFT` ---- | `ACT_RAGDOLL_RECOVERY_RIGHT` ---- | `ACT_GRABBITYGLOVES_GRAB` ---- | `ACT_GRABBITYGLOVES_RELEASE` ---- | `ACT_GRABBITYGLOVES_GRAB_IDLE` ---- | `ACT_GRABBITYGLOVES_ACTIVE` ---- | `ACT_GRABBITYGLOVES_ACTIVE_IDLE` ---- | `ACT_GRABBITYGLOVES_DEACTIVATE` ---- | `ACT_GRABBITYGLOVES_PULL` ---- | `ACT_HEADCRAB_SMOKE_BOMB` ---- | `ACT_HEADCRAB_SPIT` ---- | `ACT_ZOMBIE_TRIP` ---- | `ACT_ZOMBIE_LUNGE` ---- | `ACT_NEUTRAL_REF_POSE` ---- | `ACT_ANTLION_SCUTTLE_FORWARD` ---- | `ACT_ANTLION_SCUTTLE_BACK` ---- | `ACT_ANTLION_SCUTTLE_LEFT` ---- | `ACT_ANTLION_SCUTTLE_RIGHT` ---- | `ACT_VR_PISTOL_EMPTY_CLIP_IN_SLIDE_BACK` ---- | `ACT_VR_SHOTGUN_IDLE` ---- | `ACT_VR_SHOTGUN_OPEN_CHAMBER` ---- | `ACT_VR_SHOTGUN_RELOAD_1` ---- | `ACT_VR_SHOTGUN_RELOAD_2` ---- | `ACT_VR_SHOTGUN_RELOAD_3` ---- | `ACT_VR_SHOTGUN_CLOSE_CHAMBER` ---- | `ACT_VR_SHOTGUN_TRIGGER_SQUEEZE` ---- | `ACT_VR_SHOTGUN_SHOOT` ---- | `ACT_VR_SHOTGUN_SLIDE_BACK` ---- | `ACT_VR_SHOTGUN_SLIDE_FORWARD` ---- | `ACT_VR_PISTOL_LONG_CLIP_IN_CHAMBERED` ---- | `ACT_VR_PISTOL_LONG_CLIP_IN_SLIDE_BACK` ---- | `ACT_VR_PISTOL_BURST_TOGGLE` ---- | `ACT_VR_PISTOL_LOW_KICK` ---- | `ACT_VR_PISTOL_BURST_ATTACK` ---- | `ACT_VR_SHOTGUN_GRENADE_TWIST` ---- | `ACT_DIE_STAND` ---- | `ACT_DIE_STAND_HEADSHOT` ---- | `ACT_DIE_CROUCH` ---- | `ACT_DIE_CROUCH_HEADSHOT` ---- | `ACT_CSGO_NULL` ---- | `ACT_CSGO_DEFUSE` ---- | `ACT_CSGO_DEFUSE_WITH_KIT` ---- | `ACT_CSGO_FLASHBANG_REACTION` ---- | `ACT_CSGO_FIRE_PRIMARY` ---- | `ACT_CSGO_FIRE_PRIMARY_OPT_1` ---- | `ACT_CSGO_FIRE_PRIMARY_OPT_2` ---- | `ACT_CSGO_FIRE_SECONDARY` ---- | `ACT_CSGO_FIRE_SECONDARY_OPT_1` ---- | `ACT_CSGO_FIRE_SECONDARY_OPT_2` ---- | `ACT_CSGO_RELOAD` ---- | `ACT_CSGO_RELOAD_START` ---- | `ACT_CSGO_RELOAD_LOOP` ---- | `ACT_CSGO_RELOAD_END` ---- | `ACT_CSGO_OPERATE` ---- | `ACT_CSGO_DEPLOY` ---- | `ACT_CSGO_CATCH` ---- | `ACT_CSGO_SILENCER_DETACH` ---- | `ACT_CSGO_SILENCER_ATTACH` ---- | `ACT_CSGO_TWITCH` ---- | `ACT_CSGO_TWITCH_BUYZONE` ---- | `ACT_CSGO_PLANT_BOMB` ---- | `ACT_CSGO_IDLE_TURN_BALANCEADJUST` ---- | `ACT_CSGO_IDLE_ADJUST_STOPPEDMOVING` ---- | `ACT_CSGO_ALIVE_LOOP` ---- | `ACT_CSGO_FLINCH` ---- | `ACT_CSGO_FLINCH_HEAD` ---- | `ACT_CSGO_FLINCH_MOLOTOV` ---- | `ACT_CSGO_JUMP` ---- | `ACT_CSGO_FALL` ---- | `ACT_CSGO_CLIMB_LADDER` ---- | `ACT_CSGO_LAND_LIGHT` ---- | `ACT_CSGO_LAND_HEAVY` ---- | `ACT_CSGO_EXIT_LADDER_TOP` ---- | `ACT_CSGO_EXIT_LADDER_BOTTOM` ---- | `ACT_CSGO_PARACHUTE` ---- | `ACT_CSGO_TAUNT` ---- | `ACT_DOTA_IDLE` ---- | `ACT_DOTA_IDLE_RARE` ---- | `ACT_DOTA_RUN` ---- | `ACT_DOTA_ATTACK` ---- | `ACT_DOTA_ATTACK2` ---- | `ACT_DOTA_ATTACK_EVENT` ---- | `ACT_DOTA_DIE` ---- | `ACT_DOTA_FLINCH` ---- | `ACT_DOTA_FLAIL` ---- | `ACT_DOTA_DISABLED` ---- | `ACT_DOTA_CAST_ABILITY_1` ---- | `ACT_DOTA_CAST_ABILITY_2` ---- | `ACT_DOTA_CAST_ABILITY_3` ---- | `ACT_DOTA_CAST_ABILITY_4` ---- | `ACT_DOTA_CAST_ABILITY_5` ---- | `ACT_DOTA_CAST_ABILITY_6` ---- | `ACT_DOTA_OVERRIDE_ABILITY_1` ---- | `ACT_DOTA_OVERRIDE_ABILITY_2` ---- | `ACT_DOTA_OVERRIDE_ABILITY_3` ---- | `ACT_DOTA_OVERRIDE_ABILITY_4` ---- | `ACT_DOTA_CHANNEL_ABILITY_1` ---- | `ACT_DOTA_CHANNEL_ABILITY_2` ---- | `ACT_DOTA_CHANNEL_ABILITY_3` ---- | `ACT_DOTA_CHANNEL_ABILITY_4` ---- | `ACT_DOTA_CHANNEL_ABILITY_5` ---- | `ACT_DOTA_CHANNEL_ABILITY_6` ---- | `ACT_DOTA_CHANNEL_END_ABILITY_1` ---- | `ACT_DOTA_CHANNEL_END_ABILITY_2` ---- | `ACT_DOTA_CHANNEL_END_ABILITY_3` ---- | `ACT_DOTA_CHANNEL_END_ABILITY_4` ---- | `ACT_DOTA_CHANNEL_END_ABILITY_5` ---- | `ACT_DOTA_CHANNEL_END_ABILITY_6` ---- | `ACT_DOTA_CONSTANT_LAYER` ---- | `ACT_DOTA_CAPTURE` ---- | `ACT_DOTA_SPAWN` ---- | `ACT_DOTA_KILLTAUNT` ---- | `ACT_DOTA_TAUNT` ---- | `ACT_DOTA_THIRST` ---- | `ACT_DOTA_CAST_DRAGONBREATH` ---- | `ACT_DOTA_ECHO_SLAM` ---- | `ACT_DOTA_CAST_ABILITY_1_END` ---- | `ACT_DOTA_CAST_ABILITY_2_END` ---- | `ACT_DOTA_CAST_ABILITY_3_END` ---- | `ACT_DOTA_CAST_ABILITY_4_END` ---- | `ACT_MIRANA_LEAP_END` ---- | `ACT_WAVEFORM_START` ---- | `ACT_WAVEFORM_END` ---- | `ACT_DOTA_CAST_ABILITY_ROT` ---- | `ACT_DOTA_DIE_SPECIAL` ---- | `ACT_DOTA_RATTLETRAP_BATTERYASSAULT` ---- | `ACT_DOTA_RATTLETRAP_POWERCOGS` ---- | `ACT_DOTA_RATTLETRAP_HOOKSHOT_START` ---- | `ACT_DOTA_RATTLETRAP_HOOKSHOT_LOOP` ---- | `ACT_DOTA_RATTLETRAP_HOOKSHOT_END` ---- | `ACT_STORM_SPIRIT_OVERLOAD_RUN_OVERRIDE` ---- | `ACT_DOTA_TINKER_REARM1` ---- | `ACT_DOTA_TINKER_REARM2` ---- | `ACT_DOTA_TINKER_REARM3` ---- | `ACT_TINY_AVALANCHE` ---- | `ACT_TINY_TOSS` ---- | `ACT_TINY_GROWL` ---- | `ACT_DOTA_WEAVERBUG_ATTACH` ---- | `ACT_DOTA_CAST_WILD_AXES_END` ---- | `ACT_DOTA_CAST_LIFE_BREAK_START` ---- | `ACT_DOTA_CAST_LIFE_BREAK_END` ---- | `ACT_DOTA_NIGHTSTALKER_TRANSITION` ---- | `ACT_DOTA_LIFESTEALER_RAGE` ---- | `ACT_DOTA_LIFESTEALER_OPEN_WOUNDS` ---- | `ACT_DOTA_SAND_KING_BURROW_IN` ---- | `ACT_DOTA_SAND_KING_BURROW_OUT` ---- | `ACT_DOTA_EARTHSHAKER_TOTEM_ATTACK` ---- | `ACT_DOTA_WHEEL_LAYER` ---- | `ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START` ---- | `ACT_DOTA_ALCHEMIST_CONCOCTION` ---- | `ACT_DOTA_JAKIRO_LIQUIDFIRE_START` ---- | `ACT_DOTA_JAKIRO_LIQUIDFIRE_LOOP` ---- | `ACT_DOTA_LIFESTEALER_INFEST` ---- | `ACT_DOTA_LIFESTEALER_INFEST_END` ---- | `ACT_DOTA_LASSO_LOOP` ---- | `ACT_DOTA_ALCHEMIST_CONCOCTION_THROW` ---- | `ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END` ---- | `ACT_DOTA_CAST_COLD_SNAP` ---- | `ACT_DOTA_CAST_GHOST_WALK` ---- | `ACT_DOTA_CAST_TORNADO` ---- | `ACT_DOTA_CAST_EMP` ---- | `ACT_DOTA_CAST_ALACRITY` ---- | `ACT_DOTA_CAST_CHAOS_METEOR` ---- | `ACT_DOTA_CAST_SUN_STRIKE` ---- | `ACT_DOTA_CAST_FORGE_SPIRIT` ---- | `ACT_DOTA_CAST_ICE_WALL` ---- | `ACT_DOTA_CAST_DEAFENING_BLAST` ---- | `ACT_DOTA_VICTORY` ---- | `ACT_DOTA_DEFEAT` ---- | `ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE` ---- | `ACT_DOTA_SPIRIT_BREAKER_CHARGE_END` ---- | `ACT_DOTA_TELEPORT` ---- | `ACT_DOTA_TELEPORT_END` ---- | `ACT_DOTA_CAST_REFRACTION` ---- | `ACT_DOTA_CAST_ABILITY_7` ---- | `ACT_DOTA_CANCEL_SIREN_SONG` ---- | `ACT_DOTA_CHANNEL_ABILITY_7` ---- | `ACT_DOTA_LOADOUT` ---- | `ACT_DOTA_FORCESTAFF_END` ---- | `ACT_DOTA_POOF_END` ---- | `ACT_DOTA_SLARK_POUNCE` ---- | `ACT_DOTA_MAGNUS_SKEWER_START` ---- | `ACT_DOTA_MAGNUS_SKEWER_END` ---- | `ACT_DOTA_MEDUSA_STONE_GAZE` ---- | `ACT_DOTA_RELAX_START` ---- | `ACT_DOTA_RELAX_LOOP` ---- | `ACT_DOTA_RELAX_END` ---- | `ACT_DOTA_CENTAUR_STAMPEDE` ---- | `ACT_DOTA_BELLYACHE_START` ---- | `ACT_DOTA_BELLYACHE_LOOP` ---- | `ACT_DOTA_BELLYACHE_END` ---- | `ACT_DOTA_ROQUELAIRE_LAND` ---- | `ACT_DOTA_ROQUELAIRE_LAND_IDLE` ---- | `ACT_DOTA_GREEVIL_CAST` ---- | `ACT_DOTA_GREEVIL_OVERRIDE_ABILITY` ---- | `ACT_DOTA_GREEVIL_HOOK_START` ---- | `ACT_DOTA_GREEVIL_HOOK_END` ---- | `ACT_DOTA_GREEVIL_BLINK_BONE` ---- | `ACT_DOTA_IDLE_SLEEPING` ---- | `ACT_DOTA_INTRO` ---- | `ACT_DOTA_GESTURE_POINT` ---- | `ACT_DOTA_GESTURE_ACCENT` ---- | `ACT_DOTA_SLEEPING_END` ---- | `ACT_DOTA_AMBUSH` ---- | `ACT_DOTA_ITEM_LOOK` ---- | `ACT_DOTA_STARTLE` ---- | `ACT_DOTA_FRUSTRATION` ---- | `ACT_DOTA_TELEPORT_REACT` ---- | `ACT_DOTA_TELEPORT_END_REACT` ---- | `ACT_DOTA_SHRUG` ---- | `ACT_DOTA_RELAX_LOOP_END` ---- | `ACT_DOTA_PRESENT_ITEM` ---- | `ACT_DOTA_IDLE_IMPATIENT` ---- | `ACT_DOTA_SHARPEN_WEAPON` ---- | `ACT_DOTA_SHARPEN_WEAPON_OUT` ---- | `ACT_DOTA_IDLE_SLEEPING_END` ---- | `ACT_DOTA_BRIDGE_DESTROY` ---- | `ACT_DOTA_TAUNT_SNIPER` ---- | `ACT_DOTA_DEATH_BY_SNIPER` ---- | `ACT_DOTA_LOOK_AROUND` ---- | `ACT_DOTA_CAGED_CREEP_RAGE` ---- | `ACT_DOTA_CAGED_CREEP_RAGE_OUT` ---- | `ACT_DOTA_CAGED_CREEP_SMASH` ---- | `ACT_DOTA_CAGED_CREEP_SMASH_OUT` ---- | `ACT_DOTA_IDLE_IMPATIENT_SWORD_TAP` ---- | `ACT_DOTA_INTRO_LOOP` ---- | `ACT_DOTA_BRIDGE_THREAT` ---- | `ACT_DOTA_DAGON` ---- | `ACT_DOTA_CAST_ABILITY_2_ES_ROLL_START` ---- | `ACT_DOTA_CAST_ABILITY_2_ES_ROLL` ---- | `ACT_DOTA_CAST_ABILITY_2_ES_ROLL_END` ---- | `ACT_DOTA_NIAN_PIN_START` ---- | `ACT_DOTA_NIAN_PIN_LOOP` ---- | `ACT_DOTA_NIAN_PIN_END` ---- | `ACT_DOTA_LEAP_STUN` ---- | `ACT_DOTA_LEAP_SWIPE` ---- | `ACT_DOTA_NIAN_INTRO_LEAP` ---- | `ACT_DOTA_AREA_DENY` ---- | `ACT_DOTA_NIAN_PIN_TO_STUN` ---- | `ACT_DOTA_RAZE_1` ---- | `ACT_DOTA_RAZE_2` ---- | `ACT_DOTA_RAZE_3` ---- | `ACT_DOTA_UNDYING_DECAY` ---- | `ACT_DOTA_UNDYING_SOUL_RIP` ---- | `ACT_DOTA_UNDYING_TOMBSTONE` ---- | `ACT_DOTA_WHIRLING_AXES_RANGED` ---- | `ACT_DOTA_SHALLOW_GRAVE` ---- | `ACT_DOTA_COLD_FEET` ---- | `ACT_DOTA_ICE_VORTEX` ---- | `ACT_DOTA_CHILLING_TOUCH` ---- | `ACT_DOTA_ENFEEBLE` ---- | `ACT_DOTA_FATAL_BONDS` ---- | `ACT_DOTA_MIDNIGHT_PULSE` ---- | `ACT_DOTA_ANCESTRAL_SPIRIT` ---- | `ACT_DOTA_THUNDER_STRIKE` ---- | `ACT_DOTA_KINETIC_FIELD` ---- | `ACT_DOTA_STATIC_STORM` ---- | `ACT_DOTA_MINI_TAUNT` ---- | `ACT_DOTA_ARCTIC_BURN_END` ---- | `ACT_DOTA_LOADOUT_RARE` ---- | `ACT_DOTA_SWIM` ---- | `ACT_DOTA_FLEE` ---- | `ACT_DOTA_TROT` ---- | `ACT_DOTA_SHAKE` ---- | `ACT_DOTA_SWIM_IDLE` ---- | `ACT_DOTA_WAIT_IDLE` ---- | `ACT_DOTA_GREET` ---- | `ACT_DOTA_TELEPORT_COOP_START` ---- | `ACT_DOTA_TELEPORT_COOP_WAIT` ---- | `ACT_DOTA_TELEPORT_COOP_END` ---- | `ACT_DOTA_TELEPORT_COOP_EXIT` ---- | `ACT_DOTA_SHOPKEEPER_PET_INTERACT` ---- | `ACT_DOTA_ITEM_PICKUP` ---- | `ACT_DOTA_ITEM_DROP` ---- | `ACT_DOTA_CAPTURE_PET` ---- | `ACT_DOTA_PET_WARD_OBSERVER` ---- | `ACT_DOTA_PET_WARD_SENTRY` ---- | `ACT_DOTA_PET_LEVEL` ---- | `ACT_DOTA_CAST_BURROW_END` ---- | `ACT_DOTA_LIFESTEALER_ASSIMILATE` ---- | `ACT_DOTA_LIFESTEALER_EJECT` ---- | `ACT_DOTA_ATTACK_EVENT_BASH` ---- | `ACT_DOTA_CAPTURE_RARE` ---- | `ACT_DOTA_AW_MAGNETIC_FIELD` ---- | `ACT_DOTA_CAST_GHOST_SHIP` ---- | `ACT_DOTA_FXANIM` ---- | `ACT_DOTA_VICTORY_START` ---- | `ACT_DOTA_DEFEAT_START` ---- | `ACT_DOTA_DP_SPIRIT_SIPHON` ---- | `ACT_DOTA_TRICKS_END` ---- | `ACT_DOTA_ES_STONE_CALLER` ---- | `ACT_DOTA_MK_STRIKE` ---- | `ACT_DOTA_VERSUS` ---- | `ACT_DOTA_CAPTURE_CARD` ---- | `ACT_DOTA_MK_SPRING_SOAR` ---- | `ACT_DOTA_MK_SPRING_END` ---- | `ACT_DOTA_MK_TREE_SOAR` ---- | `ACT_DOTA_MK_TREE_END` ---- | `ACT_DOTA_MK_FUR_ARMY` ---- | `ACT_DOTA_MK_SPRING_CAST` ---- | `ACT_DOTA_NECRO_GHOST_SHROUD` ---- | `ACT_DOTA_OVERRIDE_ARCANA` ---- | `ACT_DOTA_SLIDE` ---- | `ACT_DOTA_SLIDE_LOOP` ---- | `ACT_DOTA_GENERIC_CHANNEL_1` ---- | `ACT_DOTA_GS_SOUL_CHAIN` ---- | `ACT_DOTA_GS_INK_CREATURE` ---- | `ACT_DOTA_TRANSITION` ---- | `ACT_DOTA_BLINK_DAGGER` ---- | `ACT_DOTA_BLINK_DAGGER_END` ---- | `ACT_DOTA_CUSTOM_TOWER_ATTACK` ---- | `ACT_DOTA_CUSTOM_TOWER_IDLE` ---- | `ACT_DOTA_CUSTOM_TOWER_DIE` ---- | `ACT_DOTA_CAST_COLD_SNAP_ORB` ---- | `ACT_DOTA_CAST_GHOST_WALK_ORB` ---- | `ACT_DOTA_CAST_TORNADO_ORB` ---- | `ACT_DOTA_CAST_EMP_ORB` ---- | `ACT_DOTA_CAST_ALACRITY_ORB` ---- | `ACT_DOTA_CAST_CHAOS_METEOR_ORB` ---- | `ACT_DOTA_CAST_SUN_STRIKE_ORB` ---- | `ACT_DOTA_CAST_FORGE_SPIRIT_ORB` ---- | `ACT_DOTA_CAST_ICE_WALL_ORB` ---- | `ACT_DOTA_CAST_DEAFENING_BLAST_ORB` ---- | `ACT_DOTA_NOTICE` ---- | `ACT_DOTA_CAST_ABILITY_2_ALLY` ---- | `ACT_DOTA_SHUFFLE_L` ---- | `ACT_DOTA_SHUFFLE_R` ---- | `ACT_DOTA_OVERRIDE_LOADOUT` ---- | `ACT_DOTA_TAUNT_SPECIAL` ---- | `ACT_DOTA_TELEPORT_START` ---- | `ACT_DOTA_GENERIC_CHANNEL_1_START` ---- | `ACT_DOTA_CUSTOM_TOWER_IDLE_RARE` ---- | `ACT_DOTA_CUSTOM_TOWER_TAUNT` ---- | `ACT_DOTA_CUSTOM_TOWER_HIGH_FIVE` ---- | `ACT_DOTA_ATTACK_SPECIAL` ---- | `ACT_DOTA_TRANSITION_IDLE` ---- | `ACT_DOTA_PIERCE_THE_VEIL` ---- | `ACT_DOTA_RUN_RARE` ---- | `ACT_DOTA_VIPER_DIVE` ---- | `ACT_DOTA_VIPER_DIVE_END` ---- | `ACT_DOTA_MK_STRIKE_END` ---- | `ACT_DOTA_ARCANA_VOTE` ---- | `ACT_DOTA_SPIRIT_BREAKER_ULT_RUN` ---- | `ACT_DOTA_PUNCH` ---- | `ACT_DOTA_CAST_STATUE` ---- | `ACT_DOTA_ATTACK_STATUE` ---- | `ACT_DOTA_CAST3_STATUE` ---- | `ACT_DOTA_CAST1_STATUE` ---- | `ACT_DOTA_TELEPORT_STATUE` ---- | `ACT_DOTA_VICTORY_STATUE` ---- | `ACT_DOTA_TAUNT_STATUE` ---- | `ACT_DOTA_STATUE_SEQUENCE` ---- | `ACT_DOTA_RUN_STATUE` ---- | `ACT_DOTA_IDLE_STATUE` ---- | `ACT_DOTA_CAST4_STATUE` ---- | `ACT_DOTA_FLAIL_STATUE` ---- | `ACT_DOTA_STUN_STATUE` ---- | `ACT_DOTA_TELEPORT_END_STATUE` ---- | `ACT_DOTA_CAST2_STATUE` ---- | `ACT_DOTA_SPAWN_STATUE` ---- | `ACT_DOTA_FORCESTAFF_STATUE` ---- | `ACT_DOTA_DISABLED_END` ---- | `ACT_DOTA_CYCLONE` ---- | `ACT_DOTA_IMPALE` ---- | `ACT_DOTA_TORRENT` ---- | `ACT_DOTA_RUN_ALT` ---- | `ACT_DOTA_VOODOO_REST` ---- | `ACT_DOTA_RADIANT_CREEP_HAMMER` ---- | `ACT_DOTA_RELAX_IN` ---- | `ACT_DOTA_RELAX_OUT` ---- | `ACT_DOTA_CAST_FENCE` - ---- @type GameActivity_t -ACT_RESET = 0 ---- @type GameActivity_t -ACT_IDLE = 1 ---- @type GameActivity_t -ACT_TRANSITION = 2 ---- @type GameActivity_t -ACT_COVER = 3 ---- @type GameActivity_t -ACT_COVER_MED = 4 ---- @type GameActivity_t -ACT_COVER_LOW = 5 ---- @type GameActivity_t -ACT_WALK = 6 ---- @type GameActivity_t -ACT_WALK_AIM = 7 ---- @type GameActivity_t -ACT_WALK_CROUCH = 8 ---- @type GameActivity_t -ACT_WALK_CROUCH_AIM = 9 ---- @type GameActivity_t -ACT_RUN = 10 ---- @type GameActivity_t -ACT_RUN_AIM = 11 ---- @type GameActivity_t -ACT_RUN_CROUCH = 12 ---- @type GameActivity_t -ACT_RUN_CROUCH_AIM = 13 ---- @type GameActivity_t -ACT_RUN_PROTECTED = 14 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_MOVE = 15 ---- @type GameActivity_t -ACT_RANGE_ATTACK1 = 16 ---- @type GameActivity_t -ACT_RANGE_ATTACK2 = 17 ---- @type GameActivity_t -ACT_RANGE_ATTACK1_LOW = 18 ---- @type GameActivity_t -ACT_RANGE_ATTACK2_LOW = 19 ---- @type GameActivity_t -ACT_DIESIMPLE = 20 ---- @type GameActivity_t -ACT_DIEBACKWARD = 21 ---- @type GameActivity_t -ACT_DIEFORWARD = 22 ---- @type GameActivity_t -ACT_DIEVIOLENT = 23 ---- @type GameActivity_t -ACT_DIERAGDOLL = 24 ---- @type GameActivity_t -ACT_FLY = 25 ---- @type GameActivity_t -ACT_HOVER = 26 ---- @type GameActivity_t -ACT_GLIDE = 27 ---- @type GameActivity_t -ACT_SWIM = 28 ---- @type GameActivity_t -ACT_JUMP = 29 ---- @type GameActivity_t -ACT_HOP = 30 ---- @type GameActivity_t -ACT_LEAP = 31 ---- @type GameActivity_t -ACT_LAND = 32 ---- @type GameActivity_t -ACT_CLIMB_UP = 33 ---- @type GameActivity_t -ACT_CLIMB_DOWN = 34 ---- @type GameActivity_t -ACT_CLIMB_DISMOUNT = 35 ---- @type GameActivity_t -ACT_SHIPLADDER_UP = 36 ---- @type GameActivity_t -ACT_SHIPLADDER_DOWN = 37 ---- @type GameActivity_t -ACT_STRAFE_LEFT = 38 ---- @type GameActivity_t -ACT_STRAFE_RIGHT = 39 ---- @type GameActivity_t -ACT_ROLL_LEFT = 40 ---- @type GameActivity_t -ACT_ROLL_RIGHT = 41 ---- @type GameActivity_t -ACT_TURN_LEFT = 42 ---- @type GameActivity_t -ACT_TURN_RIGHT = 43 ---- @type GameActivity_t -ACT_CROUCH = 44 ---- @type GameActivity_t -ACT_CROUCHIDLE = 45 ---- @type GameActivity_t -ACT_STAND = 46 ---- @type GameActivity_t -ACT_USE = 47 ---- @type GameActivity_t -ACT_ALIEN_BURROW_IDLE = 48 ---- @type GameActivity_t -ACT_ALIEN_BURROW_OUT = 49 ---- @type GameActivity_t -ACT_SIGNAL1 = 50 ---- @type GameActivity_t -ACT_SIGNAL2 = 51 ---- @type GameActivity_t -ACT_SIGNAL3 = 52 ---- @type GameActivity_t -ACT_SIGNAL_ADVANCE = 53 ---- @type GameActivity_t -ACT_SIGNAL_FORWARD = 54 ---- @type GameActivity_t -ACT_SIGNAL_GROUP = 55 ---- @type GameActivity_t -ACT_SIGNAL_HALT = 56 ---- @type GameActivity_t -ACT_SIGNAL_LEFT = 57 ---- @type GameActivity_t -ACT_SIGNAL_RIGHT = 58 ---- @type GameActivity_t -ACT_SIGNAL_TAKECOVER = 59 ---- @type GameActivity_t -ACT_LOOKBACK_RIGHT = 60 ---- @type GameActivity_t -ACT_LOOKBACK_LEFT = 61 ---- @type GameActivity_t -ACT_COWER = 62 ---- @type GameActivity_t -ACT_SMALL_FLINCH = 63 ---- @type GameActivity_t -ACT_BIG_FLINCH = 64 ---- @type GameActivity_t -ACT_MELEE_ATTACK1 = 65 ---- @type GameActivity_t -ACT_MELEE_ATTACK2 = 66 ---- @type GameActivity_t -ACT_RELOAD = 67 ---- @type GameActivity_t -ACT_RELOAD_START = 68 ---- @type GameActivity_t -ACT_RELOAD_FINISH = 69 ---- @type GameActivity_t -ACT_RELOAD_LOW = 70 ---- @type GameActivity_t -ACT_ARM = 71 ---- @type GameActivity_t -ACT_DISARM = 72 ---- @type GameActivity_t -ACT_DROP_WEAPON = 73 ---- @type GameActivity_t -ACT_DROP_WEAPON_SHOTGUN = 74 ---- @type GameActivity_t -ACT_PICKUP_GROUND = 75 ---- @type GameActivity_t -ACT_PICKUP_RACK = 76 ---- @type GameActivity_t -ACT_IDLE_ANGRY = 77 ---- @type GameActivity_t -ACT_IDLE_RELAXED = 78 ---- @type GameActivity_t -ACT_IDLE_STIMULATED = 79 ---- @type GameActivity_t -ACT_IDLE_AGITATED = 80 ---- @type GameActivity_t -ACT_IDLE_STEALTH = 81 ---- @type GameActivity_t -ACT_IDLE_HURT = 82 ---- @type GameActivity_t -ACT_WALK_RELAXED = 83 ---- @type GameActivity_t -ACT_WALK_STIMULATED = 84 ---- @type GameActivity_t -ACT_WALK_AGITATED = 85 ---- @type GameActivity_t -ACT_WALK_STEALTH = 86 ---- @type GameActivity_t -ACT_RUN_RELAXED = 87 ---- @type GameActivity_t -ACT_RUN_STIMULATED = 88 ---- @type GameActivity_t -ACT_RUN_AGITATED = 89 ---- @type GameActivity_t -ACT_RUN_STEALTH = 90 ---- @type GameActivity_t -ACT_IDLE_AIM_RELAXED = 91 ---- @type GameActivity_t -ACT_IDLE_AIM_STIMULATED = 92 ---- @type GameActivity_t -ACT_IDLE_AIM_AGITATED = 93 ---- @type GameActivity_t -ACT_IDLE_AIM_STEALTH = 94 ---- @type GameActivity_t -ACT_WALK_AIM_RELAXED = 95 ---- @type GameActivity_t -ACT_WALK_AIM_STIMULATED = 96 ---- @type GameActivity_t -ACT_WALK_AIM_AGITATED = 97 ---- @type GameActivity_t -ACT_WALK_AIM_STEALTH = 98 ---- @type GameActivity_t -ACT_RUN_AIM_RELAXED = 99 ---- @type GameActivity_t -ACT_RUN_AIM_STIMULATED = 100 ---- @type GameActivity_t -ACT_RUN_AIM_AGITATED = 101 ---- @type GameActivity_t -ACT_RUN_AIM_STEALTH = 102 ---- @type GameActivity_t -ACT_CROUCHIDLE_STIMULATED = 103 ---- @type GameActivity_t -ACT_CROUCHIDLE_AIM_STIMULATED = 104 ---- @type GameActivity_t -ACT_CROUCHIDLE_AGITATED = 105 ---- @type GameActivity_t -ACT_WALK_HURT = 106 ---- @type GameActivity_t -ACT_RUN_HURT = 107 ---- @type GameActivity_t -ACT_SPECIAL_ATTACK1 = 108 ---- @type GameActivity_t -ACT_SPECIAL_ATTACK2 = 109 ---- @type GameActivity_t -ACT_COMBAT_IDLE = 110 ---- @type GameActivity_t -ACT_WALK_SCARED = 111 ---- @type GameActivity_t -ACT_RUN_SCARED = 112 ---- @type GameActivity_t -ACT_VICTORY_DANCE = 113 ---- @type GameActivity_t -ACT_DIE_HEADSHOT = 114 ---- @type GameActivity_t -ACT_DIE_CHESTSHOT = 115 ---- @type GameActivity_t -ACT_DIE_GUTSHOT = 116 ---- @type GameActivity_t -ACT_DIE_BACKSHOT = 117 ---- @type GameActivity_t -ACT_FLINCH_HEAD = 118 ---- @type GameActivity_t -ACT_FLINCH_CHEST = 119 ---- @type GameActivity_t -ACT_FLINCH_STOMACH = 120 ---- @type GameActivity_t -ACT_FLINCH_LEFTARM = 121 ---- @type GameActivity_t -ACT_FLINCH_RIGHTARM = 122 ---- @type GameActivity_t -ACT_FLINCH_LEFTLEG = 123 ---- @type GameActivity_t -ACT_FLINCH_RIGHTLEG = 124 ---- @type GameActivity_t -ACT_FLINCH_PHYSICS = 125 ---- @type GameActivity_t -ACT_FLINCH_HEAD_BACK = 126 ---- @type GameActivity_t -ACT_FLINCH_CHEST_BACK = 127 ---- @type GameActivity_t -ACT_FLINCH_STOMACH_BACK = 128 ---- @type GameActivity_t -ACT_FLINCH_CROUCH_FRONT = 129 ---- @type GameActivity_t -ACT_FLINCH_CROUCH_BACK = 130 ---- @type GameActivity_t -ACT_FLINCH_CROUCH_LEFT = 131 ---- @type GameActivity_t -ACT_FLINCH_CROUCH_RIGHT = 132 ---- @type GameActivity_t -ACT_IDLE_ON_FIRE = 133 ---- @type GameActivity_t -ACT_WALK_ON_FIRE = 134 ---- @type GameActivity_t -ACT_RUN_ON_FIRE = 135 ---- @type GameActivity_t -ACT_180_LEFT = 137 ---- @type GameActivity_t -ACT_180_RIGHT = 138 ---- @type GameActivity_t -ACT_90_LEFT = 139 ---- @type GameActivity_t -ACT_90_RIGHT = 140 ---- @type GameActivity_t -ACT_STEP_LEFT = 141 ---- @type GameActivity_t -ACT_STEP_RIGHT = 142 ---- @type GameActivity_t -ACT_STEP_BACK = 143 ---- @type GameActivity_t -ACT_STEP_FORE = 144 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK1 = 145 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK2 = 146 ---- @type GameActivity_t -ACT_GESTURE_MELEE_ATTACK1 = 147 ---- @type GameActivity_t -ACT_GESTURE_MELEE_ATTACK2 = 148 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK1_LOW = 149 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK2_LOW = 150 ---- @type GameActivity_t -ACT_MELEE_ATTACK_SWING_GESTURE = 151 ---- @type GameActivity_t -ACT_GESTURE_SMALL_FLINCH = 152 ---- @type GameActivity_t -ACT_GESTURE_BIG_FLINCH = 153 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_BLAST = 154 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_BLAST_SHOTGUN = 155 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_BLAST_DAMAGED = 156 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN = 157 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_HEAD = 158 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_CHEST = 159 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_STOMACH = 160 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_LEFTARM = 161 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_RIGHTARM = 162 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_LEFTLEG = 163 ---- @type GameActivity_t -ACT_GESTURE_FLINCH_RIGHTLEG = 164 ---- @type GameActivity_t -ACT_GESTURE_TURN_LEFT = 165 ---- @type GameActivity_t -ACT_GESTURE_TURN_RIGHT = 166 ---- @type GameActivity_t -ACT_GESTURE_TURN_LEFT45 = 167 ---- @type GameActivity_t -ACT_GESTURE_TURN_RIGHT45 = 168 ---- @type GameActivity_t -ACT_GESTURE_TURN_LEFT90 = 169 ---- @type GameActivity_t -ACT_GESTURE_TURN_RIGHT90 = 170 ---- @type GameActivity_t -ACT_GESTURE_TURN_LEFT45_FLAT = 171 ---- @type GameActivity_t -ACT_GESTURE_TURN_RIGHT45_FLAT = 172 ---- @type GameActivity_t -ACT_GESTURE_TURN_LEFT90_FLAT = 173 ---- @type GameActivity_t -ACT_GESTURE_TURN_RIGHT90_FLAT = 174 ---- @type GameActivity_t -ACT_BARNACLE_HIT = 175 ---- @type GameActivity_t -ACT_BARNACLE_PULL = 176 ---- @type GameActivity_t -ACT_BARNACLE_CHOMP = 177 ---- @type GameActivity_t -ACT_BARNACLE_CHEW = 178 ---- @type GameActivity_t -ACT_DO_NOT_DISTURB = 179 ---- @type GameActivity_t -ACT_SPECIFIC_SEQUENCE = 180 ---- @type GameActivity_t -ACT_VM_DEPLOY = 181 ---- @type GameActivity_t -ACT_VM_RELOAD_EMPTY = 182 ---- @type GameActivity_t -ACT_VM_DRAW = 183 ---- @type GameActivity_t -ACT_VM_HOLSTER = 184 ---- @type GameActivity_t -ACT_VM_IDLE = 185 ---- @type GameActivity_t -ACT_VM_FIDGET = 186 ---- @type GameActivity_t -ACT_VM_PULLBACK = 187 ---- @type GameActivity_t -ACT_VM_PULLBACK_HIGH = 188 ---- @type GameActivity_t -ACT_VM_PULLBACK_LOW = 189 ---- @type GameActivity_t -ACT_VM_THROW = 190 ---- @type GameActivity_t -ACT_VM_DROP = 191 ---- @type GameActivity_t -ACT_VM_PULLPIN = 192 ---- @type GameActivity_t -ACT_VM_PRIMARYATTACK = 193 ---- @type GameActivity_t -ACT_VM_SECONDARYATTACK = 194 ---- @type GameActivity_t -ACT_VM_RELOAD = 195 ---- @type GameActivity_t -ACT_VM_DRYFIRE = 196 ---- @type GameActivity_t -ACT_VM_HITLEFT = 197 ---- @type GameActivity_t -ACT_VM_HITLEFT2 = 198 ---- @type GameActivity_t -ACT_VM_HITRIGHT = 199 ---- @type GameActivity_t -ACT_VM_HITRIGHT2 = 200 ---- @type GameActivity_t -ACT_VM_HITCENTER = 201 ---- @type GameActivity_t -ACT_VM_HITCENTER2 = 202 ---- @type GameActivity_t -ACT_VM_MISSLEFT = 203 ---- @type GameActivity_t -ACT_VM_MISSLEFT2 = 204 ---- @type GameActivity_t -ACT_VM_MISSRIGHT = 205 ---- @type GameActivity_t -ACT_VM_MISSRIGHT2 = 206 ---- @type GameActivity_t -ACT_VM_MISSCENTER = 207 ---- @type GameActivity_t -ACT_VM_MISSCENTER2 = 208 ---- @type GameActivity_t -ACT_VM_HAULBACK = 209 ---- @type GameActivity_t -ACT_VM_SWINGHARD = 210 ---- @type GameActivity_t -ACT_VM_SWINGMISS = 211 ---- @type GameActivity_t -ACT_VM_SWINGHIT = 212 ---- @type GameActivity_t -ACT_VM_IDLE_TO_LOWERED = 213 ---- @type GameActivity_t -ACT_VM_IDLE_LOWERED = 214 ---- @type GameActivity_t -ACT_VM_LOWERED_TO_IDLE = 215 ---- @type GameActivity_t -ACT_VM_RECOIL1 = 216 ---- @type GameActivity_t -ACT_VM_RECOIL2 = 217 ---- @type GameActivity_t -ACT_VM_RECOIL3 = 218 ---- @type GameActivity_t -ACT_VM_PICKUP = 219 ---- @type GameActivity_t -ACT_VM_RELEASE = 220 ---- @type GameActivity_t -ACT_VM_MAUL_LOOP = 221 ---- @type GameActivity_t -ACT_VM_ATTACH_SILENCER = 222 ---- @type GameActivity_t -ACT_VM_DETACH_SILENCER = 223 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_IDLE = 224 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_ND_IDLE = 225 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_ATTACH = 226 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_ATTACH2 = 227 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_ND_ATTACH = 228 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_ND_ATTACH2 = 229 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_DETONATE = 230 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_DETONATOR_HOLSTER = 231 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_DRAW = 232 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_ND_DRAW = 233 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_TO_THROW = 234 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_TO_THROW_ND = 235 ---- @type GameActivity_t -ACT_SLAM_STICKWALL_TO_TRIPMINE_ND = 236 ---- @type GameActivity_t -ACT_SLAM_THROW_IDLE = 237 ---- @type GameActivity_t -ACT_SLAM_THROW_ND_IDLE = 238 ---- @type GameActivity_t -ACT_SLAM_THROW_THROW = 239 ---- @type GameActivity_t -ACT_SLAM_THROW_THROW2 = 240 ---- @type GameActivity_t -ACT_SLAM_THROW_THROW_ND = 241 ---- @type GameActivity_t -ACT_SLAM_THROW_THROW_ND2 = 242 ---- @type GameActivity_t -ACT_SLAM_THROW_DRAW = 243 ---- @type GameActivity_t -ACT_SLAM_THROW_ND_DRAW = 244 ---- @type GameActivity_t -ACT_SLAM_THROW_TO_STICKWALL = 245 ---- @type GameActivity_t -ACT_SLAM_THROW_TO_STICKWALL_ND = 246 ---- @type GameActivity_t -ACT_SLAM_THROW_DETONATE = 247 ---- @type GameActivity_t -ACT_SLAM_THROW_DETONATOR_HOLSTER = 248 ---- @type GameActivity_t -ACT_SLAM_THROW_TO_TRIPMINE_ND = 249 ---- @type GameActivity_t -ACT_SLAM_TRIPMINE_IDLE = 250 ---- @type GameActivity_t -ACT_SLAM_TRIPMINE_DRAW = 251 ---- @type GameActivity_t -ACT_SLAM_TRIPMINE_ATTACH = 252 ---- @type GameActivity_t -ACT_SLAM_TRIPMINE_ATTACH2 = 253 ---- @type GameActivity_t -ACT_SLAM_TRIPMINE_TO_STICKWALL_ND = 254 ---- @type GameActivity_t -ACT_SLAM_TRIPMINE_TO_THROW_ND = 255 ---- @type GameActivity_t -ACT_SLAM_DETONATOR_IDLE = 256 ---- @type GameActivity_t -ACT_SLAM_DETONATOR_DRAW = 257 ---- @type GameActivity_t -ACT_SLAM_DETONATOR_DETONATE = 258 ---- @type GameActivity_t -ACT_SLAM_DETONATOR_HOLSTER = 259 ---- @type GameActivity_t -ACT_SLAM_DETONATOR_STICKWALL_DRAW = 260 ---- @type GameActivity_t -ACT_SLAM_DETONATOR_THROW_DRAW = 261 ---- @type GameActivity_t -ACT_SHOTGUN_RELOAD_START = 262 ---- @type GameActivity_t -ACT_SHOTGUN_RELOAD_FINISH = 263 ---- @type GameActivity_t -ACT_SHOTGUN_PUMP = 264 ---- @type GameActivity_t -ACT_SMG2_IDLE2 = 265 ---- @type GameActivity_t -ACT_SMG2_FIRE2 = 266 ---- @type GameActivity_t -ACT_SMG2_DRAW2 = 267 ---- @type GameActivity_t -ACT_SMG2_RELOAD2 = 268 ---- @type GameActivity_t -ACT_SMG2_DRYFIRE2 = 269 ---- @type GameActivity_t -ACT_SMG2_TOAUTO = 270 ---- @type GameActivity_t -ACT_SMG2_TOBURST = 271 ---- @type GameActivity_t -ACT_PHYSCANNON_UPGRADE = 272 ---- @type GameActivity_t -ACT_RANGE_ATTACK_AR1 = 273 ---- @type GameActivity_t -ACT_RANGE_ATTACK_AR2 = 274 ---- @type GameActivity_t -ACT_RANGE_ATTACK_AR2_LOW = 275 ---- @type GameActivity_t -ACT_RANGE_ATTACK_AR2_GRENADE = 276 ---- @type GameActivity_t -ACT_RANGE_ATTACK_HMG1 = 277 ---- @type GameActivity_t -ACT_RANGE_ATTACK_ML = 278 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SMG1 = 279 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SMG1_LOW = 280 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SMG2 = 281 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SHOTGUN = 282 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SHOTGUN_LOW = 283 ---- @type GameActivity_t -ACT_RANGE_ATTACK_PISTOL = 284 ---- @type GameActivity_t -ACT_RANGE_ATTACK_PISTOL_LOW = 285 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SLAM = 286 ---- @type GameActivity_t -ACT_RANGE_ATTACK_TRIPWIRE = 287 ---- @type GameActivity_t -ACT_RANGE_ATTACK_THROW = 288 ---- @type GameActivity_t -ACT_RANGE_ATTACK_SNIPER_RIFLE = 289 ---- @type GameActivity_t -ACT_RANGE_ATTACK_RPG = 290 ---- @type GameActivity_t -ACT_MELEE_ATTACK_SWING = 291 ---- @type GameActivity_t -ACT_RANGE_AIM_LOW = 292 ---- @type GameActivity_t -ACT_RANGE_AIM_SMG1_LOW = 293 ---- @type GameActivity_t -ACT_RANGE_AIM_PISTOL_LOW = 294 ---- @type GameActivity_t -ACT_RANGE_AIM_AR2_LOW = 295 ---- @type GameActivity_t -ACT_COVER_PISTOL_LOW = 296 ---- @type GameActivity_t -ACT_COVER_SMG1_LOW = 297 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_AR1 = 298 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_AR2 = 299 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE = 300 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_HMG1 = 301 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_ML = 302 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_SMG1 = 303 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_SMG1_LOW = 304 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_SMG2 = 305 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_SHOTGUN = 306 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_PISTOL = 307 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW = 308 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_SLAM = 309 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_TRIPWIRE = 310 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_THROW = 311 ---- @type GameActivity_t -ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE = 312 ---- @type GameActivity_t -ACT_GESTURE_MELEE_ATTACK_SWING = 313 ---- @type GameActivity_t -ACT_IDLE_RIFLE = 314 ---- @type GameActivity_t -ACT_IDLE_SMG1 = 315 ---- @type GameActivity_t -ACT_IDLE_ANGRY_SMG1 = 316 ---- @type GameActivity_t -ACT_IDLE_PISTOL = 317 ---- @type GameActivity_t -ACT_IDLE_ANGRY_PISTOL = 318 ---- @type GameActivity_t -ACT_IDLE_ANGRY_SHOTGUN = 319 ---- @type GameActivity_t -ACT_IDLE_STEALTH_PISTOL = 320 ---- @type GameActivity_t -ACT_IDLE_PACKAGE = 321 ---- @type GameActivity_t -ACT_WALK_PACKAGE = 322 ---- @type GameActivity_t -ACT_IDLE_SUITCASE = 323 ---- @type GameActivity_t -ACT_WALK_SUITCASE = 324 ---- @type GameActivity_t -ACT_IDLE_SMG1_RELAXED = 325 ---- @type GameActivity_t -ACT_IDLE_SMG1_STIMULATED = 326 ---- @type GameActivity_t -ACT_WALK_RIFLE_RELAXED = 327 ---- @type GameActivity_t -ACT_RUN_RIFLE_RELAXED = 328 ---- @type GameActivity_t -ACT_WALK_RIFLE_STIMULATED = 329 ---- @type GameActivity_t -ACT_RUN_RIFLE_STIMULATED = 330 ---- @type GameActivity_t -ACT_IDLE_AIM_RIFLE_STIMULATED = 331 ---- @type GameActivity_t -ACT_WALK_AIM_RIFLE_STIMULATED = 332 ---- @type GameActivity_t -ACT_RUN_AIM_RIFLE_STIMULATED = 333 ---- @type GameActivity_t -ACT_IDLE_SHOTGUN_RELAXED = 334 ---- @type GameActivity_t -ACT_IDLE_SHOTGUN_STIMULATED = 335 ---- @type GameActivity_t -ACT_IDLE_SHOTGUN_AGITATED = 336 ---- @type GameActivity_t -ACT_WALK_ANGRY = 337 ---- @type GameActivity_t -ACT_POLICE_HARASS1 = 338 ---- @type GameActivity_t -ACT_POLICE_HARASS2 = 339 ---- @type GameActivity_t -ACT_IDLE_MANNEDGUN = 340 ---- @type GameActivity_t -ACT_IDLE_MELEE = 341 ---- @type GameActivity_t -ACT_IDLE_ANGRY_MELEE = 342 ---- @type GameActivity_t -ACT_IDLE_RPG_RELAXED = 343 ---- @type GameActivity_t -ACT_IDLE_RPG = 344 ---- @type GameActivity_t -ACT_IDLE_ANGRY_RPG = 345 ---- @type GameActivity_t -ACT_COVER_LOW_RPG = 346 ---- @type GameActivity_t -ACT_WALK_RPG = 347 ---- @type GameActivity_t -ACT_RUN_RPG = 348 ---- @type GameActivity_t -ACT_WALK_CROUCH_RPG = 349 ---- @type GameActivity_t -ACT_RUN_CROUCH_RPG = 350 ---- @type GameActivity_t -ACT_WALK_RPG_RELAXED = 351 ---- @type GameActivity_t -ACT_RUN_RPG_RELAXED = 352 ---- @type GameActivity_t -ACT_WALK_RIFLE = 353 ---- @type GameActivity_t -ACT_WALK_AIM_RIFLE = 354 ---- @type GameActivity_t -ACT_WALK_CROUCH_RIFLE = 355 ---- @type GameActivity_t -ACT_WALK_CROUCH_AIM_RIFLE = 356 ---- @type GameActivity_t -ACT_RUN_RIFLE = 357 ---- @type GameActivity_t -ACT_RUN_AIM_RIFLE = 358 ---- @type GameActivity_t -ACT_RUN_CROUCH_RIFLE = 359 ---- @type GameActivity_t -ACT_RUN_CROUCH_AIM_RIFLE = 360 ---- @type GameActivity_t -ACT_RUN_STEALTH_PISTOL = 361 ---- @type GameActivity_t -ACT_WALK_AIM_SHOTGUN = 362 ---- @type GameActivity_t -ACT_RUN_AIM_SHOTGUN = 363 ---- @type GameActivity_t -ACT_WALK_PISTOL = 364 ---- @type GameActivity_t -ACT_RUN_PISTOL = 365 ---- @type GameActivity_t -ACT_WALK_AIM_PISTOL = 366 ---- @type GameActivity_t -ACT_RUN_AIM_PISTOL = 367 ---- @type GameActivity_t -ACT_WALK_STEALTH_PISTOL = 368 ---- @type GameActivity_t -ACT_WALK_AIM_STEALTH_PISTOL = 369 ---- @type GameActivity_t -ACT_RUN_AIM_STEALTH_PISTOL = 370 ---- @type GameActivity_t -ACT_RELOAD_PISTOL = 371 ---- @type GameActivity_t -ACT_RELOAD_PISTOL_LOW = 372 ---- @type GameActivity_t -ACT_RELOAD_SMG1 = 373 ---- @type GameActivity_t -ACT_RELOAD_SMG1_LOW = 374 ---- @type GameActivity_t -ACT_RELOAD_SHOTGUN = 375 ---- @type GameActivity_t -ACT_RELOAD_SHOTGUN_LOW = 376 ---- @type GameActivity_t -ACT_GESTURE_RELOAD = 377 ---- @type GameActivity_t -ACT_GESTURE_RELOAD_PISTOL = 378 ---- @type GameActivity_t -ACT_GESTURE_RELOAD_SMG1 = 379 ---- @type GameActivity_t -ACT_GESTURE_RELOAD_SHOTGUN = 380 ---- @type GameActivity_t -ACT_BUSY_LEAN_LEFT = 381 ---- @type GameActivity_t -ACT_BUSY_LEAN_LEFT_ENTRY = 382 ---- @type GameActivity_t -ACT_BUSY_LEAN_LEFT_EXIT = 383 ---- @type GameActivity_t -ACT_BUSY_LEAN_BACK = 384 ---- @type GameActivity_t -ACT_BUSY_LEAN_BACK_ENTRY = 385 ---- @type GameActivity_t -ACT_BUSY_LEAN_BACK_EXIT = 386 ---- @type GameActivity_t -ACT_BUSY_SIT_GROUND = 387 ---- @type GameActivity_t -ACT_BUSY_SIT_GROUND_ENTRY = 388 ---- @type GameActivity_t -ACT_BUSY_SIT_GROUND_EXIT = 389 ---- @type GameActivity_t -ACT_BUSY_SIT_CHAIR = 390 ---- @type GameActivity_t -ACT_BUSY_SIT_CHAIR_ENTRY = 391 ---- @type GameActivity_t -ACT_BUSY_SIT_CHAIR_EXIT = 392 ---- @type GameActivity_t -ACT_BUSY_STAND = 393 ---- @type GameActivity_t -ACT_BUSY_QUEUE = 394 ---- @type GameActivity_t -ACT_DUCK_DODGE = 395 ---- @type GameActivity_t -ACT_DIE_BARNACLE_SWALLOW = 396 ---- @type GameActivity_t -ACT_GESTURE_BARNACLE_STRANGLE = 397 ---- @type GameActivity_t -ACT_DIE_FRONTSIDE = 402 ---- @type GameActivity_t -ACT_DIE_RIGHTSIDE = 403 ---- @type GameActivity_t -ACT_DIE_BACKSIDE = 404 ---- @type GameActivity_t -ACT_DIE_LEFTSIDE = 405 ---- @type GameActivity_t -ACT_DIE_CROUCH_FRONTSIDE = 406 ---- @type GameActivity_t -ACT_DIE_CROUCH_RIGHTSIDE = 407 ---- @type GameActivity_t -ACT_DIE_CROUCH_BACKSIDE = 408 ---- @type GameActivity_t -ACT_DIE_CROUCH_LEFTSIDE = 409 ---- @type GameActivity_t -ACT_DIE_INCAP = 410 ---- @type GameActivity_t -ACT_DIE_STANDING = 411 ---- @type GameActivity_t -ACT_OPEN_DOOR = 412 ---- @type GameActivity_t -ACT_DI_ALYX_ZOMBIE_MELEE = 413 ---- @type GameActivity_t -ACT_DI_ALYX_ZOMBIE_TORSO_MELEE = 414 ---- @type GameActivity_t -ACT_DI_ALYX_HEADCRAB_MELEE = 415 ---- @type GameActivity_t -ACT_DI_ALYX_ANTLION = 416 ---- @type GameActivity_t -ACT_DI_ALYX_ZOMBIE_SHOTGUN64 = 417 ---- @type GameActivity_t -ACT_DI_ALYX_ZOMBIE_SHOTGUN26 = 418 ---- @type GameActivity_t -ACT_READINESS_RELAXED_TO_STIMULATED = 419 ---- @type GameActivity_t -ACT_READINESS_RELAXED_TO_STIMULATED_WALK = 420 ---- @type GameActivity_t -ACT_READINESS_AGITATED_TO_STIMULATED = 421 ---- @type GameActivity_t -ACT_READINESS_STIMULATED_TO_RELAXED = 422 ---- @type GameActivity_t -ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED = 423 ---- @type GameActivity_t -ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK = 424 ---- @type GameActivity_t -ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED = 425 ---- @type GameActivity_t -ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED = 426 ---- @type GameActivity_t -ACT_IDLE_CARRY = 427 ---- @type GameActivity_t -ACT_WALK_CARRY = 428 ---- @type GameActivity_t -ACT_STARTDYING = 429 ---- @type GameActivity_t -ACT_DYINGLOOP = 430 ---- @type GameActivity_t -ACT_DYINGTODEAD = 431 ---- @type GameActivity_t -ACT_RIDE_MANNED_GUN = 432 ---- @type GameActivity_t -ACT_VM_SPRINT_ENTER = 433 ---- @type GameActivity_t -ACT_VM_SPRINT_IDLE = 434 ---- @type GameActivity_t -ACT_VM_SPRINT_LEAVE = 435 ---- @type GameActivity_t -ACT_FIRE_START = 436 ---- @type GameActivity_t -ACT_FIRE_LOOP = 437 ---- @type GameActivity_t -ACT_FIRE_END = 438 ---- @type GameActivity_t -ACT_CROUCHING_GRENADEIDLE = 439 ---- @type GameActivity_t -ACT_CROUCHING_GRENADEREADY = 440 ---- @type GameActivity_t -ACT_CROUCHING_PRIMARYATTACK = 441 ---- @type GameActivity_t -ACT_OVERLAY_GRENADEIDLE = 442 ---- @type GameActivity_t -ACT_OVERLAY_GRENADEREADY = 443 ---- @type GameActivity_t -ACT_OVERLAY_PRIMARYATTACK = 444 ---- @type GameActivity_t -ACT_OVERLAY_SHIELD_UP = 445 ---- @type GameActivity_t -ACT_OVERLAY_SHIELD_DOWN = 446 ---- @type GameActivity_t -ACT_OVERLAY_SHIELD_UP_IDLE = 447 ---- @type GameActivity_t -ACT_OVERLAY_SHIELD_ATTACK = 448 ---- @type GameActivity_t -ACT_OVERLAY_SHIELD_KNOCKBACK = 449 ---- @type GameActivity_t -ACT_SHIELD_UP = 450 ---- @type GameActivity_t -ACT_SHIELD_DOWN = 451 ---- @type GameActivity_t -ACT_SHIELD_UP_IDLE = 452 ---- @type GameActivity_t -ACT_SHIELD_ATTACK = 453 ---- @type GameActivity_t -ACT_SHIELD_KNOCKBACK = 454 ---- @type GameActivity_t -ACT_CROUCHING_SHIELD_UP = 455 ---- @type GameActivity_t -ACT_CROUCHING_SHIELD_DOWN = 456 ---- @type GameActivity_t -ACT_CROUCHING_SHIELD_UP_IDLE = 457 ---- @type GameActivity_t -ACT_CROUCHING_SHIELD_ATTACK = 458 ---- @type GameActivity_t -ACT_CROUCHING_SHIELD_KNOCKBACK = 459 ---- @type GameActivity_t -ACT_TURNRIGHT45 = 460 ---- @type GameActivity_t -ACT_TURNLEFT45 = 461 ---- @type GameActivity_t -ACT_TURN = 462 ---- @type GameActivity_t -ACT_OBJ_ASSEMBLING = 463 ---- @type GameActivity_t -ACT_OBJ_DISMANTLING = 464 ---- @type GameActivity_t -ACT_OBJ_STARTUP = 465 ---- @type GameActivity_t -ACT_OBJ_RUNNING = 466 ---- @type GameActivity_t -ACT_OBJ_IDLE = 467 ---- @type GameActivity_t -ACT_OBJ_PLACING = 468 ---- @type GameActivity_t -ACT_OBJ_DETERIORATING = 469 ---- @type GameActivity_t -ACT_OBJ_UPGRADING = 470 ---- @type GameActivity_t -ACT_DEPLOY = 471 ---- @type GameActivity_t -ACT_DEPLOY_IDLE = 472 ---- @type GameActivity_t -ACT_UNDEPLOY = 473 ---- @type GameActivity_t -ACT_CROSSBOW_DRAW_UNLOADED = 474 ---- @type GameActivity_t -ACT_GAUSS_SPINUP = 475 ---- @type GameActivity_t -ACT_GAUSS_SPINCYCLE = 476 ---- @type GameActivity_t -ACT_VM_PRIMARYATTACK_SILENCED = 477 ---- @type GameActivity_t -ACT_VM_RELOAD_SILENCED = 478 ---- @type GameActivity_t -ACT_VM_DRYFIRE_SILENCED = 479 ---- @type GameActivity_t -ACT_VM_IDLE_SILENCED = 480 ---- @type GameActivity_t -ACT_VM_DRAW_SILENCED = 481 ---- @type GameActivity_t -ACT_VM_IDLE_EMPTY_LEFT = 482 ---- @type GameActivity_t -ACT_VM_DRYFIRE_LEFT = 483 ---- @type GameActivity_t -ACT_VM_IS_DRAW = 484 ---- @type GameActivity_t -ACT_VM_IS_HOLSTER = 485 ---- @type GameActivity_t -ACT_VM_IS_IDLE = 486 ---- @type GameActivity_t -ACT_VM_IS_PRIMARYATTACK = 487 ---- @type GameActivity_t -ACT_PLAYER_IDLE_FIRE = 488 ---- @type GameActivity_t -ACT_PLAYER_CROUCH_FIRE = 489 ---- @type GameActivity_t -ACT_PLAYER_CROUCH_WALK_FIRE = 490 ---- @type GameActivity_t -ACT_PLAYER_WALK_FIRE = 491 ---- @type GameActivity_t -ACT_PLAYER_RUN_FIRE = 492 ---- @type GameActivity_t -ACT_IDLETORUN = 493 ---- @type GameActivity_t -ACT_RUNTOIDLE = 494 ---- @type GameActivity_t -ACT_VM_DRAW_DEPLOYED = 495 ---- @type GameActivity_t -ACT_HL2MP_IDLE_MELEE = 496 ---- @type GameActivity_t -ACT_HL2MP_RUN_MELEE = 497 ---- @type GameActivity_t -ACT_HL2MP_IDLE_CROUCH_MELEE = 498 ---- @type GameActivity_t -ACT_HL2MP_WALK_CROUCH_MELEE = 499 ---- @type GameActivity_t -ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE = 500 ---- @type GameActivity_t -ACT_HL2MP_GESTURE_RELOAD_MELEE = 501 ---- @type GameActivity_t -ACT_HL2MP_JUMP_MELEE = 502 ---- @type GameActivity_t -ACT_MP_STAND_IDLE = 503 ---- @type GameActivity_t -ACT_MP_CROUCH_IDLE = 504 ---- @type GameActivity_t -ACT_MP_CROUCH_DEPLOYED_IDLE = 505 ---- @type GameActivity_t -ACT_MP_CROUCH_DEPLOYED = 506 ---- @type GameActivity_t -ACT_MP_DEPLOYED_IDLE = 507 ---- @type GameActivity_t -ACT_MP_RUN = 508 ---- @type GameActivity_t -ACT_MP_WALK = 509 ---- @type GameActivity_t -ACT_MP_AIRWALK = 510 ---- @type GameActivity_t -ACT_MP_CROUCHWALK = 511 ---- @type GameActivity_t -ACT_MP_SPRINT = 512 ---- @type GameActivity_t -ACT_MP_JUMP = 513 ---- @type GameActivity_t -ACT_MP_JUMP_START = 514 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT = 515 ---- @type GameActivity_t -ACT_MP_JUMP_LAND = 516 ---- @type GameActivity_t -ACT_MP_DOUBLEJUMP = 517 ---- @type GameActivity_t -ACT_MP_SWIM = 518 ---- @type GameActivity_t -ACT_MP_DEPLOYED = 519 ---- @type GameActivity_t -ACT_MP_SWIM_DEPLOYED = 520 ---- @type GameActivity_t -ACT_MP_VCD = 521 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_PRIMARYFIRE = 522 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED = 523 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_SECONDARYFIRE = 524 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_GRENADE = 525 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_PRIMARYFIRE = 526 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED = 527 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_SECONDARYFIRE = 528 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_GRENADE = 529 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_PRIMARYFIRE = 530 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_SECONDARYFIRE = 531 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_GRENADE = 532 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE = 533 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE = 534 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_GRENADE = 535 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND = 536 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_LOOP = 537 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_END = 538 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH = 539 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_LOOP = 540 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_END = 541 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM = 542 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_LOOP = 543 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_END = 544 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK = 545 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_LOOP = 546 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_END = 547 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_PREFIRE = 548 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_POSTFIRE = 549 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_STARTFIRE = 550 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_PREFIRE = 551 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_POSTFIRE = 552 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_PREFIRE = 553 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_POSTFIRE = 554 ---- @type GameActivity_t -ACT_MP_STAND_PRIMARY = 555 ---- @type GameActivity_t -ACT_MP_CROUCH_PRIMARY = 556 ---- @type GameActivity_t -ACT_MP_RUN_PRIMARY = 557 ---- @type GameActivity_t -ACT_MP_WALK_PRIMARY = 558 ---- @type GameActivity_t -ACT_MP_AIRWALK_PRIMARY = 559 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_PRIMARY = 560 ---- @type GameActivity_t -ACT_MP_JUMP_PRIMARY = 561 ---- @type GameActivity_t -ACT_MP_JUMP_START_PRIMARY = 562 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_PRIMARY = 563 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_PRIMARY = 564 ---- @type GameActivity_t -ACT_MP_SWIM_PRIMARY = 565 ---- @type GameActivity_t -ACT_MP_DEPLOYED_PRIMARY = 566 ---- @type GameActivity_t -ACT_MP_SWIM_DEPLOYED_PRIMARY = 567 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_PRIMARY = 568 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED = 569 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_PRIMARY = 570 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED = 571 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_PRIMARY = 572 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_PRIMARY = 573 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_PRIMARY = 574 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_PRIMARY_LOOP = 575 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_PRIMARY_END = 576 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_PRIMARY = 577 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP = 578 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_PRIMARY_END = 579 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_PRIMARY = 580 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_PRIMARY_LOOP = 581 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_PRIMARY_END = 582 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_PRIMARY = 583 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP = 584 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_PRIMARY_END = 585 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_GRENADE_PRIMARY = 586 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY = 587 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY = 588 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY = 589 ---- @type GameActivity_t -ACT_MP_STAND_SECONDARY = 590 ---- @type GameActivity_t -ACT_MP_CROUCH_SECONDARY = 591 ---- @type GameActivity_t -ACT_MP_RUN_SECONDARY = 592 ---- @type GameActivity_t -ACT_MP_WALK_SECONDARY = 593 ---- @type GameActivity_t -ACT_MP_AIRWALK_SECONDARY = 594 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_SECONDARY = 595 ---- @type GameActivity_t -ACT_MP_JUMP_SECONDARY = 596 ---- @type GameActivity_t -ACT_MP_JUMP_START_SECONDARY = 597 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_SECONDARY = 598 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_SECONDARY = 599 ---- @type GameActivity_t -ACT_MP_SWIM_SECONDARY = 600 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_SECONDARY = 601 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_SECONDARY = 602 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_SECONDARY = 603 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_SECONDARY = 604 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_SECONDARY = 605 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_SECONDARY_LOOP = 606 ---- @type GameActivity_t -ACT_MP_RELOAD_STAND_SECONDARY_END = 607 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_SECONDARY = 608 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP = 609 ---- @type GameActivity_t -ACT_MP_RELOAD_CROUCH_SECONDARY_END = 610 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_SECONDARY = 611 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_SECONDARY_LOOP = 612 ---- @type GameActivity_t -ACT_MP_RELOAD_SWIM_SECONDARY_END = 613 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_SECONDARY = 614 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP = 615 ---- @type GameActivity_t -ACT_MP_RELOAD_AIRWALK_SECONDARY_END = 616 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_GRENADE_SECONDARY = 617 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY = 618 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY = 619 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY = 620 ---- @type GameActivity_t -ACT_MP_STAND_MELEE = 621 ---- @type GameActivity_t -ACT_MP_CROUCH_MELEE = 622 ---- @type GameActivity_t -ACT_MP_RUN_MELEE = 623 ---- @type GameActivity_t -ACT_MP_WALK_MELEE = 624 ---- @type GameActivity_t -ACT_MP_AIRWALK_MELEE = 625 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_MELEE = 626 ---- @type GameActivity_t -ACT_MP_JUMP_MELEE = 627 ---- @type GameActivity_t -ACT_MP_JUMP_START_MELEE = 628 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_MELEE = 629 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_MELEE = 630 ---- @type GameActivity_t -ACT_MP_SWIM_MELEE = 631 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_MELEE = 632 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_MELEE_SECONDARY = 633 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_MELEE = 634 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY = 635 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_MELEE = 636 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_MELEE = 637 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_GRENADE_MELEE = 638 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_GRENADE_MELEE = 639 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_GRENADE_MELEE = 640 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE = 641 ---- @type GameActivity_t -ACT_MP_STAND_ITEM1 = 642 ---- @type GameActivity_t -ACT_MP_CROUCH_ITEM1 = 643 ---- @type GameActivity_t -ACT_MP_RUN_ITEM1 = 644 ---- @type GameActivity_t -ACT_MP_WALK_ITEM1 = 645 ---- @type GameActivity_t -ACT_MP_AIRWALK_ITEM1 = 646 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_ITEM1 = 647 ---- @type GameActivity_t -ACT_MP_JUMP_ITEM1 = 648 ---- @type GameActivity_t -ACT_MP_JUMP_START_ITEM1 = 649 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_ITEM1 = 650 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_ITEM1 = 651 ---- @type GameActivity_t -ACT_MP_SWIM_ITEM1 = 652 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_ITEM1 = 653 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_ITEM1_SECONDARY = 654 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_ITEM1 = 655 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_ITEM1_SECONDARY = 656 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_ITEM1 = 657 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_ITEM1 = 658 ---- @type GameActivity_t -ACT_MP_STAND_ITEM2 = 659 ---- @type GameActivity_t -ACT_MP_CROUCH_ITEM2 = 660 ---- @type GameActivity_t -ACT_MP_RUN_ITEM2 = 661 ---- @type GameActivity_t -ACT_MP_WALK_ITEM2 = 662 ---- @type GameActivity_t -ACT_MP_AIRWALK_ITEM2 = 663 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_ITEM2 = 664 ---- @type GameActivity_t -ACT_MP_JUMP_ITEM2 = 665 ---- @type GameActivity_t -ACT_MP_JUMP_START_ITEM2 = 666 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_ITEM2 = 667 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_ITEM2 = 668 ---- @type GameActivity_t -ACT_MP_SWIM_ITEM2 = 669 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_ITEM2 = 670 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_ITEM2_SECONDARY = 671 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_ITEM2 = 672 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_ITEM2_SECONDARY = 673 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_ITEM2 = 674 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_ITEM2 = 675 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH = 676 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_PRIMARY = 677 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_SECONDARY = 678 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_MELEE = 679 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_ITEM1 = 680 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_ITEM2 = 681 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_HEAD = 682 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_CHEST = 683 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_STOMACH = 684 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_LEFTARM = 685 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_RIGHTARM = 686 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_LEFTLEG = 687 ---- @type GameActivity_t -ACT_MP_GESTURE_FLINCH_RIGHTLEG = 688 ---- @type GameActivity_t -ACT_MP_GRENADE1_DRAW = 689 ---- @type GameActivity_t -ACT_MP_GRENADE1_IDLE = 690 ---- @type GameActivity_t -ACT_MP_GRENADE1_ATTACK = 691 ---- @type GameActivity_t -ACT_MP_GRENADE2_DRAW = 692 ---- @type GameActivity_t -ACT_MP_GRENADE2_IDLE = 693 ---- @type GameActivity_t -ACT_MP_GRENADE2_ATTACK = 694 ---- @type GameActivity_t -ACT_MP_PRIMARY_GRENADE1_DRAW = 695 ---- @type GameActivity_t -ACT_MP_PRIMARY_GRENADE1_IDLE = 696 ---- @type GameActivity_t -ACT_MP_PRIMARY_GRENADE1_ATTACK = 697 ---- @type GameActivity_t -ACT_MP_PRIMARY_GRENADE2_DRAW = 698 ---- @type GameActivity_t -ACT_MP_PRIMARY_GRENADE2_IDLE = 699 ---- @type GameActivity_t -ACT_MP_PRIMARY_GRENADE2_ATTACK = 700 ---- @type GameActivity_t -ACT_MP_SECONDARY_GRENADE1_DRAW = 701 ---- @type GameActivity_t -ACT_MP_SECONDARY_GRENADE1_IDLE = 702 ---- @type GameActivity_t -ACT_MP_SECONDARY_GRENADE1_ATTACK = 703 ---- @type GameActivity_t -ACT_MP_SECONDARY_GRENADE2_DRAW = 704 ---- @type GameActivity_t -ACT_MP_SECONDARY_GRENADE2_IDLE = 705 ---- @type GameActivity_t -ACT_MP_SECONDARY_GRENADE2_ATTACK = 706 ---- @type GameActivity_t -ACT_MP_MELEE_GRENADE1_DRAW = 707 ---- @type GameActivity_t -ACT_MP_MELEE_GRENADE1_IDLE = 708 ---- @type GameActivity_t -ACT_MP_MELEE_GRENADE1_ATTACK = 709 ---- @type GameActivity_t -ACT_MP_MELEE_GRENADE2_DRAW = 710 ---- @type GameActivity_t -ACT_MP_MELEE_GRENADE2_IDLE = 711 ---- @type GameActivity_t -ACT_MP_MELEE_GRENADE2_ATTACK = 712 ---- @type GameActivity_t -ACT_MP_ITEM1_GRENADE1_DRAW = 713 ---- @type GameActivity_t -ACT_MP_ITEM1_GRENADE1_IDLE = 714 ---- @type GameActivity_t -ACT_MP_ITEM1_GRENADE1_ATTACK = 715 ---- @type GameActivity_t -ACT_MP_ITEM1_GRENADE2_DRAW = 716 ---- @type GameActivity_t -ACT_MP_ITEM1_GRENADE2_IDLE = 717 ---- @type GameActivity_t -ACT_MP_ITEM1_GRENADE2_ATTACK = 718 ---- @type GameActivity_t -ACT_MP_ITEM2_GRENADE1_DRAW = 719 ---- @type GameActivity_t -ACT_MP_ITEM2_GRENADE1_IDLE = 720 ---- @type GameActivity_t -ACT_MP_ITEM2_GRENADE1_ATTACK = 721 ---- @type GameActivity_t -ACT_MP_ITEM2_GRENADE2_DRAW = 722 ---- @type GameActivity_t -ACT_MP_ITEM2_GRENADE2_IDLE = 723 ---- @type GameActivity_t -ACT_MP_ITEM2_GRENADE2_ATTACK = 724 ---- @type GameActivity_t -ACT_MP_STAND_BUILDING = 725 ---- @type GameActivity_t -ACT_MP_CROUCH_BUILDING = 726 ---- @type GameActivity_t -ACT_MP_RUN_BUILDING = 727 ---- @type GameActivity_t -ACT_MP_WALK_BUILDING = 728 ---- @type GameActivity_t -ACT_MP_AIRWALK_BUILDING = 729 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_BUILDING = 730 ---- @type GameActivity_t -ACT_MP_JUMP_BUILDING = 731 ---- @type GameActivity_t -ACT_MP_JUMP_START_BUILDING = 732 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_BUILDING = 733 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_BUILDING = 734 ---- @type GameActivity_t -ACT_MP_SWIM_BUILDING = 735 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_BUILDING = 736 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_BUILDING = 737 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_BUILDING = 738 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_BUILDING = 739 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_GRENADE_BUILDING = 740 ---- @type GameActivity_t -ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING = 741 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_GRENADE_BUILDING = 742 ---- @type GameActivity_t -ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING = 743 ---- @type GameActivity_t -ACT_MP_STAND_PDA = 744 ---- @type GameActivity_t -ACT_MP_CROUCH_PDA = 745 ---- @type GameActivity_t -ACT_MP_RUN_PDA = 746 ---- @type GameActivity_t -ACT_MP_WALK_PDA = 747 ---- @type GameActivity_t -ACT_MP_AIRWALK_PDA = 748 ---- @type GameActivity_t -ACT_MP_CROUCHWALK_PDA = 749 ---- @type GameActivity_t -ACT_MP_JUMP_PDA = 750 ---- @type GameActivity_t -ACT_MP_JUMP_START_PDA = 751 ---- @type GameActivity_t -ACT_MP_JUMP_FLOAT_PDA = 752 ---- @type GameActivity_t -ACT_MP_JUMP_LAND_PDA = 753 ---- @type GameActivity_t -ACT_MP_SWIM_PDA = 754 ---- @type GameActivity_t -ACT_MP_ATTACK_STAND_PDA = 755 ---- @type GameActivity_t -ACT_MP_ATTACK_SWIM_PDA = 756 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH = 757 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT = 758 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP = 759 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP = 760 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES = 761 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO = 762 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY = 763 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY = 764 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY = 765 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY = 766 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_PRIMARY = 767 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_PRIMARY = 768 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY = 769 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY = 770 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY = 771 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY = 772 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_SECONDARY = 773 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_SECONDARY = 774 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_MELEE = 775 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_MELEE = 776 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_MELEE = 777 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_MELEE = 778 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_MELEE = 779 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_MELEE = 780 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_ITEM1 = 781 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_ITEM1 = 782 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_ITEM1 = 783 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_ITEM1 = 784 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_ITEM1 = 785 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_ITEM1 = 786 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_ITEM2 = 787 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_ITEM2 = 788 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_ITEM2 = 789 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_ITEM2 = 790 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_ITEM2 = 791 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_ITEM2 = 792 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING = 793 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING = 794 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_BUILDING = 795 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_BUILDING = 796 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_BUILDING = 797 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_BUILDING = 798 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_HANDMOUTH_PDA = 799 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FINGERPOINT_PDA = 800 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_FISTPUMP_PDA = 801 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_THUMBSUP_PDA = 802 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODYES_PDA = 803 ---- @type GameActivity_t -ACT_MP_GESTURE_VC_NODNO_PDA = 804 ---- @type GameActivity_t -ACT_VM_UNUSABLE = 805 ---- @type GameActivity_t -ACT_VM_UNUSABLE_TO_USABLE = 806 ---- @type GameActivity_t -ACT_VM_USABLE_TO_UNUSABLE = 807 ---- @type GameActivity_t -ACT_PRIMARY_VM_DRAW = 808 ---- @type GameActivity_t -ACT_PRIMARY_VM_HOLSTER = 809 ---- @type GameActivity_t -ACT_PRIMARY_VM_IDLE = 810 ---- @type GameActivity_t -ACT_PRIMARY_VM_PULLBACK = 811 ---- @type GameActivity_t -ACT_PRIMARY_VM_PRIMARYATTACK = 812 ---- @type GameActivity_t -ACT_PRIMARY_VM_SECONDARYATTACK = 813 ---- @type GameActivity_t -ACT_PRIMARY_VM_RELOAD = 814 ---- @type GameActivity_t -ACT_PRIMARY_VM_DRYFIRE = 815 ---- @type GameActivity_t -ACT_PRIMARY_VM_IDLE_TO_LOWERED = 816 ---- @type GameActivity_t -ACT_PRIMARY_VM_IDLE_LOWERED = 817 ---- @type GameActivity_t -ACT_PRIMARY_VM_LOWERED_TO_IDLE = 818 ---- @type GameActivity_t -ACT_SECONDARY_VM_DRAW = 819 ---- @type GameActivity_t -ACT_SECONDARY_VM_HOLSTER = 820 ---- @type GameActivity_t -ACT_SECONDARY_VM_IDLE = 821 ---- @type GameActivity_t -ACT_SECONDARY_VM_PULLBACK = 822 ---- @type GameActivity_t -ACT_SECONDARY_VM_PRIMARYATTACK = 823 ---- @type GameActivity_t -ACT_SECONDARY_VM_SECONDARYATTACK = 824 ---- @type GameActivity_t -ACT_SECONDARY_VM_RELOAD = 825 ---- @type GameActivity_t -ACT_SECONDARY_VM_DRYFIRE = 826 ---- @type GameActivity_t -ACT_SECONDARY_VM_IDLE_TO_LOWERED = 827 ---- @type GameActivity_t -ACT_SECONDARY_VM_IDLE_LOWERED = 828 ---- @type GameActivity_t -ACT_SECONDARY_VM_LOWERED_TO_IDLE = 829 ---- @type GameActivity_t -ACT_MELEE_VM_DRAW = 830 ---- @type GameActivity_t -ACT_MELEE_VM_HOLSTER = 831 ---- @type GameActivity_t -ACT_MELEE_VM_IDLE = 832 ---- @type GameActivity_t -ACT_MELEE_VM_PULLBACK = 833 ---- @type GameActivity_t -ACT_MELEE_VM_PRIMARYATTACK = 834 ---- @type GameActivity_t -ACT_MELEE_VM_SECONDARYATTACK = 835 ---- @type GameActivity_t -ACT_MELEE_VM_RELOAD = 836 ---- @type GameActivity_t -ACT_MELEE_VM_DRYFIRE = 837 ---- @type GameActivity_t -ACT_MELEE_VM_IDLE_TO_LOWERED = 838 ---- @type GameActivity_t -ACT_MELEE_VM_IDLE_LOWERED = 839 ---- @type GameActivity_t -ACT_MELEE_VM_LOWERED_TO_IDLE = 840 ---- @type GameActivity_t -ACT_PDA_VM_DRAW = 841 ---- @type GameActivity_t -ACT_PDA_VM_HOLSTER = 842 ---- @type GameActivity_t -ACT_PDA_VM_IDLE = 843 ---- @type GameActivity_t -ACT_PDA_VM_PULLBACK = 844 ---- @type GameActivity_t -ACT_PDA_VM_PRIMARYATTACK = 845 ---- @type GameActivity_t -ACT_PDA_VM_SECONDARYATTACK = 846 ---- @type GameActivity_t -ACT_PDA_VM_RELOAD = 847 ---- @type GameActivity_t -ACT_PDA_VM_DRYFIRE = 848 ---- @type GameActivity_t -ACT_PDA_VM_IDLE_TO_LOWERED = 849 ---- @type GameActivity_t -ACT_PDA_VM_IDLE_LOWERED = 850 ---- @type GameActivity_t -ACT_PDA_VM_LOWERED_TO_IDLE = 851 ---- @type GameActivity_t -ACT_ITEM1_VM_DRAW = 852 ---- @type GameActivity_t -ACT_ITEM1_VM_HOLSTER = 853 ---- @type GameActivity_t -ACT_ITEM1_VM_IDLE = 854 ---- @type GameActivity_t -ACT_ITEM1_VM_PULLBACK = 855 ---- @type GameActivity_t -ACT_ITEM1_VM_PRIMARYATTACK = 856 ---- @type GameActivity_t -ACT_ITEM1_VM_SECONDARYATTACK = 857 ---- @type GameActivity_t -ACT_ITEM1_VM_RELOAD = 858 ---- @type GameActivity_t -ACT_ITEM1_VM_DRYFIRE = 859 ---- @type GameActivity_t -ACT_ITEM1_VM_IDLE_TO_LOWERED = 860 ---- @type GameActivity_t -ACT_ITEM1_VM_IDLE_LOWERED = 861 ---- @type GameActivity_t -ACT_ITEM1_VM_LOWERED_TO_IDLE = 862 ---- @type GameActivity_t -ACT_ITEM2_VM_DRAW = 863 ---- @type GameActivity_t -ACT_ITEM2_VM_HOLSTER = 864 ---- @type GameActivity_t -ACT_ITEM2_VM_IDLE = 865 ---- @type GameActivity_t -ACT_ITEM2_VM_PULLBACK = 866 ---- @type GameActivity_t -ACT_ITEM2_VM_PRIMARYATTACK = 867 ---- @type GameActivity_t -ACT_ITEM2_VM_SECONDARYATTACK = 868 ---- @type GameActivity_t -ACT_ITEM2_VM_RELOAD = 869 ---- @type GameActivity_t -ACT_ITEM2_VM_DRYFIRE = 870 ---- @type GameActivity_t -ACT_ITEM2_VM_IDLE_TO_LOWERED = 871 ---- @type GameActivity_t -ACT_ITEM2_VM_IDLE_LOWERED = 872 ---- @type GameActivity_t -ACT_ITEM2_VM_LOWERED_TO_IDLE = 873 ---- @type GameActivity_t -ACT_RELOAD_SUCCEED = 874 ---- @type GameActivity_t -ACT_RELOAD_FAIL = 875 ---- @type GameActivity_t -ACT_WALK_AIM_AUTOGUN = 876 ---- @type GameActivity_t -ACT_RUN_AIM_AUTOGUN = 877 ---- @type GameActivity_t -ACT_IDLE_AUTOGUN = 878 ---- @type GameActivity_t -ACT_IDLE_AIM_AUTOGUN = 879 ---- @type GameActivity_t -ACT_RELOAD_AUTOGUN = 880 ---- @type GameActivity_t -ACT_CROUCH_IDLE_AUTOGUN = 881 ---- @type GameActivity_t -ACT_RANGE_ATTACK_AUTOGUN = 882 ---- @type GameActivity_t -ACT_JUMP_AUTOGUN = 883 ---- @type GameActivity_t -ACT_IDLE_AIM_PISTOL = 884 ---- @type GameActivity_t -ACT_WALK_AIM_DUAL = 885 ---- @type GameActivity_t -ACT_RUN_AIM_DUAL = 886 ---- @type GameActivity_t -ACT_IDLE_DUAL = 887 ---- @type GameActivity_t -ACT_IDLE_AIM_DUAL = 888 ---- @type GameActivity_t -ACT_RELOAD_DUAL = 889 ---- @type GameActivity_t -ACT_CROUCH_IDLE_DUAL = 890 ---- @type GameActivity_t -ACT_RANGE_ATTACK_DUAL = 891 ---- @type GameActivity_t -ACT_JUMP_DUAL = 892 ---- @type GameActivity_t -ACT_IDLE_AIM_SHOTGUN = 893 ---- @type GameActivity_t -ACT_CROUCH_IDLE_SHOTGUN = 894 ---- @type GameActivity_t -ACT_IDLE_AIM_RIFLE = 895 ---- @type GameActivity_t -ACT_CROUCH_IDLE_RIFLE = 896 ---- @type GameActivity_t -ACT_RANGE_ATTACK_RIFLE = 897 ---- @type GameActivity_t -ACT_SLEEP = 898 ---- @type GameActivity_t -ACT_WAKE = 899 ---- @type GameActivity_t -ACT_FLICK_LEFT = 900 ---- @type GameActivity_t -ACT_FLICK_LEFT_MIDDLE = 901 ---- @type GameActivity_t -ACT_FLICK_RIGHT_MIDDLE = 902 ---- @type GameActivity_t -ACT_FLICK_RIGHT = 903 ---- @type GameActivity_t -ACT_SPINAROUND = 904 ---- @type GameActivity_t -ACT_PREP_TO_FIRE = 905 ---- @type GameActivity_t -ACT_FIRE = 906 ---- @type GameActivity_t -ACT_FIRE_RECOVER = 907 ---- @type GameActivity_t -ACT_SPRAY = 908 ---- @type GameActivity_t -ACT_PREP_EXPLODE = 909 ---- @type GameActivity_t -ACT_EXPLODE = 910 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_0 = 911 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_1 = 912 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_2 = 913 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_3 = 914 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_4 = 915 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_5 = 916 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_6 = 917 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_7 = 918 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_8 = 919 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_9 = 920 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_10 = 921 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_11 = 922 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_12 = 923 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_13 = 924 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_14 = 925 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_15 = 926 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_16 = 927 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_17 = 928 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_18 = 929 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_19 = 930 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_20 = 931 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_21 = 932 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_22 = 933 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_23 = 934 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_24 = 935 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_25 = 936 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_26 = 937 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_27 = 938 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_28 = 939 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_29 = 940 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_30 = 941 ---- @type GameActivity_t -ACT_SCRIPT_CUSTOM_31 = 942 ---- @type GameActivity_t -ACT_VR_PISTOL_LAST_SHOT = 943 ---- @type GameActivity_t -ACT_VR_PISTOL_SLIDE_RELEASE = 944 ---- @type GameActivity_t -ACT_VR_PISTOL_CLIP_OUT_CHAMBERED = 945 ---- @type GameActivity_t -ACT_VR_PISTOL_CLIP_OUT_SLIDE_BACK = 946 ---- @type GameActivity_t -ACT_VR_PISTOL_CLIP_IN_CHAMBERED = 947 ---- @type GameActivity_t -ACT_VR_PISTOL_CLIP_IN_SLIDE_BACK = 948 ---- @type GameActivity_t -ACT_VR_PISTOL_IDLE_SLIDE_BACK = 949 ---- @type GameActivity_t -ACT_VR_PISTOL_IDLE_SLIDE_BACK_CLIP_READY = 950 ---- @type GameActivity_t -ACT_RAGDOLL_RECOVERY_FRONT = 951 ---- @type GameActivity_t -ACT_RAGDOLL_RECOVERY_BACK = 952 ---- @type GameActivity_t -ACT_RAGDOLL_RECOVERY_LEFT = 953 ---- @type GameActivity_t -ACT_RAGDOLL_RECOVERY_RIGHT = 954 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_GRAB = 955 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_RELEASE = 956 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_GRAB_IDLE = 957 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_ACTIVE = 958 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_ACTIVE_IDLE = 959 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_DEACTIVATE = 960 ---- @type GameActivity_t -ACT_GRABBITYGLOVES_PULL = 961 ---- @type GameActivity_t -ACT_HEADCRAB_SMOKE_BOMB = 962 ---- @type GameActivity_t -ACT_HEADCRAB_SPIT = 963 ---- @type GameActivity_t -ACT_ZOMBIE_TRIP = 964 ---- @type GameActivity_t -ACT_ZOMBIE_LUNGE = 965 ---- @type GameActivity_t -ACT_NEUTRAL_REF_POSE = 966 ---- @type GameActivity_t -ACT_ANTLION_SCUTTLE_FORWARD = 967 ---- @type GameActivity_t -ACT_ANTLION_SCUTTLE_BACK = 968 ---- @type GameActivity_t -ACT_ANTLION_SCUTTLE_LEFT = 969 ---- @type GameActivity_t -ACT_ANTLION_SCUTTLE_RIGHT = 970 ---- @type GameActivity_t -ACT_VR_PISTOL_EMPTY_CLIP_IN_SLIDE_BACK = 971 ---- @type GameActivity_t -ACT_VR_SHOTGUN_IDLE = 972 ---- @type GameActivity_t -ACT_VR_SHOTGUN_OPEN_CHAMBER = 973 ---- @type GameActivity_t -ACT_VR_SHOTGUN_RELOAD_1 = 974 ---- @type GameActivity_t -ACT_VR_SHOTGUN_RELOAD_2 = 975 ---- @type GameActivity_t -ACT_VR_SHOTGUN_RELOAD_3 = 976 ---- @type GameActivity_t -ACT_VR_SHOTGUN_CLOSE_CHAMBER = 977 ---- @type GameActivity_t -ACT_VR_SHOTGUN_TRIGGER_SQUEEZE = 978 ---- @type GameActivity_t -ACT_VR_SHOTGUN_SHOOT = 979 ---- @type GameActivity_t -ACT_VR_SHOTGUN_SLIDE_BACK = 980 ---- @type GameActivity_t -ACT_VR_SHOTGUN_SLIDE_FORWARD = 981 ---- @type GameActivity_t -ACT_VR_PISTOL_LONG_CLIP_IN_CHAMBERED = 982 ---- @type GameActivity_t -ACT_VR_PISTOL_LONG_CLIP_IN_SLIDE_BACK = 983 ---- @type GameActivity_t -ACT_VR_PISTOL_BURST_TOGGLE = 984 ---- @type GameActivity_t -ACT_VR_PISTOL_LOW_KICK = 985 ---- @type GameActivity_t -ACT_VR_PISTOL_BURST_ATTACK = 986 ---- @type GameActivity_t -ACT_VR_SHOTGUN_GRENADE_TWIST = 987 ---- @type GameActivity_t -ACT_DIE_STAND = 988 ---- @type GameActivity_t -ACT_DIE_STAND_HEADSHOT = 989 ---- @type GameActivity_t -ACT_DIE_CROUCH = 990 ---- @type GameActivity_t -ACT_DIE_CROUCH_HEADSHOT = 991 ---- @type GameActivity_t -ACT_CSGO_NULL = 992 ---- @type GameActivity_t -ACT_CSGO_DEFUSE = 993 ---- @type GameActivity_t -ACT_CSGO_DEFUSE_WITH_KIT = 994 ---- @type GameActivity_t -ACT_CSGO_FLASHBANG_REACTION = 995 ---- @type GameActivity_t -ACT_CSGO_FIRE_PRIMARY = 996 ---- @type GameActivity_t -ACT_CSGO_FIRE_PRIMARY_OPT_1 = 997 ---- @type GameActivity_t -ACT_CSGO_FIRE_PRIMARY_OPT_2 = 998 ---- @type GameActivity_t -ACT_CSGO_FIRE_SECONDARY = 999 ---- @type GameActivity_t -ACT_CSGO_FIRE_SECONDARY_OPT_1 = 1000 ---- @type GameActivity_t -ACT_CSGO_FIRE_SECONDARY_OPT_2 = 1001 ---- @type GameActivity_t -ACT_CSGO_RELOAD = 1002 ---- @type GameActivity_t -ACT_CSGO_RELOAD_START = 1003 ---- @type GameActivity_t -ACT_CSGO_RELOAD_LOOP = 1004 ---- @type GameActivity_t -ACT_CSGO_RELOAD_END = 1005 ---- @type GameActivity_t -ACT_CSGO_OPERATE = 1006 ---- @type GameActivity_t -ACT_CSGO_DEPLOY = 1007 ---- @type GameActivity_t -ACT_CSGO_CATCH = 1008 ---- @type GameActivity_t -ACT_CSGO_SILENCER_DETACH = 1009 ---- @type GameActivity_t -ACT_CSGO_SILENCER_ATTACH = 1010 ---- @type GameActivity_t -ACT_CSGO_TWITCH = 1011 ---- @type GameActivity_t -ACT_CSGO_TWITCH_BUYZONE = 1012 ---- @type GameActivity_t -ACT_CSGO_PLANT_BOMB = 1013 ---- @type GameActivity_t -ACT_CSGO_IDLE_TURN_BALANCEADJUST = 1014 ---- @type GameActivity_t -ACT_CSGO_IDLE_ADJUST_STOPPEDMOVING = 1015 ---- @type GameActivity_t -ACT_CSGO_ALIVE_LOOP = 1016 ---- @type GameActivity_t -ACT_CSGO_FLINCH = 1017 ---- @type GameActivity_t -ACT_CSGO_FLINCH_HEAD = 1018 ---- @type GameActivity_t -ACT_CSGO_FLINCH_MOLOTOV = 1019 ---- @type GameActivity_t -ACT_CSGO_JUMP = 1020 ---- @type GameActivity_t -ACT_CSGO_FALL = 1021 ---- @type GameActivity_t -ACT_CSGO_CLIMB_LADDER = 1022 ---- @type GameActivity_t -ACT_CSGO_LAND_LIGHT = 1023 ---- @type GameActivity_t -ACT_CSGO_LAND_HEAVY = 1024 ---- @type GameActivity_t -ACT_CSGO_EXIT_LADDER_TOP = 1025 ---- @type GameActivity_t -ACT_CSGO_EXIT_LADDER_BOTTOM = 1026 ---- @type GameActivity_t -ACT_CSGO_PARACHUTE = 1027 ---- @type GameActivity_t -ACT_CSGO_TAUNT = 1028 ---- @type GameActivity_t -ACT_DOTA_IDLE = 1500 ---- @type GameActivity_t -ACT_DOTA_IDLE_RARE = 1501 ---- @type GameActivity_t -ACT_DOTA_RUN = 1502 ---- @type GameActivity_t -ACT_DOTA_ATTACK = 1503 ---- @type GameActivity_t -ACT_DOTA_ATTACK2 = 1504 ---- @type GameActivity_t -ACT_DOTA_ATTACK_EVENT = 1505 ---- @type GameActivity_t -ACT_DOTA_DIE = 1506 ---- @type GameActivity_t -ACT_DOTA_FLINCH = 1507 ---- @type GameActivity_t -ACT_DOTA_FLAIL = 1508 ---- @type GameActivity_t -ACT_DOTA_DISABLED = 1509 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_1 = 1510 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_2 = 1511 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_3 = 1512 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_4 = 1513 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_5 = 1514 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_6 = 1515 ---- @type GameActivity_t -ACT_DOTA_OVERRIDE_ABILITY_1 = 1516 ---- @type GameActivity_t -ACT_DOTA_OVERRIDE_ABILITY_2 = 1517 ---- @type GameActivity_t -ACT_DOTA_OVERRIDE_ABILITY_3 = 1518 ---- @type GameActivity_t -ACT_DOTA_OVERRIDE_ABILITY_4 = 1519 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_1 = 1520 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_2 = 1521 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_3 = 1522 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_4 = 1523 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_5 = 1524 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_6 = 1525 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_END_ABILITY_1 = 1526 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_END_ABILITY_2 = 1527 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_END_ABILITY_3 = 1528 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_END_ABILITY_4 = 1529 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_END_ABILITY_5 = 1530 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_END_ABILITY_6 = 1531 ---- @type GameActivity_t -ACT_DOTA_CONSTANT_LAYER = 1532 ---- @type GameActivity_t -ACT_DOTA_CAPTURE = 1533 ---- @type GameActivity_t -ACT_DOTA_SPAWN = 1534 ---- @type GameActivity_t -ACT_DOTA_KILLTAUNT = 1535 ---- @type GameActivity_t -ACT_DOTA_TAUNT = 1536 ---- @type GameActivity_t -ACT_DOTA_THIRST = 1537 ---- @type GameActivity_t -ACT_DOTA_CAST_DRAGONBREATH = 1538 ---- @type GameActivity_t -ACT_DOTA_ECHO_SLAM = 1539 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_1_END = 1540 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_2_END = 1541 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_3_END = 1542 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_4_END = 1543 ---- @type GameActivity_t -ACT_MIRANA_LEAP_END = 1544 ---- @type GameActivity_t -ACT_WAVEFORM_START = 1545 ---- @type GameActivity_t -ACT_WAVEFORM_END = 1546 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_ROT = 1547 ---- @type GameActivity_t -ACT_DOTA_DIE_SPECIAL = 1548 ---- @type GameActivity_t -ACT_DOTA_RATTLETRAP_BATTERYASSAULT = 1549 ---- @type GameActivity_t -ACT_DOTA_RATTLETRAP_POWERCOGS = 1550 ---- @type GameActivity_t -ACT_DOTA_RATTLETRAP_HOOKSHOT_START = 1551 ---- @type GameActivity_t -ACT_DOTA_RATTLETRAP_HOOKSHOT_LOOP = 1552 ---- @type GameActivity_t -ACT_DOTA_RATTLETRAP_HOOKSHOT_END = 1553 ---- @type GameActivity_t -ACT_STORM_SPIRIT_OVERLOAD_RUN_OVERRIDE = 1554 ---- @type GameActivity_t -ACT_DOTA_TINKER_REARM1 = 1555 ---- @type GameActivity_t -ACT_DOTA_TINKER_REARM2 = 1556 ---- @type GameActivity_t -ACT_DOTA_TINKER_REARM3 = 1557 ---- @type GameActivity_t -ACT_TINY_AVALANCHE = 1558 ---- @type GameActivity_t -ACT_TINY_TOSS = 1559 ---- @type GameActivity_t -ACT_TINY_GROWL = 1560 ---- @type GameActivity_t -ACT_DOTA_WEAVERBUG_ATTACH = 1561 ---- @type GameActivity_t -ACT_DOTA_CAST_WILD_AXES_END = 1562 ---- @type GameActivity_t -ACT_DOTA_CAST_LIFE_BREAK_START = 1563 ---- @type GameActivity_t -ACT_DOTA_CAST_LIFE_BREAK_END = 1564 ---- @type GameActivity_t -ACT_DOTA_NIGHTSTALKER_TRANSITION = 1565 ---- @type GameActivity_t -ACT_DOTA_LIFESTEALER_RAGE = 1566 ---- @type GameActivity_t -ACT_DOTA_LIFESTEALER_OPEN_WOUNDS = 1567 ---- @type GameActivity_t -ACT_DOTA_SAND_KING_BURROW_IN = 1568 ---- @type GameActivity_t -ACT_DOTA_SAND_KING_BURROW_OUT = 1569 ---- @type GameActivity_t -ACT_DOTA_EARTHSHAKER_TOTEM_ATTACK = 1570 ---- @type GameActivity_t -ACT_DOTA_WHEEL_LAYER = 1571 ---- @type GameActivity_t -ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START = 1572 ---- @type GameActivity_t -ACT_DOTA_ALCHEMIST_CONCOCTION = 1573 ---- @type GameActivity_t -ACT_DOTA_JAKIRO_LIQUIDFIRE_START = 1574 ---- @type GameActivity_t -ACT_DOTA_JAKIRO_LIQUIDFIRE_LOOP = 1575 ---- @type GameActivity_t -ACT_DOTA_LIFESTEALER_INFEST = 1576 ---- @type GameActivity_t -ACT_DOTA_LIFESTEALER_INFEST_END = 1577 ---- @type GameActivity_t -ACT_DOTA_LASSO_LOOP = 1578 ---- @type GameActivity_t -ACT_DOTA_ALCHEMIST_CONCOCTION_THROW = 1579 ---- @type GameActivity_t -ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END = 1580 ---- @type GameActivity_t -ACT_DOTA_CAST_COLD_SNAP = 1581 ---- @type GameActivity_t -ACT_DOTA_CAST_GHOST_WALK = 1582 ---- @type GameActivity_t -ACT_DOTA_CAST_TORNADO = 1583 ---- @type GameActivity_t -ACT_DOTA_CAST_EMP = 1584 ---- @type GameActivity_t -ACT_DOTA_CAST_ALACRITY = 1585 ---- @type GameActivity_t -ACT_DOTA_CAST_CHAOS_METEOR = 1586 ---- @type GameActivity_t -ACT_DOTA_CAST_SUN_STRIKE = 1587 ---- @type GameActivity_t -ACT_DOTA_CAST_FORGE_SPIRIT = 1588 ---- @type GameActivity_t -ACT_DOTA_CAST_ICE_WALL = 1589 ---- @type GameActivity_t -ACT_DOTA_CAST_DEAFENING_BLAST = 1590 ---- @type GameActivity_t -ACT_DOTA_VICTORY = 1591 ---- @type GameActivity_t -ACT_DOTA_DEFEAT = 1592 ---- @type GameActivity_t -ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE = 1593 ---- @type GameActivity_t -ACT_DOTA_SPIRIT_BREAKER_CHARGE_END = 1594 ---- @type GameActivity_t -ACT_DOTA_TELEPORT = 1595 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_END = 1596 ---- @type GameActivity_t -ACT_DOTA_CAST_REFRACTION = 1597 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_7 = 1598 ---- @type GameActivity_t -ACT_DOTA_CANCEL_SIREN_SONG = 1599 ---- @type GameActivity_t -ACT_DOTA_CHANNEL_ABILITY_7 = 1600 ---- @type GameActivity_t -ACT_DOTA_LOADOUT = 1601 ---- @type GameActivity_t -ACT_DOTA_FORCESTAFF_END = 1602 ---- @type GameActivity_t -ACT_DOTA_POOF_END = 1603 ---- @type GameActivity_t -ACT_DOTA_SLARK_POUNCE = 1604 ---- @type GameActivity_t -ACT_DOTA_MAGNUS_SKEWER_START = 1605 ---- @type GameActivity_t -ACT_DOTA_MAGNUS_SKEWER_END = 1606 ---- @type GameActivity_t -ACT_DOTA_MEDUSA_STONE_GAZE = 1607 ---- @type GameActivity_t -ACT_DOTA_RELAX_START = 1608 ---- @type GameActivity_t -ACT_DOTA_RELAX_LOOP = 1609 ---- @type GameActivity_t -ACT_DOTA_RELAX_END = 1610 ---- @type GameActivity_t -ACT_DOTA_CENTAUR_STAMPEDE = 1611 ---- @type GameActivity_t -ACT_DOTA_BELLYACHE_START = 1612 ---- @type GameActivity_t -ACT_DOTA_BELLYACHE_LOOP = 1613 ---- @type GameActivity_t -ACT_DOTA_BELLYACHE_END = 1614 ---- @type GameActivity_t -ACT_DOTA_ROQUELAIRE_LAND = 1615 ---- @type GameActivity_t -ACT_DOTA_ROQUELAIRE_LAND_IDLE = 1616 ---- @type GameActivity_t -ACT_DOTA_GREEVIL_CAST = 1617 ---- @type GameActivity_t -ACT_DOTA_GREEVIL_OVERRIDE_ABILITY = 1618 ---- @type GameActivity_t -ACT_DOTA_GREEVIL_HOOK_START = 1619 ---- @type GameActivity_t -ACT_DOTA_GREEVIL_HOOK_END = 1620 ---- @type GameActivity_t -ACT_DOTA_GREEVIL_BLINK_BONE = 1621 ---- @type GameActivity_t -ACT_DOTA_IDLE_SLEEPING = 1622 ---- @type GameActivity_t -ACT_DOTA_INTRO = 1623 ---- @type GameActivity_t -ACT_DOTA_GESTURE_POINT = 1624 ---- @type GameActivity_t -ACT_DOTA_GESTURE_ACCENT = 1625 ---- @type GameActivity_t -ACT_DOTA_SLEEPING_END = 1626 ---- @type GameActivity_t -ACT_DOTA_AMBUSH = 1627 ---- @type GameActivity_t -ACT_DOTA_ITEM_LOOK = 1628 ---- @type GameActivity_t -ACT_DOTA_STARTLE = 1629 ---- @type GameActivity_t -ACT_DOTA_FRUSTRATION = 1630 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_REACT = 1631 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_END_REACT = 1632 ---- @type GameActivity_t -ACT_DOTA_SHRUG = 1633 ---- @type GameActivity_t -ACT_DOTA_RELAX_LOOP_END = 1634 ---- @type GameActivity_t -ACT_DOTA_PRESENT_ITEM = 1635 ---- @type GameActivity_t -ACT_DOTA_IDLE_IMPATIENT = 1636 ---- @type GameActivity_t -ACT_DOTA_SHARPEN_WEAPON = 1637 ---- @type GameActivity_t -ACT_DOTA_SHARPEN_WEAPON_OUT = 1638 ---- @type GameActivity_t -ACT_DOTA_IDLE_SLEEPING_END = 1639 ---- @type GameActivity_t -ACT_DOTA_BRIDGE_DESTROY = 1640 ---- @type GameActivity_t -ACT_DOTA_TAUNT_SNIPER = 1641 ---- @type GameActivity_t -ACT_DOTA_DEATH_BY_SNIPER = 1642 ---- @type GameActivity_t -ACT_DOTA_LOOK_AROUND = 1643 ---- @type GameActivity_t -ACT_DOTA_CAGED_CREEP_RAGE = 1644 ---- @type GameActivity_t -ACT_DOTA_CAGED_CREEP_RAGE_OUT = 1645 ---- @type GameActivity_t -ACT_DOTA_CAGED_CREEP_SMASH = 1646 ---- @type GameActivity_t -ACT_DOTA_CAGED_CREEP_SMASH_OUT = 1647 ---- @type GameActivity_t -ACT_DOTA_IDLE_IMPATIENT_SWORD_TAP = 1648 ---- @type GameActivity_t -ACT_DOTA_INTRO_LOOP = 1649 ---- @type GameActivity_t -ACT_DOTA_BRIDGE_THREAT = 1650 ---- @type GameActivity_t -ACT_DOTA_DAGON = 1651 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_2_ES_ROLL_START = 1652 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_2_ES_ROLL = 1653 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_2_ES_ROLL_END = 1654 ---- @type GameActivity_t -ACT_DOTA_NIAN_PIN_START = 1655 ---- @type GameActivity_t -ACT_DOTA_NIAN_PIN_LOOP = 1656 ---- @type GameActivity_t -ACT_DOTA_NIAN_PIN_END = 1657 ---- @type GameActivity_t -ACT_DOTA_LEAP_STUN = 1658 ---- @type GameActivity_t -ACT_DOTA_LEAP_SWIPE = 1659 ---- @type GameActivity_t -ACT_DOTA_NIAN_INTRO_LEAP = 1660 ---- @type GameActivity_t -ACT_DOTA_AREA_DENY = 1661 ---- @type GameActivity_t -ACT_DOTA_NIAN_PIN_TO_STUN = 1662 ---- @type GameActivity_t -ACT_DOTA_RAZE_1 = 1663 ---- @type GameActivity_t -ACT_DOTA_RAZE_2 = 1664 ---- @type GameActivity_t -ACT_DOTA_RAZE_3 = 1665 ---- @type GameActivity_t -ACT_DOTA_UNDYING_DECAY = 1666 ---- @type GameActivity_t -ACT_DOTA_UNDYING_SOUL_RIP = 1667 ---- @type GameActivity_t -ACT_DOTA_UNDYING_TOMBSTONE = 1668 ---- @type GameActivity_t -ACT_DOTA_WHIRLING_AXES_RANGED = 1669 ---- @type GameActivity_t -ACT_DOTA_SHALLOW_GRAVE = 1670 ---- @type GameActivity_t -ACT_DOTA_COLD_FEET = 1671 ---- @type GameActivity_t -ACT_DOTA_ICE_VORTEX = 1672 ---- @type GameActivity_t -ACT_DOTA_CHILLING_TOUCH = 1673 ---- @type GameActivity_t -ACT_DOTA_ENFEEBLE = 1674 ---- @type GameActivity_t -ACT_DOTA_FATAL_BONDS = 1675 ---- @type GameActivity_t -ACT_DOTA_MIDNIGHT_PULSE = 1676 ---- @type GameActivity_t -ACT_DOTA_ANCESTRAL_SPIRIT = 1677 ---- @type GameActivity_t -ACT_DOTA_THUNDER_STRIKE = 1678 ---- @type GameActivity_t -ACT_DOTA_KINETIC_FIELD = 1679 ---- @type GameActivity_t -ACT_DOTA_STATIC_STORM = 1680 ---- @type GameActivity_t -ACT_DOTA_MINI_TAUNT = 1681 ---- @type GameActivity_t -ACT_DOTA_ARCTIC_BURN_END = 1682 ---- @type GameActivity_t -ACT_DOTA_LOADOUT_RARE = 1683 ---- @type GameActivity_t -ACT_DOTA_SWIM = 1684 ---- @type GameActivity_t -ACT_DOTA_FLEE = 1685 ---- @type GameActivity_t -ACT_DOTA_TROT = 1686 ---- @type GameActivity_t -ACT_DOTA_SHAKE = 1687 ---- @type GameActivity_t -ACT_DOTA_SWIM_IDLE = 1688 ---- @type GameActivity_t -ACT_DOTA_WAIT_IDLE = 1689 ---- @type GameActivity_t -ACT_DOTA_GREET = 1690 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_COOP_START = 1691 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_COOP_WAIT = 1692 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_COOP_END = 1693 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_COOP_EXIT = 1694 ---- @type GameActivity_t -ACT_DOTA_SHOPKEEPER_PET_INTERACT = 1695 ---- @type GameActivity_t -ACT_DOTA_ITEM_PICKUP = 1696 ---- @type GameActivity_t -ACT_DOTA_ITEM_DROP = 1697 ---- @type GameActivity_t -ACT_DOTA_CAPTURE_PET = 1698 ---- @type GameActivity_t -ACT_DOTA_PET_WARD_OBSERVER = 1699 ---- @type GameActivity_t -ACT_DOTA_PET_WARD_SENTRY = 1700 ---- @type GameActivity_t -ACT_DOTA_PET_LEVEL = 1701 ---- @type GameActivity_t -ACT_DOTA_CAST_BURROW_END = 1702 ---- @type GameActivity_t -ACT_DOTA_LIFESTEALER_ASSIMILATE = 1703 ---- @type GameActivity_t -ACT_DOTA_LIFESTEALER_EJECT = 1704 ---- @type GameActivity_t -ACT_DOTA_ATTACK_EVENT_BASH = 1705 ---- @type GameActivity_t -ACT_DOTA_CAPTURE_RARE = 1706 ---- @type GameActivity_t -ACT_DOTA_AW_MAGNETIC_FIELD = 1707 ---- @type GameActivity_t -ACT_DOTA_CAST_GHOST_SHIP = 1708 ---- @type GameActivity_t -ACT_DOTA_FXANIM = 1709 ---- @type GameActivity_t -ACT_DOTA_VICTORY_START = 1710 ---- @type GameActivity_t -ACT_DOTA_DEFEAT_START = 1711 ---- @type GameActivity_t -ACT_DOTA_DP_SPIRIT_SIPHON = 1712 ---- @type GameActivity_t -ACT_DOTA_TRICKS_END = 1713 ---- @type GameActivity_t -ACT_DOTA_ES_STONE_CALLER = 1714 ---- @type GameActivity_t -ACT_DOTA_MK_STRIKE = 1715 ---- @type GameActivity_t -ACT_DOTA_VERSUS = 1716 ---- @type GameActivity_t -ACT_DOTA_CAPTURE_CARD = 1717 ---- @type GameActivity_t -ACT_DOTA_MK_SPRING_SOAR = 1718 ---- @type GameActivity_t -ACT_DOTA_MK_SPRING_END = 1719 ---- @type GameActivity_t -ACT_DOTA_MK_TREE_SOAR = 1720 ---- @type GameActivity_t -ACT_DOTA_MK_TREE_END = 1721 ---- @type GameActivity_t -ACT_DOTA_MK_FUR_ARMY = 1722 ---- @type GameActivity_t -ACT_DOTA_MK_SPRING_CAST = 1723 ---- @type GameActivity_t -ACT_DOTA_NECRO_GHOST_SHROUD = 1724 ---- @type GameActivity_t -ACT_DOTA_OVERRIDE_ARCANA = 1725 ---- @type GameActivity_t -ACT_DOTA_SLIDE = 1726 ---- @type GameActivity_t -ACT_DOTA_SLIDE_LOOP = 1727 ---- @type GameActivity_t -ACT_DOTA_GENERIC_CHANNEL_1 = 1728 ---- @type GameActivity_t -ACT_DOTA_GS_SOUL_CHAIN = 1729 ---- @type GameActivity_t -ACT_DOTA_GS_INK_CREATURE = 1730 ---- @type GameActivity_t -ACT_DOTA_TRANSITION = 1731 ---- @type GameActivity_t -ACT_DOTA_BLINK_DAGGER = 1732 ---- @type GameActivity_t -ACT_DOTA_BLINK_DAGGER_END = 1733 ---- @type GameActivity_t -ACT_DOTA_CUSTOM_TOWER_ATTACK = 1734 ---- @type GameActivity_t -ACT_DOTA_CUSTOM_TOWER_IDLE = 1735 ---- @type GameActivity_t -ACT_DOTA_CUSTOM_TOWER_DIE = 1736 ---- @type GameActivity_t -ACT_DOTA_CAST_COLD_SNAP_ORB = 1737 ---- @type GameActivity_t -ACT_DOTA_CAST_GHOST_WALK_ORB = 1738 ---- @type GameActivity_t -ACT_DOTA_CAST_TORNADO_ORB = 1739 ---- @type GameActivity_t -ACT_DOTA_CAST_EMP_ORB = 1740 ---- @type GameActivity_t -ACT_DOTA_CAST_ALACRITY_ORB = 1741 ---- @type GameActivity_t -ACT_DOTA_CAST_CHAOS_METEOR_ORB = 1742 ---- @type GameActivity_t -ACT_DOTA_CAST_SUN_STRIKE_ORB = 1743 ---- @type GameActivity_t -ACT_DOTA_CAST_FORGE_SPIRIT_ORB = 1744 ---- @type GameActivity_t -ACT_DOTA_CAST_ICE_WALL_ORB = 1745 ---- @type GameActivity_t -ACT_DOTA_CAST_DEAFENING_BLAST_ORB = 1746 ---- @type GameActivity_t -ACT_DOTA_NOTICE = 1747 ---- @type GameActivity_t -ACT_DOTA_CAST_ABILITY_2_ALLY = 1748 ---- @type GameActivity_t -ACT_DOTA_SHUFFLE_L = 1749 ---- @type GameActivity_t -ACT_DOTA_SHUFFLE_R = 1750 ---- @type GameActivity_t -ACT_DOTA_OVERRIDE_LOADOUT = 1751 ---- @type GameActivity_t -ACT_DOTA_TAUNT_SPECIAL = 1752 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_START = 1753 ---- @type GameActivity_t -ACT_DOTA_GENERIC_CHANNEL_1_START = 1754 ---- @type GameActivity_t -ACT_DOTA_CUSTOM_TOWER_IDLE_RARE = 1755 ---- @type GameActivity_t -ACT_DOTA_CUSTOM_TOWER_TAUNT = 1756 ---- @type GameActivity_t -ACT_DOTA_CUSTOM_TOWER_HIGH_FIVE = 1757 ---- @type GameActivity_t -ACT_DOTA_ATTACK_SPECIAL = 1758 ---- @type GameActivity_t -ACT_DOTA_TRANSITION_IDLE = 1759 ---- @type GameActivity_t -ACT_DOTA_PIERCE_THE_VEIL = 1760 ---- @type GameActivity_t -ACT_DOTA_RUN_RARE = 1761 ---- @type GameActivity_t -ACT_DOTA_VIPER_DIVE = 1762 ---- @type GameActivity_t -ACT_DOTA_VIPER_DIVE_END = 1763 ---- @type GameActivity_t -ACT_DOTA_MK_STRIKE_END = 1764 ---- @type GameActivity_t -ACT_DOTA_ARCANA_VOTE = 1765 ---- @type GameActivity_t -ACT_DOTA_SPIRIT_BREAKER_ULT_RUN = 1766 ---- @type GameActivity_t -ACT_DOTA_PUNCH = 1767 ---- @type GameActivity_t -ACT_DOTA_CAST_STATUE = 1768 ---- @type GameActivity_t -ACT_DOTA_ATTACK_STATUE = 1769 ---- @type GameActivity_t -ACT_DOTA_CAST3_STATUE = 1770 ---- @type GameActivity_t -ACT_DOTA_CAST1_STATUE = 1771 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_STATUE = 1772 ---- @type GameActivity_t -ACT_DOTA_VICTORY_STATUE = 1773 ---- @type GameActivity_t -ACT_DOTA_TAUNT_STATUE = 1774 ---- @type GameActivity_t -ACT_DOTA_STATUE_SEQUENCE = 1775 ---- @type GameActivity_t -ACT_DOTA_RUN_STATUE = 1776 ---- @type GameActivity_t -ACT_DOTA_IDLE_STATUE = 1777 ---- @type GameActivity_t -ACT_DOTA_CAST4_STATUE = 1778 ---- @type GameActivity_t -ACT_DOTA_FLAIL_STATUE = 1779 ---- @type GameActivity_t -ACT_DOTA_STUN_STATUE = 1780 ---- @type GameActivity_t -ACT_DOTA_TELEPORT_END_STATUE = 1781 ---- @type GameActivity_t -ACT_DOTA_CAST2_STATUE = 1782 ---- @type GameActivity_t -ACT_DOTA_SPAWN_STATUE = 1783 ---- @type GameActivity_t -ACT_DOTA_FORCESTAFF_STATUE = 1784 ---- @type GameActivity_t -ACT_DOTA_DISABLED_END = 1785 ---- @type GameActivity_t -ACT_DOTA_CYCLONE = 1787 ---- @type GameActivity_t -ACT_DOTA_IMPALE = 1788 ---- @type GameActivity_t -ACT_DOTA_TORRENT = 1789 ---- @type GameActivity_t -ACT_DOTA_RUN_ALT = 1793 ---- @type GameActivity_t -ACT_DOTA_VOODOO_REST = 1794 ---- @type GameActivity_t -ACT_DOTA_RADIANT_CREEP_HAMMER = 1796 ---- @type GameActivity_t -ACT_DOTA_RELAX_IN = 1797 ---- @type GameActivity_t -ACT_DOTA_RELAX_OUT = 1798 ---- @type GameActivity_t -ACT_DOTA_CAST_FENCE = 1799 +--- @enum GameActivity_t +--- @field ACT_RESET 0 +--- @field ACT_IDLE 1 +--- @field ACT_TRANSITION 2 +--- @field ACT_COVER 3 +--- @field ACT_COVER_MED 4 +--- @field ACT_COVER_LOW 5 +--- @field ACT_WALK 6 +--- @field ACT_WALK_AIM 7 +--- @field ACT_WALK_CROUCH 8 +--- @field ACT_WALK_CROUCH_AIM 9 +--- @field ACT_RUN 10 +--- @field ACT_RUN_AIM 11 +--- @field ACT_RUN_CROUCH 12 +--- @field ACT_RUN_CROUCH_AIM 13 +--- @field ACT_RUN_PROTECTED 14 +--- @field ACT_SCRIPT_CUSTOM_MOVE 15 +--- @field ACT_RANGE_ATTACK1 16 +--- @field ACT_RANGE_ATTACK2 17 +--- @field ACT_RANGE_ATTACK1_LOW 18 +--- @field ACT_RANGE_ATTACK2_LOW 19 +--- @field ACT_DIESIMPLE 20 +--- @field ACT_DIEBACKWARD 21 +--- @field ACT_DIEFORWARD 22 +--- @field ACT_DIEVIOLENT 23 +--- @field ACT_DIERAGDOLL 24 +--- @field ACT_FLY 25 +--- @field ACT_HOVER 26 +--- @field ACT_GLIDE 27 +--- @field ACT_SWIM 28 +--- @field ACT_JUMP 29 +--- @field ACT_HOP 30 +--- @field ACT_LEAP 31 +--- @field ACT_LAND 32 +--- @field ACT_CLIMB_UP 33 +--- @field ACT_CLIMB_DOWN 34 +--- @field ACT_CLIMB_DISMOUNT 35 +--- @field ACT_SHIPLADDER_UP 36 +--- @field ACT_SHIPLADDER_DOWN 37 +--- @field ACT_STRAFE_LEFT 38 +--- @field ACT_STRAFE_RIGHT 39 +--- @field ACT_ROLL_LEFT 40 +--- @field ACT_ROLL_RIGHT 41 +--- @field ACT_TURN_LEFT 42 +--- @field ACT_TURN_RIGHT 43 +--- @field ACT_CROUCH 44 +--- @field ACT_CROUCHIDLE 45 +--- @field ACT_STAND 46 +--- @field ACT_USE 47 +--- @field ACT_ALIEN_BURROW_IDLE 48 +--- @field ACT_ALIEN_BURROW_OUT 49 +--- @field ACT_SIGNAL1 50 +--- @field ACT_SIGNAL2 51 +--- @field ACT_SIGNAL3 52 +--- @field ACT_SIGNAL_ADVANCE 53 +--- @field ACT_SIGNAL_FORWARD 54 +--- @field ACT_SIGNAL_GROUP 55 +--- @field ACT_SIGNAL_HALT 56 +--- @field ACT_SIGNAL_LEFT 57 +--- @field ACT_SIGNAL_RIGHT 58 +--- @field ACT_SIGNAL_TAKECOVER 59 +--- @field ACT_LOOKBACK_RIGHT 60 +--- @field ACT_LOOKBACK_LEFT 61 +--- @field ACT_COWER 62 +--- @field ACT_SMALL_FLINCH 63 +--- @field ACT_BIG_FLINCH 64 +--- @field ACT_MELEE_ATTACK1 65 +--- @field ACT_MELEE_ATTACK2 66 +--- @field ACT_RELOAD 67 +--- @field ACT_RELOAD_START 68 +--- @field ACT_RELOAD_FINISH 69 +--- @field ACT_RELOAD_LOW 70 +--- @field ACT_ARM 71 +--- @field ACT_DISARM 72 +--- @field ACT_DROP_WEAPON 73 +--- @field ACT_DROP_WEAPON_SHOTGUN 74 +--- @field ACT_PICKUP_GROUND 75 +--- @field ACT_PICKUP_RACK 76 +--- @field ACT_IDLE_ANGRY 77 +--- @field ACT_IDLE_RELAXED 78 +--- @field ACT_IDLE_STIMULATED 79 +--- @field ACT_IDLE_AGITATED 80 +--- @field ACT_IDLE_STEALTH 81 +--- @field ACT_IDLE_HURT 82 +--- @field ACT_WALK_RELAXED 83 +--- @field ACT_WALK_STIMULATED 84 +--- @field ACT_WALK_AGITATED 85 +--- @field ACT_WALK_STEALTH 86 +--- @field ACT_RUN_RELAXED 87 +--- @field ACT_RUN_STIMULATED 88 +--- @field ACT_RUN_AGITATED 89 +--- @field ACT_RUN_STEALTH 90 +--- @field ACT_IDLE_AIM_RELAXED 91 +--- @field ACT_IDLE_AIM_STIMULATED 92 +--- @field ACT_IDLE_AIM_AGITATED 93 +--- @field ACT_IDLE_AIM_STEALTH 94 +--- @field ACT_WALK_AIM_RELAXED 95 +--- @field ACT_WALK_AIM_STIMULATED 96 +--- @field ACT_WALK_AIM_AGITATED 97 +--- @field ACT_WALK_AIM_STEALTH 98 +--- @field ACT_RUN_AIM_RELAXED 99 +--- @field ACT_RUN_AIM_STIMULATED 100 +--- @field ACT_RUN_AIM_AGITATED 101 +--- @field ACT_RUN_AIM_STEALTH 102 +--- @field ACT_CROUCHIDLE_STIMULATED 103 +--- @field ACT_CROUCHIDLE_AIM_STIMULATED 104 +--- @field ACT_CROUCHIDLE_AGITATED 105 +--- @field ACT_WALK_HURT 106 +--- @field ACT_RUN_HURT 107 +--- @field ACT_SPECIAL_ATTACK1 108 +--- @field ACT_SPECIAL_ATTACK2 109 +--- @field ACT_COMBAT_IDLE 110 +--- @field ACT_WALK_SCARED 111 +--- @field ACT_RUN_SCARED 112 +--- @field ACT_VICTORY_DANCE 113 +--- @field ACT_DIE_HEADSHOT 114 +--- @field ACT_DIE_CHESTSHOT 115 +--- @field ACT_DIE_GUTSHOT 116 +--- @field ACT_DIE_BACKSHOT 117 +--- @field ACT_FLINCH_HEAD 118 +--- @field ACT_FLINCH_CHEST 119 +--- @field ACT_FLINCH_STOMACH 120 +--- @field ACT_FLINCH_LEFTARM 121 +--- @field ACT_FLINCH_RIGHTARM 122 +--- @field ACT_FLINCH_LEFTLEG 123 +--- @field ACT_FLINCH_RIGHTLEG 124 +--- @field ACT_FLINCH_PHYSICS 125 +--- @field ACT_FLINCH_HEAD_BACK 126 +--- @field ACT_FLINCH_CHEST_BACK 127 +--- @field ACT_FLINCH_STOMACH_BACK 128 +--- @field ACT_FLINCH_CROUCH_FRONT 129 +--- @field ACT_FLINCH_CROUCH_BACK 130 +--- @field ACT_FLINCH_CROUCH_LEFT 131 +--- @field ACT_FLINCH_CROUCH_RIGHT 132 +--- @field ACT_IDLE_ON_FIRE 133 +--- @field ACT_WALK_ON_FIRE 134 +--- @field ACT_RUN_ON_FIRE 135 +--- @field ACT_180_LEFT 137 +--- @field ACT_180_RIGHT 138 +--- @field ACT_90_LEFT 139 +--- @field ACT_90_RIGHT 140 +--- @field ACT_STEP_LEFT 141 +--- @field ACT_STEP_RIGHT 142 +--- @field ACT_STEP_BACK 143 +--- @field ACT_STEP_FORE 144 +--- @field ACT_GESTURE_RANGE_ATTACK1 145 +--- @field ACT_GESTURE_RANGE_ATTACK2 146 +--- @field ACT_GESTURE_MELEE_ATTACK1 147 +--- @field ACT_GESTURE_MELEE_ATTACK2 148 +--- @field ACT_GESTURE_RANGE_ATTACK1_LOW 149 +--- @field ACT_GESTURE_RANGE_ATTACK2_LOW 150 +--- @field ACT_MELEE_ATTACK_SWING_GESTURE 151 +--- @field ACT_GESTURE_SMALL_FLINCH 152 +--- @field ACT_GESTURE_BIG_FLINCH 153 +--- @field ACT_GESTURE_FLINCH_BLAST 154 +--- @field ACT_GESTURE_FLINCH_BLAST_SHOTGUN 155 +--- @field ACT_GESTURE_FLINCH_BLAST_DAMAGED 156 +--- @field ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN 157 +--- @field ACT_GESTURE_FLINCH_HEAD 158 +--- @field ACT_GESTURE_FLINCH_CHEST 159 +--- @field ACT_GESTURE_FLINCH_STOMACH 160 +--- @field ACT_GESTURE_FLINCH_LEFTARM 161 +--- @field ACT_GESTURE_FLINCH_RIGHTARM 162 +--- @field ACT_GESTURE_FLINCH_LEFTLEG 163 +--- @field ACT_GESTURE_FLINCH_RIGHTLEG 164 +--- @field ACT_GESTURE_TURN_LEFT 165 +--- @field ACT_GESTURE_TURN_RIGHT 166 +--- @field ACT_GESTURE_TURN_LEFT45 167 +--- @field ACT_GESTURE_TURN_RIGHT45 168 +--- @field ACT_GESTURE_TURN_LEFT90 169 +--- @field ACT_GESTURE_TURN_RIGHT90 170 +--- @field ACT_GESTURE_TURN_LEFT45_FLAT 171 +--- @field ACT_GESTURE_TURN_RIGHT45_FLAT 172 +--- @field ACT_GESTURE_TURN_LEFT90_FLAT 173 +--- @field ACT_GESTURE_TURN_RIGHT90_FLAT 174 +--- @field ACT_BARNACLE_HIT 175 +--- @field ACT_BARNACLE_PULL 176 +--- @field ACT_BARNACLE_CHOMP 177 +--- @field ACT_BARNACLE_CHEW 178 +--- @field ACT_DO_NOT_DISTURB 179 +--- @field ACT_SPECIFIC_SEQUENCE 180 +--- @field ACT_VM_DEPLOY 181 +--- @field ACT_VM_RELOAD_EMPTY 182 +--- @field ACT_VM_DRAW 183 +--- @field ACT_VM_HOLSTER 184 +--- @field ACT_VM_IDLE 185 +--- @field ACT_VM_FIDGET 186 +--- @field ACT_VM_PULLBACK 187 +--- @field ACT_VM_PULLBACK_HIGH 188 +--- @field ACT_VM_PULLBACK_LOW 189 +--- @field ACT_VM_THROW 190 +--- @field ACT_VM_DROP 191 +--- @field ACT_VM_PULLPIN 192 +--- @field ACT_VM_PRIMARYATTACK 193 +--- @field ACT_VM_SECONDARYATTACK 194 +--- @field ACT_VM_RELOAD 195 +--- @field ACT_VM_DRYFIRE 196 +--- @field ACT_VM_HITLEFT 197 +--- @field ACT_VM_HITLEFT2 198 +--- @field ACT_VM_HITRIGHT 199 +--- @field ACT_VM_HITRIGHT2 200 +--- @field ACT_VM_HITCENTER 201 +--- @field ACT_VM_HITCENTER2 202 +--- @field ACT_VM_MISSLEFT 203 +--- @field ACT_VM_MISSLEFT2 204 +--- @field ACT_VM_MISSRIGHT 205 +--- @field ACT_VM_MISSRIGHT2 206 +--- @field ACT_VM_MISSCENTER 207 +--- @field ACT_VM_MISSCENTER2 208 +--- @field ACT_VM_HAULBACK 209 +--- @field ACT_VM_SWINGHARD 210 +--- @field ACT_VM_SWINGMISS 211 +--- @field ACT_VM_SWINGHIT 212 +--- @field ACT_VM_IDLE_TO_LOWERED 213 +--- @field ACT_VM_IDLE_LOWERED 214 +--- @field ACT_VM_LOWERED_TO_IDLE 215 +--- @field ACT_VM_RECOIL1 216 +--- @field ACT_VM_RECOIL2 217 +--- @field ACT_VM_RECOIL3 218 +--- @field ACT_VM_PICKUP 219 +--- @field ACT_VM_RELEASE 220 +--- @field ACT_VM_MAUL_LOOP 221 +--- @field ACT_VM_ATTACH_SILENCER 222 +--- @field ACT_VM_DETACH_SILENCER 223 +--- @field ACT_SLAM_STICKWALL_IDLE 224 +--- @field ACT_SLAM_STICKWALL_ND_IDLE 225 +--- @field ACT_SLAM_STICKWALL_ATTACH 226 +--- @field ACT_SLAM_STICKWALL_ATTACH2 227 +--- @field ACT_SLAM_STICKWALL_ND_ATTACH 228 +--- @field ACT_SLAM_STICKWALL_ND_ATTACH2 229 +--- @field ACT_SLAM_STICKWALL_DETONATE 230 +--- @field ACT_SLAM_STICKWALL_DETONATOR_HOLSTER 231 +--- @field ACT_SLAM_STICKWALL_DRAW 232 +--- @field ACT_SLAM_STICKWALL_ND_DRAW 233 +--- @field ACT_SLAM_STICKWALL_TO_THROW 234 +--- @field ACT_SLAM_STICKWALL_TO_THROW_ND 235 +--- @field ACT_SLAM_STICKWALL_TO_TRIPMINE_ND 236 +--- @field ACT_SLAM_THROW_IDLE 237 +--- @field ACT_SLAM_THROW_ND_IDLE 238 +--- @field ACT_SLAM_THROW_THROW 239 +--- @field ACT_SLAM_THROW_THROW2 240 +--- @field ACT_SLAM_THROW_THROW_ND 241 +--- @field ACT_SLAM_THROW_THROW_ND2 242 +--- @field ACT_SLAM_THROW_DRAW 243 +--- @field ACT_SLAM_THROW_ND_DRAW 244 +--- @field ACT_SLAM_THROW_TO_STICKWALL 245 +--- @field ACT_SLAM_THROW_TO_STICKWALL_ND 246 +--- @field ACT_SLAM_THROW_DETONATE 247 +--- @field ACT_SLAM_THROW_DETONATOR_HOLSTER 248 +--- @field ACT_SLAM_THROW_TO_TRIPMINE_ND 249 +--- @field ACT_SLAM_TRIPMINE_IDLE 250 +--- @field ACT_SLAM_TRIPMINE_DRAW 251 +--- @field ACT_SLAM_TRIPMINE_ATTACH 252 +--- @field ACT_SLAM_TRIPMINE_ATTACH2 253 +--- @field ACT_SLAM_TRIPMINE_TO_STICKWALL_ND 254 +--- @field ACT_SLAM_TRIPMINE_TO_THROW_ND 255 +--- @field ACT_SLAM_DETONATOR_IDLE 256 +--- @field ACT_SLAM_DETONATOR_DRAW 257 +--- @field ACT_SLAM_DETONATOR_DETONATE 258 +--- @field ACT_SLAM_DETONATOR_HOLSTER 259 +--- @field ACT_SLAM_DETONATOR_STICKWALL_DRAW 260 +--- @field ACT_SLAM_DETONATOR_THROW_DRAW 261 +--- @field ACT_SHOTGUN_RELOAD_START 262 +--- @field ACT_SHOTGUN_RELOAD_FINISH 263 +--- @field ACT_SHOTGUN_PUMP 264 +--- @field ACT_SMG2_IDLE2 265 +--- @field ACT_SMG2_FIRE2 266 +--- @field ACT_SMG2_DRAW2 267 +--- @field ACT_SMG2_RELOAD2 268 +--- @field ACT_SMG2_DRYFIRE2 269 +--- @field ACT_SMG2_TOAUTO 270 +--- @field ACT_SMG2_TOBURST 271 +--- @field ACT_PHYSCANNON_UPGRADE 272 +--- @field ACT_RANGE_ATTACK_AR1 273 +--- @field ACT_RANGE_ATTACK_AR2 274 +--- @field ACT_RANGE_ATTACK_AR2_LOW 275 +--- @field ACT_RANGE_ATTACK_AR2_GRENADE 276 +--- @field ACT_RANGE_ATTACK_HMG1 277 +--- @field ACT_RANGE_ATTACK_ML 278 +--- @field ACT_RANGE_ATTACK_SMG1 279 +--- @field ACT_RANGE_ATTACK_SMG1_LOW 280 +--- @field ACT_RANGE_ATTACK_SMG2 281 +--- @field ACT_RANGE_ATTACK_SHOTGUN 282 +--- @field ACT_RANGE_ATTACK_SHOTGUN_LOW 283 +--- @field ACT_RANGE_ATTACK_PISTOL 284 +--- @field ACT_RANGE_ATTACK_PISTOL_LOW 285 +--- @field ACT_RANGE_ATTACK_SLAM 286 +--- @field ACT_RANGE_ATTACK_TRIPWIRE 287 +--- @field ACT_RANGE_ATTACK_THROW 288 +--- @field ACT_RANGE_ATTACK_SNIPER_RIFLE 289 +--- @field ACT_RANGE_ATTACK_RPG 290 +--- @field ACT_MELEE_ATTACK_SWING 291 +--- @field ACT_RANGE_AIM_LOW 292 +--- @field ACT_RANGE_AIM_SMG1_LOW 293 +--- @field ACT_RANGE_AIM_PISTOL_LOW 294 +--- @field ACT_RANGE_AIM_AR2_LOW 295 +--- @field ACT_COVER_PISTOL_LOW 296 +--- @field ACT_COVER_SMG1_LOW 297 +--- @field ACT_GESTURE_RANGE_ATTACK_AR1 298 +--- @field ACT_GESTURE_RANGE_ATTACK_AR2 299 +--- @field ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE 300 +--- @field ACT_GESTURE_RANGE_ATTACK_HMG1 301 +--- @field ACT_GESTURE_RANGE_ATTACK_ML 302 +--- @field ACT_GESTURE_RANGE_ATTACK_SMG1 303 +--- @field ACT_GESTURE_RANGE_ATTACK_SMG1_LOW 304 +--- @field ACT_GESTURE_RANGE_ATTACK_SMG2 305 +--- @field ACT_GESTURE_RANGE_ATTACK_SHOTGUN 306 +--- @field ACT_GESTURE_RANGE_ATTACK_PISTOL 307 +--- @field ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW 308 +--- @field ACT_GESTURE_RANGE_ATTACK_SLAM 309 +--- @field ACT_GESTURE_RANGE_ATTACK_TRIPWIRE 310 +--- @field ACT_GESTURE_RANGE_ATTACK_THROW 311 +--- @field ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE 312 +--- @field ACT_GESTURE_MELEE_ATTACK_SWING 313 +--- @field ACT_IDLE_RIFLE 314 +--- @field ACT_IDLE_SMG1 315 +--- @field ACT_IDLE_ANGRY_SMG1 316 +--- @field ACT_IDLE_PISTOL 317 +--- @field ACT_IDLE_ANGRY_PISTOL 318 +--- @field ACT_IDLE_ANGRY_SHOTGUN 319 +--- @field ACT_IDLE_STEALTH_PISTOL 320 +--- @field ACT_IDLE_PACKAGE 321 +--- @field ACT_WALK_PACKAGE 322 +--- @field ACT_IDLE_SUITCASE 323 +--- @field ACT_WALK_SUITCASE 324 +--- @field ACT_IDLE_SMG1_RELAXED 325 +--- @field ACT_IDLE_SMG1_STIMULATED 326 +--- @field ACT_WALK_RIFLE_RELAXED 327 +--- @field ACT_RUN_RIFLE_RELAXED 328 +--- @field ACT_WALK_RIFLE_STIMULATED 329 +--- @field ACT_RUN_RIFLE_STIMULATED 330 +--- @field ACT_IDLE_AIM_RIFLE_STIMULATED 331 +--- @field ACT_WALK_AIM_RIFLE_STIMULATED 332 +--- @field ACT_RUN_AIM_RIFLE_STIMULATED 333 +--- @field ACT_IDLE_SHOTGUN_RELAXED 334 +--- @field ACT_IDLE_SHOTGUN_STIMULATED 335 +--- @field ACT_IDLE_SHOTGUN_AGITATED 336 +--- @field ACT_WALK_ANGRY 337 +--- @field ACT_POLICE_HARASS1 338 +--- @field ACT_POLICE_HARASS2 339 +--- @field ACT_IDLE_MANNEDGUN 340 +--- @field ACT_IDLE_MELEE 341 +--- @field ACT_IDLE_ANGRY_MELEE 342 +--- @field ACT_IDLE_RPG_RELAXED 343 +--- @field ACT_IDLE_RPG 344 +--- @field ACT_IDLE_ANGRY_RPG 345 +--- @field ACT_COVER_LOW_RPG 346 +--- @field ACT_WALK_RPG 347 +--- @field ACT_RUN_RPG 348 +--- @field ACT_WALK_CROUCH_RPG 349 +--- @field ACT_RUN_CROUCH_RPG 350 +--- @field ACT_WALK_RPG_RELAXED 351 +--- @field ACT_RUN_RPG_RELAXED 352 +--- @field ACT_WALK_RIFLE 353 +--- @field ACT_WALK_AIM_RIFLE 354 +--- @field ACT_WALK_CROUCH_RIFLE 355 +--- @field ACT_WALK_CROUCH_AIM_RIFLE 356 +--- @field ACT_RUN_RIFLE 357 +--- @field ACT_RUN_AIM_RIFLE 358 +--- @field ACT_RUN_CROUCH_RIFLE 359 +--- @field ACT_RUN_CROUCH_AIM_RIFLE 360 +--- @field ACT_RUN_STEALTH_PISTOL 361 +--- @field ACT_WALK_AIM_SHOTGUN 362 +--- @field ACT_RUN_AIM_SHOTGUN 363 +--- @field ACT_WALK_PISTOL 364 +--- @field ACT_RUN_PISTOL 365 +--- @field ACT_WALK_AIM_PISTOL 366 +--- @field ACT_RUN_AIM_PISTOL 367 +--- @field ACT_WALK_STEALTH_PISTOL 368 +--- @field ACT_WALK_AIM_STEALTH_PISTOL 369 +--- @field ACT_RUN_AIM_STEALTH_PISTOL 370 +--- @field ACT_RELOAD_PISTOL 371 +--- @field ACT_RELOAD_PISTOL_LOW 372 +--- @field ACT_RELOAD_SMG1 373 +--- @field ACT_RELOAD_SMG1_LOW 374 +--- @field ACT_RELOAD_SHOTGUN 375 +--- @field ACT_RELOAD_SHOTGUN_LOW 376 +--- @field ACT_GESTURE_RELOAD 377 +--- @field ACT_GESTURE_RELOAD_PISTOL 378 +--- @field ACT_GESTURE_RELOAD_SMG1 379 +--- @field ACT_GESTURE_RELOAD_SHOTGUN 380 +--- @field ACT_BUSY_LEAN_LEFT 381 +--- @field ACT_BUSY_LEAN_LEFT_ENTRY 382 +--- @field ACT_BUSY_LEAN_LEFT_EXIT 383 +--- @field ACT_BUSY_LEAN_BACK 384 +--- @field ACT_BUSY_LEAN_BACK_ENTRY 385 +--- @field ACT_BUSY_LEAN_BACK_EXIT 386 +--- @field ACT_BUSY_SIT_GROUND 387 +--- @field ACT_BUSY_SIT_GROUND_ENTRY 388 +--- @field ACT_BUSY_SIT_GROUND_EXIT 389 +--- @field ACT_BUSY_SIT_CHAIR 390 +--- @field ACT_BUSY_SIT_CHAIR_ENTRY 391 +--- @field ACT_BUSY_SIT_CHAIR_EXIT 392 +--- @field ACT_BUSY_STAND 393 +--- @field ACT_BUSY_QUEUE 394 +--- @field ACT_DUCK_DODGE 395 +--- @field ACT_DIE_BARNACLE_SWALLOW 396 +--- @field ACT_GESTURE_BARNACLE_STRANGLE 397 +--- @field ACT_DIE_FRONTSIDE 402 +--- @field ACT_DIE_RIGHTSIDE 403 +--- @field ACT_DIE_BACKSIDE 404 +--- @field ACT_DIE_LEFTSIDE 405 +--- @field ACT_DIE_CROUCH_FRONTSIDE 406 +--- @field ACT_DIE_CROUCH_RIGHTSIDE 407 +--- @field ACT_DIE_CROUCH_BACKSIDE 408 +--- @field ACT_DIE_CROUCH_LEFTSIDE 409 +--- @field ACT_DIE_INCAP 410 +--- @field ACT_DIE_STANDING 411 +--- @field ACT_OPEN_DOOR 412 +--- @field ACT_DI_ALYX_ZOMBIE_MELEE 413 +--- @field ACT_DI_ALYX_ZOMBIE_TORSO_MELEE 414 +--- @field ACT_DI_ALYX_HEADCRAB_MELEE 415 +--- @field ACT_DI_ALYX_ANTLION 416 +--- @field ACT_DI_ALYX_ZOMBIE_SHOTGUN64 417 +--- @field ACT_DI_ALYX_ZOMBIE_SHOTGUN26 418 +--- @field ACT_READINESS_RELAXED_TO_STIMULATED 419 +--- @field ACT_READINESS_RELAXED_TO_STIMULATED_WALK 420 +--- @field ACT_READINESS_AGITATED_TO_STIMULATED 421 +--- @field ACT_READINESS_STIMULATED_TO_RELAXED 422 +--- @field ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED 423 +--- @field ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK 424 +--- @field ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED 425 +--- @field ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED 426 +--- @field ACT_IDLE_CARRY 427 +--- @field ACT_WALK_CARRY 428 +--- @field ACT_STARTDYING 429 +--- @field ACT_DYINGLOOP 430 +--- @field ACT_DYINGTODEAD 431 +--- @field ACT_RIDE_MANNED_GUN 432 +--- @field ACT_VM_SPRINT_ENTER 433 +--- @field ACT_VM_SPRINT_IDLE 434 +--- @field ACT_VM_SPRINT_LEAVE 435 +--- @field ACT_FIRE_START 436 +--- @field ACT_FIRE_LOOP 437 +--- @field ACT_FIRE_END 438 +--- @field ACT_CROUCHING_GRENADEIDLE 439 +--- @field ACT_CROUCHING_GRENADEREADY 440 +--- @field ACT_CROUCHING_PRIMARYATTACK 441 +--- @field ACT_OVERLAY_GRENADEIDLE 442 +--- @field ACT_OVERLAY_GRENADEREADY 443 +--- @field ACT_OVERLAY_PRIMARYATTACK 444 +--- @field ACT_OVERLAY_SHIELD_UP 445 +--- @field ACT_OVERLAY_SHIELD_DOWN 446 +--- @field ACT_OVERLAY_SHIELD_UP_IDLE 447 +--- @field ACT_OVERLAY_SHIELD_ATTACK 448 +--- @field ACT_OVERLAY_SHIELD_KNOCKBACK 449 +--- @field ACT_SHIELD_UP 450 +--- @field ACT_SHIELD_DOWN 451 +--- @field ACT_SHIELD_UP_IDLE 452 +--- @field ACT_SHIELD_ATTACK 453 +--- @field ACT_SHIELD_KNOCKBACK 454 +--- @field ACT_CROUCHING_SHIELD_UP 455 +--- @field ACT_CROUCHING_SHIELD_DOWN 456 +--- @field ACT_CROUCHING_SHIELD_UP_IDLE 457 +--- @field ACT_CROUCHING_SHIELD_ATTACK 458 +--- @field ACT_CROUCHING_SHIELD_KNOCKBACK 459 +--- @field ACT_TURNRIGHT45 460 +--- @field ACT_TURNLEFT45 461 +--- @field ACT_TURN 462 +--- @field ACT_OBJ_ASSEMBLING 463 +--- @field ACT_OBJ_DISMANTLING 464 +--- @field ACT_OBJ_STARTUP 465 +--- @field ACT_OBJ_RUNNING 466 +--- @field ACT_OBJ_IDLE 467 +--- @field ACT_OBJ_PLACING 468 +--- @field ACT_OBJ_DETERIORATING 469 +--- @field ACT_OBJ_UPGRADING 470 +--- @field ACT_DEPLOY 471 +--- @field ACT_DEPLOY_IDLE 472 +--- @field ACT_UNDEPLOY 473 +--- @field ACT_CROSSBOW_DRAW_UNLOADED 474 +--- @field ACT_GAUSS_SPINUP 475 +--- @field ACT_GAUSS_SPINCYCLE 476 +--- @field ACT_VM_PRIMARYATTACK_SILENCED 477 +--- @field ACT_VM_RELOAD_SILENCED 478 +--- @field ACT_VM_DRYFIRE_SILENCED 479 +--- @field ACT_VM_IDLE_SILENCED 480 +--- @field ACT_VM_DRAW_SILENCED 481 +--- @field ACT_VM_IDLE_EMPTY_LEFT 482 +--- @field ACT_VM_DRYFIRE_LEFT 483 +--- @field ACT_VM_IS_DRAW 484 +--- @field ACT_VM_IS_HOLSTER 485 +--- @field ACT_VM_IS_IDLE 486 +--- @field ACT_VM_IS_PRIMARYATTACK 487 +--- @field ACT_PLAYER_IDLE_FIRE 488 +--- @field ACT_PLAYER_CROUCH_FIRE 489 +--- @field ACT_PLAYER_CROUCH_WALK_FIRE 490 +--- @field ACT_PLAYER_WALK_FIRE 491 +--- @field ACT_PLAYER_RUN_FIRE 492 +--- @field ACT_IDLETORUN 493 +--- @field ACT_RUNTOIDLE 494 +--- @field ACT_VM_DRAW_DEPLOYED 495 +--- @field ACT_HL2MP_IDLE_MELEE 496 +--- @field ACT_HL2MP_RUN_MELEE 497 +--- @field ACT_HL2MP_IDLE_CROUCH_MELEE 498 +--- @field ACT_HL2MP_WALK_CROUCH_MELEE 499 +--- @field ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE 500 +--- @field ACT_HL2MP_GESTURE_RELOAD_MELEE 501 +--- @field ACT_HL2MP_JUMP_MELEE 502 +--- @field ACT_MP_STAND_IDLE 503 +--- @field ACT_MP_CROUCH_IDLE 504 +--- @field ACT_MP_CROUCH_DEPLOYED_IDLE 505 +--- @field ACT_MP_CROUCH_DEPLOYED 506 +--- @field ACT_MP_DEPLOYED_IDLE 507 +--- @field ACT_MP_RUN 508 +--- @field ACT_MP_WALK 509 +--- @field ACT_MP_AIRWALK 510 +--- @field ACT_MP_CROUCHWALK 511 +--- @field ACT_MP_SPRINT 512 +--- @field ACT_MP_JUMP 513 +--- @field ACT_MP_JUMP_START 514 +--- @field ACT_MP_JUMP_FLOAT 515 +--- @field ACT_MP_JUMP_LAND 516 +--- @field ACT_MP_DOUBLEJUMP 517 +--- @field ACT_MP_SWIM 518 +--- @field ACT_MP_DEPLOYED 519 +--- @field ACT_MP_SWIM_DEPLOYED 520 +--- @field ACT_MP_VCD 521 +--- @field ACT_MP_ATTACK_STAND_PRIMARYFIRE 522 +--- @field ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED 523 +--- @field ACT_MP_ATTACK_STAND_SECONDARYFIRE 524 +--- @field ACT_MP_ATTACK_STAND_GRENADE 525 +--- @field ACT_MP_ATTACK_CROUCH_PRIMARYFIRE 526 +--- @field ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED 527 +--- @field ACT_MP_ATTACK_CROUCH_SECONDARYFIRE 528 +--- @field ACT_MP_ATTACK_CROUCH_GRENADE 529 +--- @field ACT_MP_ATTACK_SWIM_PRIMARYFIRE 530 +--- @field ACT_MP_ATTACK_SWIM_SECONDARYFIRE 531 +--- @field ACT_MP_ATTACK_SWIM_GRENADE 532 +--- @field ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE 533 +--- @field ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE 534 +--- @field ACT_MP_ATTACK_AIRWALK_GRENADE 535 +--- @field ACT_MP_RELOAD_STAND 536 +--- @field ACT_MP_RELOAD_STAND_LOOP 537 +--- @field ACT_MP_RELOAD_STAND_END 538 +--- @field ACT_MP_RELOAD_CROUCH 539 +--- @field ACT_MP_RELOAD_CROUCH_LOOP 540 +--- @field ACT_MP_RELOAD_CROUCH_END 541 +--- @field ACT_MP_RELOAD_SWIM 542 +--- @field ACT_MP_RELOAD_SWIM_LOOP 543 +--- @field ACT_MP_RELOAD_SWIM_END 544 +--- @field ACT_MP_RELOAD_AIRWALK 545 +--- @field ACT_MP_RELOAD_AIRWALK_LOOP 546 +--- @field ACT_MP_RELOAD_AIRWALK_END 547 +--- @field ACT_MP_ATTACK_STAND_PREFIRE 548 +--- @field ACT_MP_ATTACK_STAND_POSTFIRE 549 +--- @field ACT_MP_ATTACK_STAND_STARTFIRE 550 +--- @field ACT_MP_ATTACK_CROUCH_PREFIRE 551 +--- @field ACT_MP_ATTACK_CROUCH_POSTFIRE 552 +--- @field ACT_MP_ATTACK_SWIM_PREFIRE 553 +--- @field ACT_MP_ATTACK_SWIM_POSTFIRE 554 +--- @field ACT_MP_STAND_PRIMARY 555 +--- @field ACT_MP_CROUCH_PRIMARY 556 +--- @field ACT_MP_RUN_PRIMARY 557 +--- @field ACT_MP_WALK_PRIMARY 558 +--- @field ACT_MP_AIRWALK_PRIMARY 559 +--- @field ACT_MP_CROUCHWALK_PRIMARY 560 +--- @field ACT_MP_JUMP_PRIMARY 561 +--- @field ACT_MP_JUMP_START_PRIMARY 562 +--- @field ACT_MP_JUMP_FLOAT_PRIMARY 563 +--- @field ACT_MP_JUMP_LAND_PRIMARY 564 +--- @field ACT_MP_SWIM_PRIMARY 565 +--- @field ACT_MP_DEPLOYED_PRIMARY 566 +--- @field ACT_MP_SWIM_DEPLOYED_PRIMARY 567 +--- @field ACT_MP_ATTACK_STAND_PRIMARY 568 +--- @field ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED 569 +--- @field ACT_MP_ATTACK_CROUCH_PRIMARY 570 +--- @field ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED 571 +--- @field ACT_MP_ATTACK_SWIM_PRIMARY 572 +--- @field ACT_MP_ATTACK_AIRWALK_PRIMARY 573 +--- @field ACT_MP_RELOAD_STAND_PRIMARY 574 +--- @field ACT_MP_RELOAD_STAND_PRIMARY_LOOP 575 +--- @field ACT_MP_RELOAD_STAND_PRIMARY_END 576 +--- @field ACT_MP_RELOAD_CROUCH_PRIMARY 577 +--- @field ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP 578 +--- @field ACT_MP_RELOAD_CROUCH_PRIMARY_END 579 +--- @field ACT_MP_RELOAD_SWIM_PRIMARY 580 +--- @field ACT_MP_RELOAD_SWIM_PRIMARY_LOOP 581 +--- @field ACT_MP_RELOAD_SWIM_PRIMARY_END 582 +--- @field ACT_MP_RELOAD_AIRWALK_PRIMARY 583 +--- @field ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP 584 +--- @field ACT_MP_RELOAD_AIRWALK_PRIMARY_END 585 +--- @field ACT_MP_ATTACK_STAND_GRENADE_PRIMARY 586 +--- @field ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY 587 +--- @field ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY 588 +--- @field ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY 589 +--- @field ACT_MP_STAND_SECONDARY 590 +--- @field ACT_MP_CROUCH_SECONDARY 591 +--- @field ACT_MP_RUN_SECONDARY 592 +--- @field ACT_MP_WALK_SECONDARY 593 +--- @field ACT_MP_AIRWALK_SECONDARY 594 +--- @field ACT_MP_CROUCHWALK_SECONDARY 595 +--- @field ACT_MP_JUMP_SECONDARY 596 +--- @field ACT_MP_JUMP_START_SECONDARY 597 +--- @field ACT_MP_JUMP_FLOAT_SECONDARY 598 +--- @field ACT_MP_JUMP_LAND_SECONDARY 599 +--- @field ACT_MP_SWIM_SECONDARY 600 +--- @field ACT_MP_ATTACK_STAND_SECONDARY 601 +--- @field ACT_MP_ATTACK_CROUCH_SECONDARY 602 +--- @field ACT_MP_ATTACK_SWIM_SECONDARY 603 +--- @field ACT_MP_ATTACK_AIRWALK_SECONDARY 604 +--- @field ACT_MP_RELOAD_STAND_SECONDARY 605 +--- @field ACT_MP_RELOAD_STAND_SECONDARY_LOOP 606 +--- @field ACT_MP_RELOAD_STAND_SECONDARY_END 607 +--- @field ACT_MP_RELOAD_CROUCH_SECONDARY 608 +--- @field ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP 609 +--- @field ACT_MP_RELOAD_CROUCH_SECONDARY_END 610 +--- @field ACT_MP_RELOAD_SWIM_SECONDARY 611 +--- @field ACT_MP_RELOAD_SWIM_SECONDARY_LOOP 612 +--- @field ACT_MP_RELOAD_SWIM_SECONDARY_END 613 +--- @field ACT_MP_RELOAD_AIRWALK_SECONDARY 614 +--- @field ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP 615 +--- @field ACT_MP_RELOAD_AIRWALK_SECONDARY_END 616 +--- @field ACT_MP_ATTACK_STAND_GRENADE_SECONDARY 617 +--- @field ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY 618 +--- @field ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY 619 +--- @field ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY 620 +--- @field ACT_MP_STAND_MELEE 621 +--- @field ACT_MP_CROUCH_MELEE 622 +--- @field ACT_MP_RUN_MELEE 623 +--- @field ACT_MP_WALK_MELEE 624 +--- @field ACT_MP_AIRWALK_MELEE 625 +--- @field ACT_MP_CROUCHWALK_MELEE 626 +--- @field ACT_MP_JUMP_MELEE 627 +--- @field ACT_MP_JUMP_START_MELEE 628 +--- @field ACT_MP_JUMP_FLOAT_MELEE 629 +--- @field ACT_MP_JUMP_LAND_MELEE 630 +--- @field ACT_MP_SWIM_MELEE 631 +--- @field ACT_MP_ATTACK_STAND_MELEE 632 +--- @field ACT_MP_ATTACK_STAND_MELEE_SECONDARY 633 +--- @field ACT_MP_ATTACK_CROUCH_MELEE 634 +--- @field ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY 635 +--- @field ACT_MP_ATTACK_SWIM_MELEE 636 +--- @field ACT_MP_ATTACK_AIRWALK_MELEE 637 +--- @field ACT_MP_ATTACK_STAND_GRENADE_MELEE 638 +--- @field ACT_MP_ATTACK_CROUCH_GRENADE_MELEE 639 +--- @field ACT_MP_ATTACK_SWIM_GRENADE_MELEE 640 +--- @field ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE 641 +--- @field ACT_MP_STAND_ITEM1 642 +--- @field ACT_MP_CROUCH_ITEM1 643 +--- @field ACT_MP_RUN_ITEM1 644 +--- @field ACT_MP_WALK_ITEM1 645 +--- @field ACT_MP_AIRWALK_ITEM1 646 +--- @field ACT_MP_CROUCHWALK_ITEM1 647 +--- @field ACT_MP_JUMP_ITEM1 648 +--- @field ACT_MP_JUMP_START_ITEM1 649 +--- @field ACT_MP_JUMP_FLOAT_ITEM1 650 +--- @field ACT_MP_JUMP_LAND_ITEM1 651 +--- @field ACT_MP_SWIM_ITEM1 652 +--- @field ACT_MP_ATTACK_STAND_ITEM1 653 +--- @field ACT_MP_ATTACK_STAND_ITEM1_SECONDARY 654 +--- @field ACT_MP_ATTACK_CROUCH_ITEM1 655 +--- @field ACT_MP_ATTACK_CROUCH_ITEM1_SECONDARY 656 +--- @field ACT_MP_ATTACK_SWIM_ITEM1 657 +--- @field ACT_MP_ATTACK_AIRWALK_ITEM1 658 +--- @field ACT_MP_STAND_ITEM2 659 +--- @field ACT_MP_CROUCH_ITEM2 660 +--- @field ACT_MP_RUN_ITEM2 661 +--- @field ACT_MP_WALK_ITEM2 662 +--- @field ACT_MP_AIRWALK_ITEM2 663 +--- @field ACT_MP_CROUCHWALK_ITEM2 664 +--- @field ACT_MP_JUMP_ITEM2 665 +--- @field ACT_MP_JUMP_START_ITEM2 666 +--- @field ACT_MP_JUMP_FLOAT_ITEM2 667 +--- @field ACT_MP_JUMP_LAND_ITEM2 668 +--- @field ACT_MP_SWIM_ITEM2 669 +--- @field ACT_MP_ATTACK_STAND_ITEM2 670 +--- @field ACT_MP_ATTACK_STAND_ITEM2_SECONDARY 671 +--- @field ACT_MP_ATTACK_CROUCH_ITEM2 672 +--- @field ACT_MP_ATTACK_CROUCH_ITEM2_SECONDARY 673 +--- @field ACT_MP_ATTACK_SWIM_ITEM2 674 +--- @field ACT_MP_ATTACK_AIRWALK_ITEM2 675 +--- @field ACT_MP_GESTURE_FLINCH 676 +--- @field ACT_MP_GESTURE_FLINCH_PRIMARY 677 +--- @field ACT_MP_GESTURE_FLINCH_SECONDARY 678 +--- @field ACT_MP_GESTURE_FLINCH_MELEE 679 +--- @field ACT_MP_GESTURE_FLINCH_ITEM1 680 +--- @field ACT_MP_GESTURE_FLINCH_ITEM2 681 +--- @field ACT_MP_GESTURE_FLINCH_HEAD 682 +--- @field ACT_MP_GESTURE_FLINCH_CHEST 683 +--- @field ACT_MP_GESTURE_FLINCH_STOMACH 684 +--- @field ACT_MP_GESTURE_FLINCH_LEFTARM 685 +--- @field ACT_MP_GESTURE_FLINCH_RIGHTARM 686 +--- @field ACT_MP_GESTURE_FLINCH_LEFTLEG 687 +--- @field ACT_MP_GESTURE_FLINCH_RIGHTLEG 688 +--- @field ACT_MP_GRENADE1_DRAW 689 +--- @field ACT_MP_GRENADE1_IDLE 690 +--- @field ACT_MP_GRENADE1_ATTACK 691 +--- @field ACT_MP_GRENADE2_DRAW 692 +--- @field ACT_MP_GRENADE2_IDLE 693 +--- @field ACT_MP_GRENADE2_ATTACK 694 +--- @field ACT_MP_PRIMARY_GRENADE1_DRAW 695 +--- @field ACT_MP_PRIMARY_GRENADE1_IDLE 696 +--- @field ACT_MP_PRIMARY_GRENADE1_ATTACK 697 +--- @field ACT_MP_PRIMARY_GRENADE2_DRAW 698 +--- @field ACT_MP_PRIMARY_GRENADE2_IDLE 699 +--- @field ACT_MP_PRIMARY_GRENADE2_ATTACK 700 +--- @field ACT_MP_SECONDARY_GRENADE1_DRAW 701 +--- @field ACT_MP_SECONDARY_GRENADE1_IDLE 702 +--- @field ACT_MP_SECONDARY_GRENADE1_ATTACK 703 +--- @field ACT_MP_SECONDARY_GRENADE2_DRAW 704 +--- @field ACT_MP_SECONDARY_GRENADE2_IDLE 705 +--- @field ACT_MP_SECONDARY_GRENADE2_ATTACK 706 +--- @field ACT_MP_MELEE_GRENADE1_DRAW 707 +--- @field ACT_MP_MELEE_GRENADE1_IDLE 708 +--- @field ACT_MP_MELEE_GRENADE1_ATTACK 709 +--- @field ACT_MP_MELEE_GRENADE2_DRAW 710 +--- @field ACT_MP_MELEE_GRENADE2_IDLE 711 +--- @field ACT_MP_MELEE_GRENADE2_ATTACK 712 +--- @field ACT_MP_ITEM1_GRENADE1_DRAW 713 +--- @field ACT_MP_ITEM1_GRENADE1_IDLE 714 +--- @field ACT_MP_ITEM1_GRENADE1_ATTACK 715 +--- @field ACT_MP_ITEM1_GRENADE2_DRAW 716 +--- @field ACT_MP_ITEM1_GRENADE2_IDLE 717 +--- @field ACT_MP_ITEM1_GRENADE2_ATTACK 718 +--- @field ACT_MP_ITEM2_GRENADE1_DRAW 719 +--- @field ACT_MP_ITEM2_GRENADE1_IDLE 720 +--- @field ACT_MP_ITEM2_GRENADE1_ATTACK 721 +--- @field ACT_MP_ITEM2_GRENADE2_DRAW 722 +--- @field ACT_MP_ITEM2_GRENADE2_IDLE 723 +--- @field ACT_MP_ITEM2_GRENADE2_ATTACK 724 +--- @field ACT_MP_STAND_BUILDING 725 +--- @field ACT_MP_CROUCH_BUILDING 726 +--- @field ACT_MP_RUN_BUILDING 727 +--- @field ACT_MP_WALK_BUILDING 728 +--- @field ACT_MP_AIRWALK_BUILDING 729 +--- @field ACT_MP_CROUCHWALK_BUILDING 730 +--- @field ACT_MP_JUMP_BUILDING 731 +--- @field ACT_MP_JUMP_START_BUILDING 732 +--- @field ACT_MP_JUMP_FLOAT_BUILDING 733 +--- @field ACT_MP_JUMP_LAND_BUILDING 734 +--- @field ACT_MP_SWIM_BUILDING 735 +--- @field ACT_MP_ATTACK_STAND_BUILDING 736 +--- @field ACT_MP_ATTACK_CROUCH_BUILDING 737 +--- @field ACT_MP_ATTACK_SWIM_BUILDING 738 +--- @field ACT_MP_ATTACK_AIRWALK_BUILDING 739 +--- @field ACT_MP_ATTACK_STAND_GRENADE_BUILDING 740 +--- @field ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING 741 +--- @field ACT_MP_ATTACK_SWIM_GRENADE_BUILDING 742 +--- @field ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING 743 +--- @field ACT_MP_STAND_PDA 744 +--- @field ACT_MP_CROUCH_PDA 745 +--- @field ACT_MP_RUN_PDA 746 +--- @field ACT_MP_WALK_PDA 747 +--- @field ACT_MP_AIRWALK_PDA 748 +--- @field ACT_MP_CROUCHWALK_PDA 749 +--- @field ACT_MP_JUMP_PDA 750 +--- @field ACT_MP_JUMP_START_PDA 751 +--- @field ACT_MP_JUMP_FLOAT_PDA 752 +--- @field ACT_MP_JUMP_LAND_PDA 753 +--- @field ACT_MP_SWIM_PDA 754 +--- @field ACT_MP_ATTACK_STAND_PDA 755 +--- @field ACT_MP_ATTACK_SWIM_PDA 756 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH 757 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT 758 +--- @field ACT_MP_GESTURE_VC_FISTPUMP 759 +--- @field ACT_MP_GESTURE_VC_THUMBSUP 760 +--- @field ACT_MP_GESTURE_VC_NODYES 761 +--- @field ACT_MP_GESTURE_VC_NODNO 762 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY 763 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY 764 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY 765 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY 766 +--- @field ACT_MP_GESTURE_VC_NODYES_PRIMARY 767 +--- @field ACT_MP_GESTURE_VC_NODNO_PRIMARY 768 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY 769 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY 770 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY 771 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY 772 +--- @field ACT_MP_GESTURE_VC_NODYES_SECONDARY 773 +--- @field ACT_MP_GESTURE_VC_NODNO_SECONDARY 774 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_MELEE 775 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_MELEE 776 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_MELEE 777 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_MELEE 778 +--- @field ACT_MP_GESTURE_VC_NODYES_MELEE 779 +--- @field ACT_MP_GESTURE_VC_NODNO_MELEE 780 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_ITEM1 781 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_ITEM1 782 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_ITEM1 783 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_ITEM1 784 +--- @field ACT_MP_GESTURE_VC_NODYES_ITEM1 785 +--- @field ACT_MP_GESTURE_VC_NODNO_ITEM1 786 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_ITEM2 787 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_ITEM2 788 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_ITEM2 789 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_ITEM2 790 +--- @field ACT_MP_GESTURE_VC_NODYES_ITEM2 791 +--- @field ACT_MP_GESTURE_VC_NODNO_ITEM2 792 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING 793 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING 794 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_BUILDING 795 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_BUILDING 796 +--- @field ACT_MP_GESTURE_VC_NODYES_BUILDING 797 +--- @field ACT_MP_GESTURE_VC_NODNO_BUILDING 798 +--- @field ACT_MP_GESTURE_VC_HANDMOUTH_PDA 799 +--- @field ACT_MP_GESTURE_VC_FINGERPOINT_PDA 800 +--- @field ACT_MP_GESTURE_VC_FISTPUMP_PDA 801 +--- @field ACT_MP_GESTURE_VC_THUMBSUP_PDA 802 +--- @field ACT_MP_GESTURE_VC_NODYES_PDA 803 +--- @field ACT_MP_GESTURE_VC_NODNO_PDA 804 +--- @field ACT_VM_UNUSABLE 805 +--- @field ACT_VM_UNUSABLE_TO_USABLE 806 +--- @field ACT_VM_USABLE_TO_UNUSABLE 807 +--- @field ACT_PRIMARY_VM_DRAW 808 +--- @field ACT_PRIMARY_VM_HOLSTER 809 +--- @field ACT_PRIMARY_VM_IDLE 810 +--- @field ACT_PRIMARY_VM_PULLBACK 811 +--- @field ACT_PRIMARY_VM_PRIMARYATTACK 812 +--- @field ACT_PRIMARY_VM_SECONDARYATTACK 813 +--- @field ACT_PRIMARY_VM_RELOAD 814 +--- @field ACT_PRIMARY_VM_DRYFIRE 815 +--- @field ACT_PRIMARY_VM_IDLE_TO_LOWERED 816 +--- @field ACT_PRIMARY_VM_IDLE_LOWERED 817 +--- @field ACT_PRIMARY_VM_LOWERED_TO_IDLE 818 +--- @field ACT_SECONDARY_VM_DRAW 819 +--- @field ACT_SECONDARY_VM_HOLSTER 820 +--- @field ACT_SECONDARY_VM_IDLE 821 +--- @field ACT_SECONDARY_VM_PULLBACK 822 +--- @field ACT_SECONDARY_VM_PRIMARYATTACK 823 +--- @field ACT_SECONDARY_VM_SECONDARYATTACK 824 +--- @field ACT_SECONDARY_VM_RELOAD 825 +--- @field ACT_SECONDARY_VM_DRYFIRE 826 +--- @field ACT_SECONDARY_VM_IDLE_TO_LOWERED 827 +--- @field ACT_SECONDARY_VM_IDLE_LOWERED 828 +--- @field ACT_SECONDARY_VM_LOWERED_TO_IDLE 829 +--- @field ACT_MELEE_VM_DRAW 830 +--- @field ACT_MELEE_VM_HOLSTER 831 +--- @field ACT_MELEE_VM_IDLE 832 +--- @field ACT_MELEE_VM_PULLBACK 833 +--- @field ACT_MELEE_VM_PRIMARYATTACK 834 +--- @field ACT_MELEE_VM_SECONDARYATTACK 835 +--- @field ACT_MELEE_VM_RELOAD 836 +--- @field ACT_MELEE_VM_DRYFIRE 837 +--- @field ACT_MELEE_VM_IDLE_TO_LOWERED 838 +--- @field ACT_MELEE_VM_IDLE_LOWERED 839 +--- @field ACT_MELEE_VM_LOWERED_TO_IDLE 840 +--- @field ACT_PDA_VM_DRAW 841 +--- @field ACT_PDA_VM_HOLSTER 842 +--- @field ACT_PDA_VM_IDLE 843 +--- @field ACT_PDA_VM_PULLBACK 844 +--- @field ACT_PDA_VM_PRIMARYATTACK 845 +--- @field ACT_PDA_VM_SECONDARYATTACK 846 +--- @field ACT_PDA_VM_RELOAD 847 +--- @field ACT_PDA_VM_DRYFIRE 848 +--- @field ACT_PDA_VM_IDLE_TO_LOWERED 849 +--- @field ACT_PDA_VM_IDLE_LOWERED 850 +--- @field ACT_PDA_VM_LOWERED_TO_IDLE 851 +--- @field ACT_ITEM1_VM_DRAW 852 +--- @field ACT_ITEM1_VM_HOLSTER 853 +--- @field ACT_ITEM1_VM_IDLE 854 +--- @field ACT_ITEM1_VM_PULLBACK 855 +--- @field ACT_ITEM1_VM_PRIMARYATTACK 856 +--- @field ACT_ITEM1_VM_SECONDARYATTACK 857 +--- @field ACT_ITEM1_VM_RELOAD 858 +--- @field ACT_ITEM1_VM_DRYFIRE 859 +--- @field ACT_ITEM1_VM_IDLE_TO_LOWERED 860 +--- @field ACT_ITEM1_VM_IDLE_LOWERED 861 +--- @field ACT_ITEM1_VM_LOWERED_TO_IDLE 862 +--- @field ACT_ITEM2_VM_DRAW 863 +--- @field ACT_ITEM2_VM_HOLSTER 864 +--- @field ACT_ITEM2_VM_IDLE 865 +--- @field ACT_ITEM2_VM_PULLBACK 866 +--- @field ACT_ITEM2_VM_PRIMARYATTACK 867 +--- @field ACT_ITEM2_VM_SECONDARYATTACK 868 +--- @field ACT_ITEM2_VM_RELOAD 869 +--- @field ACT_ITEM2_VM_DRYFIRE 870 +--- @field ACT_ITEM2_VM_IDLE_TO_LOWERED 871 +--- @field ACT_ITEM2_VM_IDLE_LOWERED 872 +--- @field ACT_ITEM2_VM_LOWERED_TO_IDLE 873 +--- @field ACT_RELOAD_SUCCEED 874 +--- @field ACT_RELOAD_FAIL 875 +--- @field ACT_WALK_AIM_AUTOGUN 876 +--- @field ACT_RUN_AIM_AUTOGUN 877 +--- @field ACT_IDLE_AUTOGUN 878 +--- @field ACT_IDLE_AIM_AUTOGUN 879 +--- @field ACT_RELOAD_AUTOGUN 880 +--- @field ACT_CROUCH_IDLE_AUTOGUN 881 +--- @field ACT_RANGE_ATTACK_AUTOGUN 882 +--- @field ACT_JUMP_AUTOGUN 883 +--- @field ACT_IDLE_AIM_PISTOL 884 +--- @field ACT_WALK_AIM_DUAL 885 +--- @field ACT_RUN_AIM_DUAL 886 +--- @field ACT_IDLE_DUAL 887 +--- @field ACT_IDLE_AIM_DUAL 888 +--- @field ACT_RELOAD_DUAL 889 +--- @field ACT_CROUCH_IDLE_DUAL 890 +--- @field ACT_RANGE_ATTACK_DUAL 891 +--- @field ACT_JUMP_DUAL 892 +--- @field ACT_IDLE_AIM_SHOTGUN 893 +--- @field ACT_CROUCH_IDLE_SHOTGUN 894 +--- @field ACT_IDLE_AIM_RIFLE 895 +--- @field ACT_CROUCH_IDLE_RIFLE 896 +--- @field ACT_RANGE_ATTACK_RIFLE 897 +--- @field ACT_SLEEP 898 +--- @field ACT_WAKE 899 +--- @field ACT_FLICK_LEFT 900 +--- @field ACT_FLICK_LEFT_MIDDLE 901 +--- @field ACT_FLICK_RIGHT_MIDDLE 902 +--- @field ACT_FLICK_RIGHT 903 +--- @field ACT_SPINAROUND 904 +--- @field ACT_PREP_TO_FIRE 905 +--- @field ACT_FIRE 906 +--- @field ACT_FIRE_RECOVER 907 +--- @field ACT_SPRAY 908 +--- @field ACT_PREP_EXPLODE 909 +--- @field ACT_EXPLODE 910 +--- @field ACT_SCRIPT_CUSTOM_0 911 +--- @field ACT_SCRIPT_CUSTOM_1 912 +--- @field ACT_SCRIPT_CUSTOM_2 913 +--- @field ACT_SCRIPT_CUSTOM_3 914 +--- @field ACT_SCRIPT_CUSTOM_4 915 +--- @field ACT_SCRIPT_CUSTOM_5 916 +--- @field ACT_SCRIPT_CUSTOM_6 917 +--- @field ACT_SCRIPT_CUSTOM_7 918 +--- @field ACT_SCRIPT_CUSTOM_8 919 +--- @field ACT_SCRIPT_CUSTOM_9 920 +--- @field ACT_SCRIPT_CUSTOM_10 921 +--- @field ACT_SCRIPT_CUSTOM_11 922 +--- @field ACT_SCRIPT_CUSTOM_12 923 +--- @field ACT_SCRIPT_CUSTOM_13 924 +--- @field ACT_SCRIPT_CUSTOM_14 925 +--- @field ACT_SCRIPT_CUSTOM_15 926 +--- @field ACT_SCRIPT_CUSTOM_16 927 +--- @field ACT_SCRIPT_CUSTOM_17 928 +--- @field ACT_SCRIPT_CUSTOM_18 929 +--- @field ACT_SCRIPT_CUSTOM_19 930 +--- @field ACT_SCRIPT_CUSTOM_20 931 +--- @field ACT_SCRIPT_CUSTOM_21 932 +--- @field ACT_SCRIPT_CUSTOM_22 933 +--- @field ACT_SCRIPT_CUSTOM_23 934 +--- @field ACT_SCRIPT_CUSTOM_24 935 +--- @field ACT_SCRIPT_CUSTOM_25 936 +--- @field ACT_SCRIPT_CUSTOM_26 937 +--- @field ACT_SCRIPT_CUSTOM_27 938 +--- @field ACT_SCRIPT_CUSTOM_28 939 +--- @field ACT_SCRIPT_CUSTOM_29 940 +--- @field ACT_SCRIPT_CUSTOM_30 941 +--- @field ACT_SCRIPT_CUSTOM_31 942 +--- @field ACT_VR_PISTOL_LAST_SHOT 943 +--- @field ACT_VR_PISTOL_SLIDE_RELEASE 944 +--- @field ACT_VR_PISTOL_CLIP_OUT_CHAMBERED 945 +--- @field ACT_VR_PISTOL_CLIP_OUT_SLIDE_BACK 946 +--- @field ACT_VR_PISTOL_CLIP_IN_CHAMBERED 947 +--- @field ACT_VR_PISTOL_CLIP_IN_SLIDE_BACK 948 +--- @field ACT_VR_PISTOL_IDLE_SLIDE_BACK 949 +--- @field ACT_VR_PISTOL_IDLE_SLIDE_BACK_CLIP_READY 950 +--- @field ACT_RAGDOLL_RECOVERY_FRONT 951 +--- @field ACT_RAGDOLL_RECOVERY_BACK 952 +--- @field ACT_RAGDOLL_RECOVERY_LEFT 953 +--- @field ACT_RAGDOLL_RECOVERY_RIGHT 954 +--- @field ACT_GRABBITYGLOVES_GRAB 955 +--- @field ACT_GRABBITYGLOVES_RELEASE 956 +--- @field ACT_GRABBITYGLOVES_GRAB_IDLE 957 +--- @field ACT_GRABBITYGLOVES_ACTIVE 958 +--- @field ACT_GRABBITYGLOVES_ACTIVE_IDLE 959 +--- @field ACT_GRABBITYGLOVES_DEACTIVATE 960 +--- @field ACT_GRABBITYGLOVES_PULL 961 +--- @field ACT_HEADCRAB_SMOKE_BOMB 962 +--- @field ACT_HEADCRAB_SPIT 963 +--- @field ACT_ZOMBIE_TRIP 964 +--- @field ACT_ZOMBIE_LUNGE 965 +--- @field ACT_NEUTRAL_REF_POSE 966 +--- @field ACT_ANTLION_SCUTTLE_FORWARD 967 +--- @field ACT_ANTLION_SCUTTLE_BACK 968 +--- @field ACT_ANTLION_SCUTTLE_LEFT 969 +--- @field ACT_ANTLION_SCUTTLE_RIGHT 970 +--- @field ACT_VR_PISTOL_EMPTY_CLIP_IN_SLIDE_BACK 971 +--- @field ACT_VR_SHOTGUN_IDLE 972 +--- @field ACT_VR_SHOTGUN_OPEN_CHAMBER 973 +--- @field ACT_VR_SHOTGUN_RELOAD_1 974 +--- @field ACT_VR_SHOTGUN_RELOAD_2 975 +--- @field ACT_VR_SHOTGUN_RELOAD_3 976 +--- @field ACT_VR_SHOTGUN_CLOSE_CHAMBER 977 +--- @field ACT_VR_SHOTGUN_TRIGGER_SQUEEZE 978 +--- @field ACT_VR_SHOTGUN_SHOOT 979 +--- @field ACT_VR_SHOTGUN_SLIDE_BACK 980 +--- @field ACT_VR_SHOTGUN_SLIDE_FORWARD 981 +--- @field ACT_VR_PISTOL_LONG_CLIP_IN_CHAMBERED 982 +--- @field ACT_VR_PISTOL_LONG_CLIP_IN_SLIDE_BACK 983 +--- @field ACT_VR_PISTOL_BURST_TOGGLE 984 +--- @field ACT_VR_PISTOL_LOW_KICK 985 +--- @field ACT_VR_PISTOL_BURST_ATTACK 986 +--- @field ACT_VR_SHOTGUN_GRENADE_TWIST 987 +--- @field ACT_DIE_STAND 988 +--- @field ACT_DIE_STAND_HEADSHOT 989 +--- @field ACT_DIE_CROUCH 990 +--- @field ACT_DIE_CROUCH_HEADSHOT 991 +--- @field ACT_CSGO_NULL 992 +--- @field ACT_CSGO_DEFUSE 993 +--- @field ACT_CSGO_DEFUSE_WITH_KIT 994 +--- @field ACT_CSGO_FLASHBANG_REACTION 995 +--- @field ACT_CSGO_FIRE_PRIMARY 996 +--- @field ACT_CSGO_FIRE_PRIMARY_OPT_1 997 +--- @field ACT_CSGO_FIRE_PRIMARY_OPT_2 998 +--- @field ACT_CSGO_FIRE_SECONDARY 999 +--- @field ACT_CSGO_FIRE_SECONDARY_OPT_1 1000 +--- @field ACT_CSGO_FIRE_SECONDARY_OPT_2 1001 +--- @field ACT_CSGO_RELOAD 1002 +--- @field ACT_CSGO_RELOAD_START 1003 +--- @field ACT_CSGO_RELOAD_LOOP 1004 +--- @field ACT_CSGO_RELOAD_END 1005 +--- @field ACT_CSGO_OPERATE 1006 +--- @field ACT_CSGO_DEPLOY 1007 +--- @field ACT_CSGO_CATCH 1008 +--- @field ACT_CSGO_SILENCER_DETACH 1009 +--- @field ACT_CSGO_SILENCER_ATTACH 1010 +--- @field ACT_CSGO_TWITCH 1011 +--- @field ACT_CSGO_TWITCH_BUYZONE 1012 +--- @field ACT_CSGO_PLANT_BOMB 1013 +--- @field ACT_CSGO_IDLE_TURN_BALANCEADJUST 1014 +--- @field ACT_CSGO_IDLE_ADJUST_STOPPEDMOVING 1015 +--- @field ACT_CSGO_ALIVE_LOOP 1016 +--- @field ACT_CSGO_FLINCH 1017 +--- @field ACT_CSGO_FLINCH_HEAD 1018 +--- @field ACT_CSGO_FLINCH_MOLOTOV 1019 +--- @field ACT_CSGO_JUMP 1020 +--- @field ACT_CSGO_FALL 1021 +--- @field ACT_CSGO_CLIMB_LADDER 1022 +--- @field ACT_CSGO_LAND_LIGHT 1023 +--- @field ACT_CSGO_LAND_HEAVY 1024 +--- @field ACT_CSGO_EXIT_LADDER_TOP 1025 +--- @field ACT_CSGO_EXIT_LADDER_BOTTOM 1026 +--- @field ACT_CSGO_PARACHUTE 1027 +--- @field ACT_CSGO_TAUNT 1028 +--- @field ACT_DOTA_IDLE 1500 +--- @field ACT_DOTA_IDLE_RARE 1501 +--- @field ACT_DOTA_RUN 1502 +--- @field ACT_DOTA_ATTACK 1503 +--- @field ACT_DOTA_ATTACK2 1504 +--- @field ACT_DOTA_ATTACK_EVENT 1505 +--- @field ACT_DOTA_DIE 1506 +--- @field ACT_DOTA_FLINCH 1507 +--- @field ACT_DOTA_FLAIL 1508 +--- @field ACT_DOTA_DISABLED 1509 +--- @field ACT_DOTA_CAST_ABILITY_1 1510 +--- @field ACT_DOTA_CAST_ABILITY_2 1511 +--- @field ACT_DOTA_CAST_ABILITY_3 1512 +--- @field ACT_DOTA_CAST_ABILITY_4 1513 +--- @field ACT_DOTA_CAST_ABILITY_5 1514 +--- @field ACT_DOTA_CAST_ABILITY_6 1515 +--- @field ACT_DOTA_OVERRIDE_ABILITY_1 1516 +--- @field ACT_DOTA_OVERRIDE_ABILITY_2 1517 +--- @field ACT_DOTA_OVERRIDE_ABILITY_3 1518 +--- @field ACT_DOTA_OVERRIDE_ABILITY_4 1519 +--- @field ACT_DOTA_CHANNEL_ABILITY_1 1520 +--- @field ACT_DOTA_CHANNEL_ABILITY_2 1521 +--- @field ACT_DOTA_CHANNEL_ABILITY_3 1522 +--- @field ACT_DOTA_CHANNEL_ABILITY_4 1523 +--- @field ACT_DOTA_CHANNEL_ABILITY_5 1524 +--- @field ACT_DOTA_CHANNEL_ABILITY_6 1525 +--- @field ACT_DOTA_CHANNEL_END_ABILITY_1 1526 +--- @field ACT_DOTA_CHANNEL_END_ABILITY_2 1527 +--- @field ACT_DOTA_CHANNEL_END_ABILITY_3 1528 +--- @field ACT_DOTA_CHANNEL_END_ABILITY_4 1529 +--- @field ACT_DOTA_CHANNEL_END_ABILITY_5 1530 +--- @field ACT_DOTA_CHANNEL_END_ABILITY_6 1531 +--- @field ACT_DOTA_CONSTANT_LAYER 1532 +--- @field ACT_DOTA_CAPTURE 1533 +--- @field ACT_DOTA_SPAWN 1534 +--- @field ACT_DOTA_KILLTAUNT 1535 +--- @field ACT_DOTA_TAUNT 1536 +--- @field ACT_DOTA_THIRST 1537 +--- @field ACT_DOTA_CAST_DRAGONBREATH 1538 +--- @field ACT_DOTA_ECHO_SLAM 1539 +--- @field ACT_DOTA_CAST_ABILITY_1_END 1540 +--- @field ACT_DOTA_CAST_ABILITY_2_END 1541 +--- @field ACT_DOTA_CAST_ABILITY_3_END 1542 +--- @field ACT_DOTA_CAST_ABILITY_4_END 1543 +--- @field ACT_MIRANA_LEAP_END 1544 +--- @field ACT_WAVEFORM_START 1545 +--- @field ACT_WAVEFORM_END 1546 +--- @field ACT_DOTA_CAST_ABILITY_ROT 1547 +--- @field ACT_DOTA_DIE_SPECIAL 1548 +--- @field ACT_DOTA_RATTLETRAP_BATTERYASSAULT 1549 +--- @field ACT_DOTA_RATTLETRAP_POWERCOGS 1550 +--- @field ACT_DOTA_RATTLETRAP_HOOKSHOT_START 1551 +--- @field ACT_DOTA_RATTLETRAP_HOOKSHOT_LOOP 1552 +--- @field ACT_DOTA_RATTLETRAP_HOOKSHOT_END 1553 +--- @field ACT_STORM_SPIRIT_OVERLOAD_RUN_OVERRIDE 1554 +--- @field ACT_DOTA_TINKER_REARM1 1555 +--- @field ACT_DOTA_TINKER_REARM2 1556 +--- @field ACT_DOTA_TINKER_REARM3 1557 +--- @field ACT_TINY_AVALANCHE 1558 +--- @field ACT_TINY_TOSS 1559 +--- @field ACT_TINY_GROWL 1560 +--- @field ACT_DOTA_WEAVERBUG_ATTACH 1561 +--- @field ACT_DOTA_CAST_WILD_AXES_END 1562 +--- @field ACT_DOTA_CAST_LIFE_BREAK_START 1563 +--- @field ACT_DOTA_CAST_LIFE_BREAK_END 1564 +--- @field ACT_DOTA_NIGHTSTALKER_TRANSITION 1565 +--- @field ACT_DOTA_LIFESTEALER_RAGE 1566 +--- @field ACT_DOTA_LIFESTEALER_OPEN_WOUNDS 1567 +--- @field ACT_DOTA_SAND_KING_BURROW_IN 1568 +--- @field ACT_DOTA_SAND_KING_BURROW_OUT 1569 +--- @field ACT_DOTA_EARTHSHAKER_TOTEM_ATTACK 1570 +--- @field ACT_DOTA_WHEEL_LAYER 1571 +--- @field ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START 1572 +--- @field ACT_DOTA_ALCHEMIST_CONCOCTION 1573 +--- @field ACT_DOTA_JAKIRO_LIQUIDFIRE_START 1574 +--- @field ACT_DOTA_JAKIRO_LIQUIDFIRE_LOOP 1575 +--- @field ACT_DOTA_LIFESTEALER_INFEST 1576 +--- @field ACT_DOTA_LIFESTEALER_INFEST_END 1577 +--- @field ACT_DOTA_LASSO_LOOP 1578 +--- @field ACT_DOTA_ALCHEMIST_CONCOCTION_THROW 1579 +--- @field ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END 1580 +--- @field ACT_DOTA_CAST_COLD_SNAP 1581 +--- @field ACT_DOTA_CAST_GHOST_WALK 1582 +--- @field ACT_DOTA_CAST_TORNADO 1583 +--- @field ACT_DOTA_CAST_EMP 1584 +--- @field ACT_DOTA_CAST_ALACRITY 1585 +--- @field ACT_DOTA_CAST_CHAOS_METEOR 1586 +--- @field ACT_DOTA_CAST_SUN_STRIKE 1587 +--- @field ACT_DOTA_CAST_FORGE_SPIRIT 1588 +--- @field ACT_DOTA_CAST_ICE_WALL 1589 +--- @field ACT_DOTA_CAST_DEAFENING_BLAST 1590 +--- @field ACT_DOTA_VICTORY 1591 +--- @field ACT_DOTA_DEFEAT 1592 +--- @field ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE 1593 +--- @field ACT_DOTA_SPIRIT_BREAKER_CHARGE_END 1594 +--- @field ACT_DOTA_TELEPORT 1595 +--- @field ACT_DOTA_TELEPORT_END 1596 +--- @field ACT_DOTA_CAST_REFRACTION 1597 +--- @field ACT_DOTA_CAST_ABILITY_7 1598 +--- @field ACT_DOTA_CANCEL_SIREN_SONG 1599 +--- @field ACT_DOTA_CHANNEL_ABILITY_7 1600 +--- @field ACT_DOTA_LOADOUT 1601 +--- @field ACT_DOTA_FORCESTAFF_END 1602 +--- @field ACT_DOTA_POOF_END 1603 +--- @field ACT_DOTA_SLARK_POUNCE 1604 +--- @field ACT_DOTA_MAGNUS_SKEWER_START 1605 +--- @field ACT_DOTA_MAGNUS_SKEWER_END 1606 +--- @field ACT_DOTA_MEDUSA_STONE_GAZE 1607 +--- @field ACT_DOTA_RELAX_START 1608 +--- @field ACT_DOTA_RELAX_LOOP 1609 +--- @field ACT_DOTA_RELAX_END 1610 +--- @field ACT_DOTA_CENTAUR_STAMPEDE 1611 +--- @field ACT_DOTA_BELLYACHE_START 1612 +--- @field ACT_DOTA_BELLYACHE_LOOP 1613 +--- @field ACT_DOTA_BELLYACHE_END 1614 +--- @field ACT_DOTA_ROQUELAIRE_LAND 1615 +--- @field ACT_DOTA_ROQUELAIRE_LAND_IDLE 1616 +--- @field ACT_DOTA_GREEVIL_CAST 1617 +--- @field ACT_DOTA_GREEVIL_OVERRIDE_ABILITY 1618 +--- @field ACT_DOTA_GREEVIL_HOOK_START 1619 +--- @field ACT_DOTA_GREEVIL_HOOK_END 1620 +--- @field ACT_DOTA_GREEVIL_BLINK_BONE 1621 +--- @field ACT_DOTA_IDLE_SLEEPING 1622 +--- @field ACT_DOTA_INTRO 1623 +--- @field ACT_DOTA_GESTURE_POINT 1624 +--- @field ACT_DOTA_GESTURE_ACCENT 1625 +--- @field ACT_DOTA_SLEEPING_END 1626 +--- @field ACT_DOTA_AMBUSH 1627 +--- @field ACT_DOTA_ITEM_LOOK 1628 +--- @field ACT_DOTA_STARTLE 1629 +--- @field ACT_DOTA_FRUSTRATION 1630 +--- @field ACT_DOTA_TELEPORT_REACT 1631 +--- @field ACT_DOTA_TELEPORT_END_REACT 1632 +--- @field ACT_DOTA_SHRUG 1633 +--- @field ACT_DOTA_RELAX_LOOP_END 1634 +--- @field ACT_DOTA_PRESENT_ITEM 1635 +--- @field ACT_DOTA_IDLE_IMPATIENT 1636 +--- @field ACT_DOTA_SHARPEN_WEAPON 1637 +--- @field ACT_DOTA_SHARPEN_WEAPON_OUT 1638 +--- @field ACT_DOTA_IDLE_SLEEPING_END 1639 +--- @field ACT_DOTA_BRIDGE_DESTROY 1640 +--- @field ACT_DOTA_TAUNT_SNIPER 1641 +--- @field ACT_DOTA_DEATH_BY_SNIPER 1642 +--- @field ACT_DOTA_LOOK_AROUND 1643 +--- @field ACT_DOTA_CAGED_CREEP_RAGE 1644 +--- @field ACT_DOTA_CAGED_CREEP_RAGE_OUT 1645 +--- @field ACT_DOTA_CAGED_CREEP_SMASH 1646 +--- @field ACT_DOTA_CAGED_CREEP_SMASH_OUT 1647 +--- @field ACT_DOTA_IDLE_IMPATIENT_SWORD_TAP 1648 +--- @field ACT_DOTA_INTRO_LOOP 1649 +--- @field ACT_DOTA_BRIDGE_THREAT 1650 +--- @field ACT_DOTA_DAGON 1651 +--- @field ACT_DOTA_CAST_ABILITY_2_ES_ROLL_START 1652 +--- @field ACT_DOTA_CAST_ABILITY_2_ES_ROLL 1653 +--- @field ACT_DOTA_CAST_ABILITY_2_ES_ROLL_END 1654 +--- @field ACT_DOTA_NIAN_PIN_START 1655 +--- @field ACT_DOTA_NIAN_PIN_LOOP 1656 +--- @field ACT_DOTA_NIAN_PIN_END 1657 +--- @field ACT_DOTA_LEAP_STUN 1658 +--- @field ACT_DOTA_LEAP_SWIPE 1659 +--- @field ACT_DOTA_NIAN_INTRO_LEAP 1660 +--- @field ACT_DOTA_AREA_DENY 1661 +--- @field ACT_DOTA_NIAN_PIN_TO_STUN 1662 +--- @field ACT_DOTA_RAZE_1 1663 +--- @field ACT_DOTA_RAZE_2 1664 +--- @field ACT_DOTA_RAZE_3 1665 +--- @field ACT_DOTA_UNDYING_DECAY 1666 +--- @field ACT_DOTA_UNDYING_SOUL_RIP 1667 +--- @field ACT_DOTA_UNDYING_TOMBSTONE 1668 +--- @field ACT_DOTA_WHIRLING_AXES_RANGED 1669 +--- @field ACT_DOTA_SHALLOW_GRAVE 1670 +--- @field ACT_DOTA_COLD_FEET 1671 +--- @field ACT_DOTA_ICE_VORTEX 1672 +--- @field ACT_DOTA_CHILLING_TOUCH 1673 +--- @field ACT_DOTA_ENFEEBLE 1674 +--- @field ACT_DOTA_FATAL_BONDS 1675 +--- @field ACT_DOTA_MIDNIGHT_PULSE 1676 +--- @field ACT_DOTA_ANCESTRAL_SPIRIT 1677 +--- @field ACT_DOTA_THUNDER_STRIKE 1678 +--- @field ACT_DOTA_KINETIC_FIELD 1679 +--- @field ACT_DOTA_STATIC_STORM 1680 +--- @field ACT_DOTA_MINI_TAUNT 1681 +--- @field ACT_DOTA_ARCTIC_BURN_END 1682 +--- @field ACT_DOTA_LOADOUT_RARE 1683 +--- @field ACT_DOTA_SWIM 1684 +--- @field ACT_DOTA_FLEE 1685 +--- @field ACT_DOTA_TROT 1686 +--- @field ACT_DOTA_SHAKE 1687 +--- @field ACT_DOTA_SWIM_IDLE 1688 +--- @field ACT_DOTA_WAIT_IDLE 1689 +--- @field ACT_DOTA_GREET 1690 +--- @field ACT_DOTA_TELEPORT_COOP_START 1691 +--- @field ACT_DOTA_TELEPORT_COOP_WAIT 1692 +--- @field ACT_DOTA_TELEPORT_COOP_END 1693 +--- @field ACT_DOTA_TELEPORT_COOP_EXIT 1694 +--- @field ACT_DOTA_SHOPKEEPER_PET_INTERACT 1695 +--- @field ACT_DOTA_ITEM_PICKUP 1696 +--- @field ACT_DOTA_ITEM_DROP 1697 +--- @field ACT_DOTA_CAPTURE_PET 1698 +--- @field ACT_DOTA_PET_WARD_OBSERVER 1699 +--- @field ACT_DOTA_PET_WARD_SENTRY 1700 +--- @field ACT_DOTA_PET_LEVEL 1701 +--- @field ACT_DOTA_CAST_BURROW_END 1702 +--- @field ACT_DOTA_LIFESTEALER_ASSIMILATE 1703 +--- @field ACT_DOTA_LIFESTEALER_EJECT 1704 +--- @field ACT_DOTA_ATTACK_EVENT_BASH 1705 +--- @field ACT_DOTA_CAPTURE_RARE 1706 +--- @field ACT_DOTA_AW_MAGNETIC_FIELD 1707 +--- @field ACT_DOTA_CAST_GHOST_SHIP 1708 +--- @field ACT_DOTA_FXANIM 1709 +--- @field ACT_DOTA_VICTORY_START 1710 +--- @field ACT_DOTA_DEFEAT_START 1711 +--- @field ACT_DOTA_DP_SPIRIT_SIPHON 1712 +--- @field ACT_DOTA_TRICKS_END 1713 +--- @field ACT_DOTA_ES_STONE_CALLER 1714 +--- @field ACT_DOTA_MK_STRIKE 1715 +--- @field ACT_DOTA_VERSUS 1716 +--- @field ACT_DOTA_CAPTURE_CARD 1717 +--- @field ACT_DOTA_MK_SPRING_SOAR 1718 +--- @field ACT_DOTA_MK_SPRING_END 1719 +--- @field ACT_DOTA_MK_TREE_SOAR 1720 +--- @field ACT_DOTA_MK_TREE_END 1721 +--- @field ACT_DOTA_MK_FUR_ARMY 1722 +--- @field ACT_DOTA_MK_SPRING_CAST 1723 +--- @field ACT_DOTA_NECRO_GHOST_SHROUD 1724 +--- @field ACT_DOTA_OVERRIDE_ARCANA 1725 +--- @field ACT_DOTA_SLIDE 1726 +--- @field ACT_DOTA_SLIDE_LOOP 1727 +--- @field ACT_DOTA_GENERIC_CHANNEL_1 1728 +--- @field ACT_DOTA_GS_SOUL_CHAIN 1729 +--- @field ACT_DOTA_GS_INK_CREATURE 1730 +--- @field ACT_DOTA_TRANSITION 1731 +--- @field ACT_DOTA_BLINK_DAGGER 1732 +--- @field ACT_DOTA_BLINK_DAGGER_END 1733 +--- @field ACT_DOTA_CUSTOM_TOWER_ATTACK 1734 +--- @field ACT_DOTA_CUSTOM_TOWER_IDLE 1735 +--- @field ACT_DOTA_CUSTOM_TOWER_DIE 1736 +--- @field ACT_DOTA_CAST_COLD_SNAP_ORB 1737 +--- @field ACT_DOTA_CAST_GHOST_WALK_ORB 1738 +--- @field ACT_DOTA_CAST_TORNADO_ORB 1739 +--- @field ACT_DOTA_CAST_EMP_ORB 1740 +--- @field ACT_DOTA_CAST_ALACRITY_ORB 1741 +--- @field ACT_DOTA_CAST_CHAOS_METEOR_ORB 1742 +--- @field ACT_DOTA_CAST_SUN_STRIKE_ORB 1743 +--- @field ACT_DOTA_CAST_FORGE_SPIRIT_ORB 1744 +--- @field ACT_DOTA_CAST_ICE_WALL_ORB 1745 +--- @field ACT_DOTA_CAST_DEAFENING_BLAST_ORB 1746 +--- @field ACT_DOTA_NOTICE 1747 +--- @field ACT_DOTA_CAST_ABILITY_2_ALLY 1748 +--- @field ACT_DOTA_SHUFFLE_L 1749 +--- @field ACT_DOTA_SHUFFLE_R 1750 +--- @field ACT_DOTA_OVERRIDE_LOADOUT 1751 +--- @field ACT_DOTA_TAUNT_SPECIAL 1752 +--- @field ACT_DOTA_TELEPORT_START 1753 +--- @field ACT_DOTA_GENERIC_CHANNEL_1_START 1754 +--- @field ACT_DOTA_CUSTOM_TOWER_IDLE_RARE 1755 +--- @field ACT_DOTA_CUSTOM_TOWER_TAUNT 1756 +--- @field ACT_DOTA_CUSTOM_TOWER_HIGH_FIVE 1757 +--- @field ACT_DOTA_ATTACK_SPECIAL 1758 +--- @field ACT_DOTA_TRANSITION_IDLE 1759 +--- @field ACT_DOTA_PIERCE_THE_VEIL 1760 +--- @field ACT_DOTA_RUN_RARE 1761 +--- @field ACT_DOTA_VIPER_DIVE 1762 +--- @field ACT_DOTA_VIPER_DIVE_END 1763 +--- @field ACT_DOTA_MK_STRIKE_END 1764 +--- @field ACT_DOTA_SHADOW_VAULT 1765 +--- @field ACT_DOTA_KEZ_KATANA_ULT_START 1766 +--- @field ACT_DOTA_KEZ_KATANA_ULT_CHAIN_A 1767 +--- @field ACT_DOTA_KEZ_KATANA_ULT_CHAIN_B 1768 +--- @field ACT_DOTA_KEZ_KATANA_ULT_END 1769 +--- @field ACT_DOTA_KEZ_KATANA_IMPALE 1770 +--- @field ACT_DOTA_KEZ_KATANA_IMPALE_FAST 1771 +--- @field ACT_DOTA_UNICYCLE 1772 +--- @field ACT_DOTA_UNICYCLE_END 1773 +--- @field ACT_DOTA_MVP_SCREEN 1776 +--- @field ACT_DOTA_RUN_STATUE 1777 +--- @field ACT_DOTA_CAST1_STATUE 1778 +--- @field ACT_DOTA_CAST2_STATUE 1779 +--- @field ACT_DOTA_STUN_STATUE 1780 +--- @field ACT_DOTA_FLAIL_STATUE 1781 +--- @field ACT_DOTA_SPAWN_STATUE 1782 +--- @field ACT_DOTA_TELEPORT_END_STATUE 1783 +--- @field ACT_DOTA_ATTACK_STATUE 1784 +--- @field ACT_DOTA_FORCESTAFF_STATUE 1785 +--- @field ACT_DOTA_TELEPORT_STATUE 1786 +--- @field ACT_DOTA_VICTORY_STATUE 1787 +--- @field ACT_DOTA_TAUNT_STATUE 1788 +--- @field ACT_DOTA_DISABLED_END 1789 +--- @field ACT_DOTA_CYCLONE 1791 +--- @field ACT_DOTA_IMPALE 1792 +--- @field ACT_DOTA_TORRENT 1793 +--- @field ACT_DOTA_VOODOO_REST 1794 +--- @field ACT_DOTA_RUN_ALT 1795 +--- @field ACT_DOTA_RADIANT_CREEP_HAMMER 1800 +--- @field ACT_DOTA_RELAX_IN 1801 +--- @field ACT_DOTA_RELAX_OUT 1802 +--- @field ACT_DOTA_CAST_FENCE 1803 +--- @field ACT_DOTA_SPWN 1804 +local GameActivity_t = {} +ACT_RESET = GameActivity_t.ACT_RESET +ACT_IDLE = GameActivity_t.ACT_IDLE +ACT_TRANSITION = GameActivity_t.ACT_TRANSITION +ACT_COVER = GameActivity_t.ACT_COVER +ACT_COVER_MED = GameActivity_t.ACT_COVER_MED +ACT_COVER_LOW = GameActivity_t.ACT_COVER_LOW +ACT_WALK = GameActivity_t.ACT_WALK +ACT_WALK_AIM = GameActivity_t.ACT_WALK_AIM +ACT_WALK_CROUCH = GameActivity_t.ACT_WALK_CROUCH +ACT_WALK_CROUCH_AIM = GameActivity_t.ACT_WALK_CROUCH_AIM +ACT_RUN = GameActivity_t.ACT_RUN +ACT_RUN_AIM = GameActivity_t.ACT_RUN_AIM +ACT_RUN_CROUCH = GameActivity_t.ACT_RUN_CROUCH +ACT_RUN_CROUCH_AIM = GameActivity_t.ACT_RUN_CROUCH_AIM +ACT_RUN_PROTECTED = GameActivity_t.ACT_RUN_PROTECTED +ACT_SCRIPT_CUSTOM_MOVE = GameActivity_t.ACT_SCRIPT_CUSTOM_MOVE +ACT_RANGE_ATTACK1 = GameActivity_t.ACT_RANGE_ATTACK1 +ACT_RANGE_ATTACK2 = GameActivity_t.ACT_RANGE_ATTACK2 +ACT_RANGE_ATTACK1_LOW = GameActivity_t.ACT_RANGE_ATTACK1_LOW +ACT_RANGE_ATTACK2_LOW = GameActivity_t.ACT_RANGE_ATTACK2_LOW +ACT_DIESIMPLE = GameActivity_t.ACT_DIESIMPLE +ACT_DIEBACKWARD = GameActivity_t.ACT_DIEBACKWARD +ACT_DIEFORWARD = GameActivity_t.ACT_DIEFORWARD +ACT_DIEVIOLENT = GameActivity_t.ACT_DIEVIOLENT +ACT_DIERAGDOLL = GameActivity_t.ACT_DIERAGDOLL +ACT_FLY = GameActivity_t.ACT_FLY +ACT_HOVER = GameActivity_t.ACT_HOVER +ACT_GLIDE = GameActivity_t.ACT_GLIDE +ACT_SWIM = GameActivity_t.ACT_SWIM +ACT_JUMP = GameActivity_t.ACT_JUMP +ACT_HOP = GameActivity_t.ACT_HOP +ACT_LEAP = GameActivity_t.ACT_LEAP +ACT_LAND = GameActivity_t.ACT_LAND +ACT_CLIMB_UP = GameActivity_t.ACT_CLIMB_UP +ACT_CLIMB_DOWN = GameActivity_t.ACT_CLIMB_DOWN +ACT_CLIMB_DISMOUNT = GameActivity_t.ACT_CLIMB_DISMOUNT +ACT_SHIPLADDER_UP = GameActivity_t.ACT_SHIPLADDER_UP +ACT_SHIPLADDER_DOWN = GameActivity_t.ACT_SHIPLADDER_DOWN +ACT_STRAFE_LEFT = GameActivity_t.ACT_STRAFE_LEFT +ACT_STRAFE_RIGHT = GameActivity_t.ACT_STRAFE_RIGHT +ACT_ROLL_LEFT = GameActivity_t.ACT_ROLL_LEFT +ACT_ROLL_RIGHT = GameActivity_t.ACT_ROLL_RIGHT +ACT_TURN_LEFT = GameActivity_t.ACT_TURN_LEFT +ACT_TURN_RIGHT = GameActivity_t.ACT_TURN_RIGHT +ACT_CROUCH = GameActivity_t.ACT_CROUCH +ACT_CROUCHIDLE = GameActivity_t.ACT_CROUCHIDLE +ACT_STAND = GameActivity_t.ACT_STAND +ACT_USE = GameActivity_t.ACT_USE +ACT_ALIEN_BURROW_IDLE = GameActivity_t.ACT_ALIEN_BURROW_IDLE +ACT_ALIEN_BURROW_OUT = GameActivity_t.ACT_ALIEN_BURROW_OUT +ACT_SIGNAL1 = GameActivity_t.ACT_SIGNAL1 +ACT_SIGNAL2 = GameActivity_t.ACT_SIGNAL2 +ACT_SIGNAL3 = GameActivity_t.ACT_SIGNAL3 +ACT_SIGNAL_ADVANCE = GameActivity_t.ACT_SIGNAL_ADVANCE +ACT_SIGNAL_FORWARD = GameActivity_t.ACT_SIGNAL_FORWARD +ACT_SIGNAL_GROUP = GameActivity_t.ACT_SIGNAL_GROUP +ACT_SIGNAL_HALT = GameActivity_t.ACT_SIGNAL_HALT +ACT_SIGNAL_LEFT = GameActivity_t.ACT_SIGNAL_LEFT +ACT_SIGNAL_RIGHT = GameActivity_t.ACT_SIGNAL_RIGHT +ACT_SIGNAL_TAKECOVER = GameActivity_t.ACT_SIGNAL_TAKECOVER +ACT_LOOKBACK_RIGHT = GameActivity_t.ACT_LOOKBACK_RIGHT +ACT_LOOKBACK_LEFT = GameActivity_t.ACT_LOOKBACK_LEFT +ACT_COWER = GameActivity_t.ACT_COWER +ACT_SMALL_FLINCH = GameActivity_t.ACT_SMALL_FLINCH +ACT_BIG_FLINCH = GameActivity_t.ACT_BIG_FLINCH +ACT_MELEE_ATTACK1 = GameActivity_t.ACT_MELEE_ATTACK1 +ACT_MELEE_ATTACK2 = GameActivity_t.ACT_MELEE_ATTACK2 +ACT_RELOAD = GameActivity_t.ACT_RELOAD +ACT_RELOAD_START = GameActivity_t.ACT_RELOAD_START +ACT_RELOAD_FINISH = GameActivity_t.ACT_RELOAD_FINISH +ACT_RELOAD_LOW = GameActivity_t.ACT_RELOAD_LOW +ACT_ARM = GameActivity_t.ACT_ARM +ACT_DISARM = GameActivity_t.ACT_DISARM +ACT_DROP_WEAPON = GameActivity_t.ACT_DROP_WEAPON +ACT_DROP_WEAPON_SHOTGUN = GameActivity_t.ACT_DROP_WEAPON_SHOTGUN +ACT_PICKUP_GROUND = GameActivity_t.ACT_PICKUP_GROUND +ACT_PICKUP_RACK = GameActivity_t.ACT_PICKUP_RACK +ACT_IDLE_ANGRY = GameActivity_t.ACT_IDLE_ANGRY +ACT_IDLE_RELAXED = GameActivity_t.ACT_IDLE_RELAXED +ACT_IDLE_STIMULATED = GameActivity_t.ACT_IDLE_STIMULATED +ACT_IDLE_AGITATED = GameActivity_t.ACT_IDLE_AGITATED +ACT_IDLE_STEALTH = GameActivity_t.ACT_IDLE_STEALTH +ACT_IDLE_HURT = GameActivity_t.ACT_IDLE_HURT +ACT_WALK_RELAXED = GameActivity_t.ACT_WALK_RELAXED +ACT_WALK_STIMULATED = GameActivity_t.ACT_WALK_STIMULATED +ACT_WALK_AGITATED = GameActivity_t.ACT_WALK_AGITATED +ACT_WALK_STEALTH = GameActivity_t.ACT_WALK_STEALTH +ACT_RUN_RELAXED = GameActivity_t.ACT_RUN_RELAXED +ACT_RUN_STIMULATED = GameActivity_t.ACT_RUN_STIMULATED +ACT_RUN_AGITATED = GameActivity_t.ACT_RUN_AGITATED +ACT_RUN_STEALTH = GameActivity_t.ACT_RUN_STEALTH +ACT_IDLE_AIM_RELAXED = GameActivity_t.ACT_IDLE_AIM_RELAXED +ACT_IDLE_AIM_STIMULATED = GameActivity_t.ACT_IDLE_AIM_STIMULATED +ACT_IDLE_AIM_AGITATED = GameActivity_t.ACT_IDLE_AIM_AGITATED +ACT_IDLE_AIM_STEALTH = GameActivity_t.ACT_IDLE_AIM_STEALTH +ACT_WALK_AIM_RELAXED = GameActivity_t.ACT_WALK_AIM_RELAXED +ACT_WALK_AIM_STIMULATED = GameActivity_t.ACT_WALK_AIM_STIMULATED +ACT_WALK_AIM_AGITATED = GameActivity_t.ACT_WALK_AIM_AGITATED +ACT_WALK_AIM_STEALTH = GameActivity_t.ACT_WALK_AIM_STEALTH +ACT_RUN_AIM_RELAXED = GameActivity_t.ACT_RUN_AIM_RELAXED +ACT_RUN_AIM_STIMULATED = GameActivity_t.ACT_RUN_AIM_STIMULATED +ACT_RUN_AIM_AGITATED = GameActivity_t.ACT_RUN_AIM_AGITATED +ACT_RUN_AIM_STEALTH = GameActivity_t.ACT_RUN_AIM_STEALTH +ACT_CROUCHIDLE_STIMULATED = GameActivity_t.ACT_CROUCHIDLE_STIMULATED +ACT_CROUCHIDLE_AIM_STIMULATED = GameActivity_t.ACT_CROUCHIDLE_AIM_STIMULATED +ACT_CROUCHIDLE_AGITATED = GameActivity_t.ACT_CROUCHIDLE_AGITATED +ACT_WALK_HURT = GameActivity_t.ACT_WALK_HURT +ACT_RUN_HURT = GameActivity_t.ACT_RUN_HURT +ACT_SPECIAL_ATTACK1 = GameActivity_t.ACT_SPECIAL_ATTACK1 +ACT_SPECIAL_ATTACK2 = GameActivity_t.ACT_SPECIAL_ATTACK2 +ACT_COMBAT_IDLE = GameActivity_t.ACT_COMBAT_IDLE +ACT_WALK_SCARED = GameActivity_t.ACT_WALK_SCARED +ACT_RUN_SCARED = GameActivity_t.ACT_RUN_SCARED +ACT_VICTORY_DANCE = GameActivity_t.ACT_VICTORY_DANCE +ACT_DIE_HEADSHOT = GameActivity_t.ACT_DIE_HEADSHOT +ACT_DIE_CHESTSHOT = GameActivity_t.ACT_DIE_CHESTSHOT +ACT_DIE_GUTSHOT = GameActivity_t.ACT_DIE_GUTSHOT +ACT_DIE_BACKSHOT = GameActivity_t.ACT_DIE_BACKSHOT +ACT_FLINCH_HEAD = GameActivity_t.ACT_FLINCH_HEAD +ACT_FLINCH_CHEST = GameActivity_t.ACT_FLINCH_CHEST +ACT_FLINCH_STOMACH = GameActivity_t.ACT_FLINCH_STOMACH +ACT_FLINCH_LEFTARM = GameActivity_t.ACT_FLINCH_LEFTARM +ACT_FLINCH_RIGHTARM = GameActivity_t.ACT_FLINCH_RIGHTARM +ACT_FLINCH_LEFTLEG = GameActivity_t.ACT_FLINCH_LEFTLEG +ACT_FLINCH_RIGHTLEG = GameActivity_t.ACT_FLINCH_RIGHTLEG +ACT_FLINCH_PHYSICS = GameActivity_t.ACT_FLINCH_PHYSICS +ACT_FLINCH_HEAD_BACK = GameActivity_t.ACT_FLINCH_HEAD_BACK +ACT_FLINCH_CHEST_BACK = GameActivity_t.ACT_FLINCH_CHEST_BACK +ACT_FLINCH_STOMACH_BACK = GameActivity_t.ACT_FLINCH_STOMACH_BACK +ACT_FLINCH_CROUCH_FRONT = GameActivity_t.ACT_FLINCH_CROUCH_FRONT +ACT_FLINCH_CROUCH_BACK = GameActivity_t.ACT_FLINCH_CROUCH_BACK +ACT_FLINCH_CROUCH_LEFT = GameActivity_t.ACT_FLINCH_CROUCH_LEFT +ACT_FLINCH_CROUCH_RIGHT = GameActivity_t.ACT_FLINCH_CROUCH_RIGHT +ACT_IDLE_ON_FIRE = GameActivity_t.ACT_IDLE_ON_FIRE +ACT_WALK_ON_FIRE = GameActivity_t.ACT_WALK_ON_FIRE +ACT_RUN_ON_FIRE = GameActivity_t.ACT_RUN_ON_FIRE +ACT_180_LEFT = GameActivity_t.ACT_180_LEFT +ACT_180_RIGHT = GameActivity_t.ACT_180_RIGHT +ACT_90_LEFT = GameActivity_t.ACT_90_LEFT +ACT_90_RIGHT = GameActivity_t.ACT_90_RIGHT +ACT_STEP_LEFT = GameActivity_t.ACT_STEP_LEFT +ACT_STEP_RIGHT = GameActivity_t.ACT_STEP_RIGHT +ACT_STEP_BACK = GameActivity_t.ACT_STEP_BACK +ACT_STEP_FORE = GameActivity_t.ACT_STEP_FORE +ACT_GESTURE_RANGE_ATTACK1 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK1 +ACT_GESTURE_RANGE_ATTACK2 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK2 +ACT_GESTURE_MELEE_ATTACK1 = GameActivity_t.ACT_GESTURE_MELEE_ATTACK1 +ACT_GESTURE_MELEE_ATTACK2 = GameActivity_t.ACT_GESTURE_MELEE_ATTACK2 +ACT_GESTURE_RANGE_ATTACK1_LOW = GameActivity_t.ACT_GESTURE_RANGE_ATTACK1_LOW +ACT_GESTURE_RANGE_ATTACK2_LOW = GameActivity_t.ACT_GESTURE_RANGE_ATTACK2_LOW +ACT_MELEE_ATTACK_SWING_GESTURE = GameActivity_t.ACT_MELEE_ATTACK_SWING_GESTURE +ACT_GESTURE_SMALL_FLINCH = GameActivity_t.ACT_GESTURE_SMALL_FLINCH +ACT_GESTURE_BIG_FLINCH = GameActivity_t.ACT_GESTURE_BIG_FLINCH +ACT_GESTURE_FLINCH_BLAST = GameActivity_t.ACT_GESTURE_FLINCH_BLAST +ACT_GESTURE_FLINCH_BLAST_SHOTGUN = GameActivity_t.ACT_GESTURE_FLINCH_BLAST_SHOTGUN +ACT_GESTURE_FLINCH_BLAST_DAMAGED = GameActivity_t.ACT_GESTURE_FLINCH_BLAST_DAMAGED +ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN = GameActivity_t.ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN +ACT_GESTURE_FLINCH_HEAD = GameActivity_t.ACT_GESTURE_FLINCH_HEAD +ACT_GESTURE_FLINCH_CHEST = GameActivity_t.ACT_GESTURE_FLINCH_CHEST +ACT_GESTURE_FLINCH_STOMACH = GameActivity_t.ACT_GESTURE_FLINCH_STOMACH +ACT_GESTURE_FLINCH_LEFTARM = GameActivity_t.ACT_GESTURE_FLINCH_LEFTARM +ACT_GESTURE_FLINCH_RIGHTARM = GameActivity_t.ACT_GESTURE_FLINCH_RIGHTARM +ACT_GESTURE_FLINCH_LEFTLEG = GameActivity_t.ACT_GESTURE_FLINCH_LEFTLEG +ACT_GESTURE_FLINCH_RIGHTLEG = GameActivity_t.ACT_GESTURE_FLINCH_RIGHTLEG +ACT_GESTURE_TURN_LEFT = GameActivity_t.ACT_GESTURE_TURN_LEFT +ACT_GESTURE_TURN_RIGHT = GameActivity_t.ACT_GESTURE_TURN_RIGHT +ACT_GESTURE_TURN_LEFT45 = GameActivity_t.ACT_GESTURE_TURN_LEFT45 +ACT_GESTURE_TURN_RIGHT45 = GameActivity_t.ACT_GESTURE_TURN_RIGHT45 +ACT_GESTURE_TURN_LEFT90 = GameActivity_t.ACT_GESTURE_TURN_LEFT90 +ACT_GESTURE_TURN_RIGHT90 = GameActivity_t.ACT_GESTURE_TURN_RIGHT90 +ACT_GESTURE_TURN_LEFT45_FLAT = GameActivity_t.ACT_GESTURE_TURN_LEFT45_FLAT +ACT_GESTURE_TURN_RIGHT45_FLAT = GameActivity_t.ACT_GESTURE_TURN_RIGHT45_FLAT +ACT_GESTURE_TURN_LEFT90_FLAT = GameActivity_t.ACT_GESTURE_TURN_LEFT90_FLAT +ACT_GESTURE_TURN_RIGHT90_FLAT = GameActivity_t.ACT_GESTURE_TURN_RIGHT90_FLAT +ACT_BARNACLE_HIT = GameActivity_t.ACT_BARNACLE_HIT +ACT_BARNACLE_PULL = GameActivity_t.ACT_BARNACLE_PULL +ACT_BARNACLE_CHOMP = GameActivity_t.ACT_BARNACLE_CHOMP +ACT_BARNACLE_CHEW = GameActivity_t.ACT_BARNACLE_CHEW +ACT_DO_NOT_DISTURB = GameActivity_t.ACT_DO_NOT_DISTURB +ACT_SPECIFIC_SEQUENCE = GameActivity_t.ACT_SPECIFIC_SEQUENCE +ACT_VM_DEPLOY = GameActivity_t.ACT_VM_DEPLOY +ACT_VM_RELOAD_EMPTY = GameActivity_t.ACT_VM_RELOAD_EMPTY +ACT_VM_DRAW = GameActivity_t.ACT_VM_DRAW +ACT_VM_HOLSTER = GameActivity_t.ACT_VM_HOLSTER +ACT_VM_IDLE = GameActivity_t.ACT_VM_IDLE +ACT_VM_FIDGET = GameActivity_t.ACT_VM_FIDGET +ACT_VM_PULLBACK = GameActivity_t.ACT_VM_PULLBACK +ACT_VM_PULLBACK_HIGH = GameActivity_t.ACT_VM_PULLBACK_HIGH +ACT_VM_PULLBACK_LOW = GameActivity_t.ACT_VM_PULLBACK_LOW +ACT_VM_THROW = GameActivity_t.ACT_VM_THROW +ACT_VM_DROP = GameActivity_t.ACT_VM_DROP +ACT_VM_PULLPIN = GameActivity_t.ACT_VM_PULLPIN +ACT_VM_PRIMARYATTACK = GameActivity_t.ACT_VM_PRIMARYATTACK +ACT_VM_SECONDARYATTACK = GameActivity_t.ACT_VM_SECONDARYATTACK +ACT_VM_RELOAD = GameActivity_t.ACT_VM_RELOAD +ACT_VM_DRYFIRE = GameActivity_t.ACT_VM_DRYFIRE +ACT_VM_HITLEFT = GameActivity_t.ACT_VM_HITLEFT +ACT_VM_HITLEFT2 = GameActivity_t.ACT_VM_HITLEFT2 +ACT_VM_HITRIGHT = GameActivity_t.ACT_VM_HITRIGHT +ACT_VM_HITRIGHT2 = GameActivity_t.ACT_VM_HITRIGHT2 +ACT_VM_HITCENTER = GameActivity_t.ACT_VM_HITCENTER +ACT_VM_HITCENTER2 = GameActivity_t.ACT_VM_HITCENTER2 +ACT_VM_MISSLEFT = GameActivity_t.ACT_VM_MISSLEFT +ACT_VM_MISSLEFT2 = GameActivity_t.ACT_VM_MISSLEFT2 +ACT_VM_MISSRIGHT = GameActivity_t.ACT_VM_MISSRIGHT +ACT_VM_MISSRIGHT2 = GameActivity_t.ACT_VM_MISSRIGHT2 +ACT_VM_MISSCENTER = GameActivity_t.ACT_VM_MISSCENTER +ACT_VM_MISSCENTER2 = GameActivity_t.ACT_VM_MISSCENTER2 +ACT_VM_HAULBACK = GameActivity_t.ACT_VM_HAULBACK +ACT_VM_SWINGHARD = GameActivity_t.ACT_VM_SWINGHARD +ACT_VM_SWINGMISS = GameActivity_t.ACT_VM_SWINGMISS +ACT_VM_SWINGHIT = GameActivity_t.ACT_VM_SWINGHIT +ACT_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_VM_IDLE_TO_LOWERED +ACT_VM_IDLE_LOWERED = GameActivity_t.ACT_VM_IDLE_LOWERED +ACT_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_VM_LOWERED_TO_IDLE +ACT_VM_RECOIL1 = GameActivity_t.ACT_VM_RECOIL1 +ACT_VM_RECOIL2 = GameActivity_t.ACT_VM_RECOIL2 +ACT_VM_RECOIL3 = GameActivity_t.ACT_VM_RECOIL3 +ACT_VM_PICKUP = GameActivity_t.ACT_VM_PICKUP +ACT_VM_RELEASE = GameActivity_t.ACT_VM_RELEASE +ACT_VM_MAUL_LOOP = GameActivity_t.ACT_VM_MAUL_LOOP +ACT_VM_ATTACH_SILENCER = GameActivity_t.ACT_VM_ATTACH_SILENCER +ACT_VM_DETACH_SILENCER = GameActivity_t.ACT_VM_DETACH_SILENCER +ACT_SLAM_STICKWALL_IDLE = GameActivity_t.ACT_SLAM_STICKWALL_IDLE +ACT_SLAM_STICKWALL_ND_IDLE = GameActivity_t.ACT_SLAM_STICKWALL_ND_IDLE +ACT_SLAM_STICKWALL_ATTACH = GameActivity_t.ACT_SLAM_STICKWALL_ATTACH +ACT_SLAM_STICKWALL_ATTACH2 = GameActivity_t.ACT_SLAM_STICKWALL_ATTACH2 +ACT_SLAM_STICKWALL_ND_ATTACH = GameActivity_t.ACT_SLAM_STICKWALL_ND_ATTACH +ACT_SLAM_STICKWALL_ND_ATTACH2 = GameActivity_t.ACT_SLAM_STICKWALL_ND_ATTACH2 +ACT_SLAM_STICKWALL_DETONATE = GameActivity_t.ACT_SLAM_STICKWALL_DETONATE +ACT_SLAM_STICKWALL_DETONATOR_HOLSTER = GameActivity_t.ACT_SLAM_STICKWALL_DETONATOR_HOLSTER +ACT_SLAM_STICKWALL_DRAW = GameActivity_t.ACT_SLAM_STICKWALL_DRAW +ACT_SLAM_STICKWALL_ND_DRAW = GameActivity_t.ACT_SLAM_STICKWALL_ND_DRAW +ACT_SLAM_STICKWALL_TO_THROW = GameActivity_t.ACT_SLAM_STICKWALL_TO_THROW +ACT_SLAM_STICKWALL_TO_THROW_ND = GameActivity_t.ACT_SLAM_STICKWALL_TO_THROW_ND +ACT_SLAM_STICKWALL_TO_TRIPMINE_ND = GameActivity_t.ACT_SLAM_STICKWALL_TO_TRIPMINE_ND +ACT_SLAM_THROW_IDLE = GameActivity_t.ACT_SLAM_THROW_IDLE +ACT_SLAM_THROW_ND_IDLE = GameActivity_t.ACT_SLAM_THROW_ND_IDLE +ACT_SLAM_THROW_THROW = GameActivity_t.ACT_SLAM_THROW_THROW +ACT_SLAM_THROW_THROW2 = GameActivity_t.ACT_SLAM_THROW_THROW2 +ACT_SLAM_THROW_THROW_ND = GameActivity_t.ACT_SLAM_THROW_THROW_ND +ACT_SLAM_THROW_THROW_ND2 = GameActivity_t.ACT_SLAM_THROW_THROW_ND2 +ACT_SLAM_THROW_DRAW = GameActivity_t.ACT_SLAM_THROW_DRAW +ACT_SLAM_THROW_ND_DRAW = GameActivity_t.ACT_SLAM_THROW_ND_DRAW +ACT_SLAM_THROW_TO_STICKWALL = GameActivity_t.ACT_SLAM_THROW_TO_STICKWALL +ACT_SLAM_THROW_TO_STICKWALL_ND = GameActivity_t.ACT_SLAM_THROW_TO_STICKWALL_ND +ACT_SLAM_THROW_DETONATE = GameActivity_t.ACT_SLAM_THROW_DETONATE +ACT_SLAM_THROW_DETONATOR_HOLSTER = GameActivity_t.ACT_SLAM_THROW_DETONATOR_HOLSTER +ACT_SLAM_THROW_TO_TRIPMINE_ND = GameActivity_t.ACT_SLAM_THROW_TO_TRIPMINE_ND +ACT_SLAM_TRIPMINE_IDLE = GameActivity_t.ACT_SLAM_TRIPMINE_IDLE +ACT_SLAM_TRIPMINE_DRAW = GameActivity_t.ACT_SLAM_TRIPMINE_DRAW +ACT_SLAM_TRIPMINE_ATTACH = GameActivity_t.ACT_SLAM_TRIPMINE_ATTACH +ACT_SLAM_TRIPMINE_ATTACH2 = GameActivity_t.ACT_SLAM_TRIPMINE_ATTACH2 +ACT_SLAM_TRIPMINE_TO_STICKWALL_ND = GameActivity_t.ACT_SLAM_TRIPMINE_TO_STICKWALL_ND +ACT_SLAM_TRIPMINE_TO_THROW_ND = GameActivity_t.ACT_SLAM_TRIPMINE_TO_THROW_ND +ACT_SLAM_DETONATOR_IDLE = GameActivity_t.ACT_SLAM_DETONATOR_IDLE +ACT_SLAM_DETONATOR_DRAW = GameActivity_t.ACT_SLAM_DETONATOR_DRAW +ACT_SLAM_DETONATOR_DETONATE = GameActivity_t.ACT_SLAM_DETONATOR_DETONATE +ACT_SLAM_DETONATOR_HOLSTER = GameActivity_t.ACT_SLAM_DETONATOR_HOLSTER +ACT_SLAM_DETONATOR_STICKWALL_DRAW = GameActivity_t.ACT_SLAM_DETONATOR_STICKWALL_DRAW +ACT_SLAM_DETONATOR_THROW_DRAW = GameActivity_t.ACT_SLAM_DETONATOR_THROW_DRAW +ACT_SHOTGUN_RELOAD_START = GameActivity_t.ACT_SHOTGUN_RELOAD_START +ACT_SHOTGUN_RELOAD_FINISH = GameActivity_t.ACT_SHOTGUN_RELOAD_FINISH +ACT_SHOTGUN_PUMP = GameActivity_t.ACT_SHOTGUN_PUMP +ACT_SMG2_IDLE2 = GameActivity_t.ACT_SMG2_IDLE2 +ACT_SMG2_FIRE2 = GameActivity_t.ACT_SMG2_FIRE2 +ACT_SMG2_DRAW2 = GameActivity_t.ACT_SMG2_DRAW2 +ACT_SMG2_RELOAD2 = GameActivity_t.ACT_SMG2_RELOAD2 +ACT_SMG2_DRYFIRE2 = GameActivity_t.ACT_SMG2_DRYFIRE2 +ACT_SMG2_TOAUTO = GameActivity_t.ACT_SMG2_TOAUTO +ACT_SMG2_TOBURST = GameActivity_t.ACT_SMG2_TOBURST +ACT_PHYSCANNON_UPGRADE = GameActivity_t.ACT_PHYSCANNON_UPGRADE +ACT_RANGE_ATTACK_AR1 = GameActivity_t.ACT_RANGE_ATTACK_AR1 +ACT_RANGE_ATTACK_AR2 = GameActivity_t.ACT_RANGE_ATTACK_AR2 +ACT_RANGE_ATTACK_AR2_LOW = GameActivity_t.ACT_RANGE_ATTACK_AR2_LOW +ACT_RANGE_ATTACK_AR2_GRENADE = GameActivity_t.ACT_RANGE_ATTACK_AR2_GRENADE +ACT_RANGE_ATTACK_HMG1 = GameActivity_t.ACT_RANGE_ATTACK_HMG1 +ACT_RANGE_ATTACK_ML = GameActivity_t.ACT_RANGE_ATTACK_ML +ACT_RANGE_ATTACK_SMG1 = GameActivity_t.ACT_RANGE_ATTACK_SMG1 +ACT_RANGE_ATTACK_SMG1_LOW = GameActivity_t.ACT_RANGE_ATTACK_SMG1_LOW +ACT_RANGE_ATTACK_SMG2 = GameActivity_t.ACT_RANGE_ATTACK_SMG2 +ACT_RANGE_ATTACK_SHOTGUN = GameActivity_t.ACT_RANGE_ATTACK_SHOTGUN +ACT_RANGE_ATTACK_SHOTGUN_LOW = GameActivity_t.ACT_RANGE_ATTACK_SHOTGUN_LOW +ACT_RANGE_ATTACK_PISTOL = GameActivity_t.ACT_RANGE_ATTACK_PISTOL +ACT_RANGE_ATTACK_PISTOL_LOW = GameActivity_t.ACT_RANGE_ATTACK_PISTOL_LOW +ACT_RANGE_ATTACK_SLAM = GameActivity_t.ACT_RANGE_ATTACK_SLAM +ACT_RANGE_ATTACK_TRIPWIRE = GameActivity_t.ACT_RANGE_ATTACK_TRIPWIRE +ACT_RANGE_ATTACK_THROW = GameActivity_t.ACT_RANGE_ATTACK_THROW +ACT_RANGE_ATTACK_SNIPER_RIFLE = GameActivity_t.ACT_RANGE_ATTACK_SNIPER_RIFLE +ACT_RANGE_ATTACK_RPG = GameActivity_t.ACT_RANGE_ATTACK_RPG +ACT_MELEE_ATTACK_SWING = GameActivity_t.ACT_MELEE_ATTACK_SWING +ACT_RANGE_AIM_LOW = GameActivity_t.ACT_RANGE_AIM_LOW +ACT_RANGE_AIM_SMG1_LOW = GameActivity_t.ACT_RANGE_AIM_SMG1_LOW +ACT_RANGE_AIM_PISTOL_LOW = GameActivity_t.ACT_RANGE_AIM_PISTOL_LOW +ACT_RANGE_AIM_AR2_LOW = GameActivity_t.ACT_RANGE_AIM_AR2_LOW +ACT_COVER_PISTOL_LOW = GameActivity_t.ACT_COVER_PISTOL_LOW +ACT_COVER_SMG1_LOW = GameActivity_t.ACT_COVER_SMG1_LOW +ACT_GESTURE_RANGE_ATTACK_AR1 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_AR1 +ACT_GESTURE_RANGE_ATTACK_AR2 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_AR2 +ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE +ACT_GESTURE_RANGE_ATTACK_HMG1 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_HMG1 +ACT_GESTURE_RANGE_ATTACK_ML = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_ML +ACT_GESTURE_RANGE_ATTACK_SMG1 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_SMG1 +ACT_GESTURE_RANGE_ATTACK_SMG1_LOW = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_SMG1_LOW +ACT_GESTURE_RANGE_ATTACK_SMG2 = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_SMG2 +ACT_GESTURE_RANGE_ATTACK_SHOTGUN = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_SHOTGUN +ACT_GESTURE_RANGE_ATTACK_PISTOL = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_PISTOL +ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW +ACT_GESTURE_RANGE_ATTACK_SLAM = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_SLAM +ACT_GESTURE_RANGE_ATTACK_TRIPWIRE = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_TRIPWIRE +ACT_GESTURE_RANGE_ATTACK_THROW = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_THROW +ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE = GameActivity_t.ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE +ACT_GESTURE_MELEE_ATTACK_SWING = GameActivity_t.ACT_GESTURE_MELEE_ATTACK_SWING +ACT_IDLE_RIFLE = GameActivity_t.ACT_IDLE_RIFLE +ACT_IDLE_SMG1 = GameActivity_t.ACT_IDLE_SMG1 +ACT_IDLE_ANGRY_SMG1 = GameActivity_t.ACT_IDLE_ANGRY_SMG1 +ACT_IDLE_PISTOL = GameActivity_t.ACT_IDLE_PISTOL +ACT_IDLE_ANGRY_PISTOL = GameActivity_t.ACT_IDLE_ANGRY_PISTOL +ACT_IDLE_ANGRY_SHOTGUN = GameActivity_t.ACT_IDLE_ANGRY_SHOTGUN +ACT_IDLE_STEALTH_PISTOL = GameActivity_t.ACT_IDLE_STEALTH_PISTOL +ACT_IDLE_PACKAGE = GameActivity_t.ACT_IDLE_PACKAGE +ACT_WALK_PACKAGE = GameActivity_t.ACT_WALK_PACKAGE +ACT_IDLE_SUITCASE = GameActivity_t.ACT_IDLE_SUITCASE +ACT_WALK_SUITCASE = GameActivity_t.ACT_WALK_SUITCASE +ACT_IDLE_SMG1_RELAXED = GameActivity_t.ACT_IDLE_SMG1_RELAXED +ACT_IDLE_SMG1_STIMULATED = GameActivity_t.ACT_IDLE_SMG1_STIMULATED +ACT_WALK_RIFLE_RELAXED = GameActivity_t.ACT_WALK_RIFLE_RELAXED +ACT_RUN_RIFLE_RELAXED = GameActivity_t.ACT_RUN_RIFLE_RELAXED +ACT_WALK_RIFLE_STIMULATED = GameActivity_t.ACT_WALK_RIFLE_STIMULATED +ACT_RUN_RIFLE_STIMULATED = GameActivity_t.ACT_RUN_RIFLE_STIMULATED +ACT_IDLE_AIM_RIFLE_STIMULATED = GameActivity_t.ACT_IDLE_AIM_RIFLE_STIMULATED +ACT_WALK_AIM_RIFLE_STIMULATED = GameActivity_t.ACT_WALK_AIM_RIFLE_STIMULATED +ACT_RUN_AIM_RIFLE_STIMULATED = GameActivity_t.ACT_RUN_AIM_RIFLE_STIMULATED +ACT_IDLE_SHOTGUN_RELAXED = GameActivity_t.ACT_IDLE_SHOTGUN_RELAXED +ACT_IDLE_SHOTGUN_STIMULATED = GameActivity_t.ACT_IDLE_SHOTGUN_STIMULATED +ACT_IDLE_SHOTGUN_AGITATED = GameActivity_t.ACT_IDLE_SHOTGUN_AGITATED +ACT_WALK_ANGRY = GameActivity_t.ACT_WALK_ANGRY +ACT_POLICE_HARASS1 = GameActivity_t.ACT_POLICE_HARASS1 +ACT_POLICE_HARASS2 = GameActivity_t.ACT_POLICE_HARASS2 +ACT_IDLE_MANNEDGUN = GameActivity_t.ACT_IDLE_MANNEDGUN +ACT_IDLE_MELEE = GameActivity_t.ACT_IDLE_MELEE +ACT_IDLE_ANGRY_MELEE = GameActivity_t.ACT_IDLE_ANGRY_MELEE +ACT_IDLE_RPG_RELAXED = GameActivity_t.ACT_IDLE_RPG_RELAXED +ACT_IDLE_RPG = GameActivity_t.ACT_IDLE_RPG +ACT_IDLE_ANGRY_RPG = GameActivity_t.ACT_IDLE_ANGRY_RPG +ACT_COVER_LOW_RPG = GameActivity_t.ACT_COVER_LOW_RPG +ACT_WALK_RPG = GameActivity_t.ACT_WALK_RPG +ACT_RUN_RPG = GameActivity_t.ACT_RUN_RPG +ACT_WALK_CROUCH_RPG = GameActivity_t.ACT_WALK_CROUCH_RPG +ACT_RUN_CROUCH_RPG = GameActivity_t.ACT_RUN_CROUCH_RPG +ACT_WALK_RPG_RELAXED = GameActivity_t.ACT_WALK_RPG_RELAXED +ACT_RUN_RPG_RELAXED = GameActivity_t.ACT_RUN_RPG_RELAXED +ACT_WALK_RIFLE = GameActivity_t.ACT_WALK_RIFLE +ACT_WALK_AIM_RIFLE = GameActivity_t.ACT_WALK_AIM_RIFLE +ACT_WALK_CROUCH_RIFLE = GameActivity_t.ACT_WALK_CROUCH_RIFLE +ACT_WALK_CROUCH_AIM_RIFLE = GameActivity_t.ACT_WALK_CROUCH_AIM_RIFLE +ACT_RUN_RIFLE = GameActivity_t.ACT_RUN_RIFLE +ACT_RUN_AIM_RIFLE = GameActivity_t.ACT_RUN_AIM_RIFLE +ACT_RUN_CROUCH_RIFLE = GameActivity_t.ACT_RUN_CROUCH_RIFLE +ACT_RUN_CROUCH_AIM_RIFLE = GameActivity_t.ACT_RUN_CROUCH_AIM_RIFLE +ACT_RUN_STEALTH_PISTOL = GameActivity_t.ACT_RUN_STEALTH_PISTOL +ACT_WALK_AIM_SHOTGUN = GameActivity_t.ACT_WALK_AIM_SHOTGUN +ACT_RUN_AIM_SHOTGUN = GameActivity_t.ACT_RUN_AIM_SHOTGUN +ACT_WALK_PISTOL = GameActivity_t.ACT_WALK_PISTOL +ACT_RUN_PISTOL = GameActivity_t.ACT_RUN_PISTOL +ACT_WALK_AIM_PISTOL = GameActivity_t.ACT_WALK_AIM_PISTOL +ACT_RUN_AIM_PISTOL = GameActivity_t.ACT_RUN_AIM_PISTOL +ACT_WALK_STEALTH_PISTOL = GameActivity_t.ACT_WALK_STEALTH_PISTOL +ACT_WALK_AIM_STEALTH_PISTOL = GameActivity_t.ACT_WALK_AIM_STEALTH_PISTOL +ACT_RUN_AIM_STEALTH_PISTOL = GameActivity_t.ACT_RUN_AIM_STEALTH_PISTOL +ACT_RELOAD_PISTOL = GameActivity_t.ACT_RELOAD_PISTOL +ACT_RELOAD_PISTOL_LOW = GameActivity_t.ACT_RELOAD_PISTOL_LOW +ACT_RELOAD_SMG1 = GameActivity_t.ACT_RELOAD_SMG1 +ACT_RELOAD_SMG1_LOW = GameActivity_t.ACT_RELOAD_SMG1_LOW +ACT_RELOAD_SHOTGUN = GameActivity_t.ACT_RELOAD_SHOTGUN +ACT_RELOAD_SHOTGUN_LOW = GameActivity_t.ACT_RELOAD_SHOTGUN_LOW +ACT_GESTURE_RELOAD = GameActivity_t.ACT_GESTURE_RELOAD +ACT_GESTURE_RELOAD_PISTOL = GameActivity_t.ACT_GESTURE_RELOAD_PISTOL +ACT_GESTURE_RELOAD_SMG1 = GameActivity_t.ACT_GESTURE_RELOAD_SMG1 +ACT_GESTURE_RELOAD_SHOTGUN = GameActivity_t.ACT_GESTURE_RELOAD_SHOTGUN +ACT_BUSY_LEAN_LEFT = GameActivity_t.ACT_BUSY_LEAN_LEFT +ACT_BUSY_LEAN_LEFT_ENTRY = GameActivity_t.ACT_BUSY_LEAN_LEFT_ENTRY +ACT_BUSY_LEAN_LEFT_EXIT = GameActivity_t.ACT_BUSY_LEAN_LEFT_EXIT +ACT_BUSY_LEAN_BACK = GameActivity_t.ACT_BUSY_LEAN_BACK +ACT_BUSY_LEAN_BACK_ENTRY = GameActivity_t.ACT_BUSY_LEAN_BACK_ENTRY +ACT_BUSY_LEAN_BACK_EXIT = GameActivity_t.ACT_BUSY_LEAN_BACK_EXIT +ACT_BUSY_SIT_GROUND = GameActivity_t.ACT_BUSY_SIT_GROUND +ACT_BUSY_SIT_GROUND_ENTRY = GameActivity_t.ACT_BUSY_SIT_GROUND_ENTRY +ACT_BUSY_SIT_GROUND_EXIT = GameActivity_t.ACT_BUSY_SIT_GROUND_EXIT +ACT_BUSY_SIT_CHAIR = GameActivity_t.ACT_BUSY_SIT_CHAIR +ACT_BUSY_SIT_CHAIR_ENTRY = GameActivity_t.ACT_BUSY_SIT_CHAIR_ENTRY +ACT_BUSY_SIT_CHAIR_EXIT = GameActivity_t.ACT_BUSY_SIT_CHAIR_EXIT +ACT_BUSY_STAND = GameActivity_t.ACT_BUSY_STAND +ACT_BUSY_QUEUE = GameActivity_t.ACT_BUSY_QUEUE +ACT_DUCK_DODGE = GameActivity_t.ACT_DUCK_DODGE +ACT_DIE_BARNACLE_SWALLOW = GameActivity_t.ACT_DIE_BARNACLE_SWALLOW +ACT_GESTURE_BARNACLE_STRANGLE = GameActivity_t.ACT_GESTURE_BARNACLE_STRANGLE +ACT_DIE_FRONTSIDE = GameActivity_t.ACT_DIE_FRONTSIDE +ACT_DIE_RIGHTSIDE = GameActivity_t.ACT_DIE_RIGHTSIDE +ACT_DIE_BACKSIDE = GameActivity_t.ACT_DIE_BACKSIDE +ACT_DIE_LEFTSIDE = GameActivity_t.ACT_DIE_LEFTSIDE +ACT_DIE_CROUCH_FRONTSIDE = GameActivity_t.ACT_DIE_CROUCH_FRONTSIDE +ACT_DIE_CROUCH_RIGHTSIDE = GameActivity_t.ACT_DIE_CROUCH_RIGHTSIDE +ACT_DIE_CROUCH_BACKSIDE = GameActivity_t.ACT_DIE_CROUCH_BACKSIDE +ACT_DIE_CROUCH_LEFTSIDE = GameActivity_t.ACT_DIE_CROUCH_LEFTSIDE +ACT_DIE_INCAP = GameActivity_t.ACT_DIE_INCAP +ACT_DIE_STANDING = GameActivity_t.ACT_DIE_STANDING +ACT_OPEN_DOOR = GameActivity_t.ACT_OPEN_DOOR +ACT_DI_ALYX_ZOMBIE_MELEE = GameActivity_t.ACT_DI_ALYX_ZOMBIE_MELEE +ACT_DI_ALYX_ZOMBIE_TORSO_MELEE = GameActivity_t.ACT_DI_ALYX_ZOMBIE_TORSO_MELEE +ACT_DI_ALYX_HEADCRAB_MELEE = GameActivity_t.ACT_DI_ALYX_HEADCRAB_MELEE +ACT_DI_ALYX_ANTLION = GameActivity_t.ACT_DI_ALYX_ANTLION +ACT_DI_ALYX_ZOMBIE_SHOTGUN64 = GameActivity_t.ACT_DI_ALYX_ZOMBIE_SHOTGUN64 +ACT_DI_ALYX_ZOMBIE_SHOTGUN26 = GameActivity_t.ACT_DI_ALYX_ZOMBIE_SHOTGUN26 +ACT_READINESS_RELAXED_TO_STIMULATED = GameActivity_t.ACT_READINESS_RELAXED_TO_STIMULATED +ACT_READINESS_RELAXED_TO_STIMULATED_WALK = GameActivity_t.ACT_READINESS_RELAXED_TO_STIMULATED_WALK +ACT_READINESS_AGITATED_TO_STIMULATED = GameActivity_t.ACT_READINESS_AGITATED_TO_STIMULATED +ACT_READINESS_STIMULATED_TO_RELAXED = GameActivity_t.ACT_READINESS_STIMULATED_TO_RELAXED +ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED = GameActivity_t.ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED +ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK = GameActivity_t.ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK +ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED = GameActivity_t.ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED +ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED = GameActivity_t.ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED +ACT_IDLE_CARRY = GameActivity_t.ACT_IDLE_CARRY +ACT_WALK_CARRY = GameActivity_t.ACT_WALK_CARRY +ACT_STARTDYING = GameActivity_t.ACT_STARTDYING +ACT_DYINGLOOP = GameActivity_t.ACT_DYINGLOOP +ACT_DYINGTODEAD = GameActivity_t.ACT_DYINGTODEAD +ACT_RIDE_MANNED_GUN = GameActivity_t.ACT_RIDE_MANNED_GUN +ACT_VM_SPRINT_ENTER = GameActivity_t.ACT_VM_SPRINT_ENTER +ACT_VM_SPRINT_IDLE = GameActivity_t.ACT_VM_SPRINT_IDLE +ACT_VM_SPRINT_LEAVE = GameActivity_t.ACT_VM_SPRINT_LEAVE +ACT_FIRE_START = GameActivity_t.ACT_FIRE_START +ACT_FIRE_LOOP = GameActivity_t.ACT_FIRE_LOOP +ACT_FIRE_END = GameActivity_t.ACT_FIRE_END +ACT_CROUCHING_GRENADEIDLE = GameActivity_t.ACT_CROUCHING_GRENADEIDLE +ACT_CROUCHING_GRENADEREADY = GameActivity_t.ACT_CROUCHING_GRENADEREADY +ACT_CROUCHING_PRIMARYATTACK = GameActivity_t.ACT_CROUCHING_PRIMARYATTACK +ACT_OVERLAY_GRENADEIDLE = GameActivity_t.ACT_OVERLAY_GRENADEIDLE +ACT_OVERLAY_GRENADEREADY = GameActivity_t.ACT_OVERLAY_GRENADEREADY +ACT_OVERLAY_PRIMARYATTACK = GameActivity_t.ACT_OVERLAY_PRIMARYATTACK +ACT_OVERLAY_SHIELD_UP = GameActivity_t.ACT_OVERLAY_SHIELD_UP +ACT_OVERLAY_SHIELD_DOWN = GameActivity_t.ACT_OVERLAY_SHIELD_DOWN +ACT_OVERLAY_SHIELD_UP_IDLE = GameActivity_t.ACT_OVERLAY_SHIELD_UP_IDLE +ACT_OVERLAY_SHIELD_ATTACK = GameActivity_t.ACT_OVERLAY_SHIELD_ATTACK +ACT_OVERLAY_SHIELD_KNOCKBACK = GameActivity_t.ACT_OVERLAY_SHIELD_KNOCKBACK +ACT_SHIELD_UP = GameActivity_t.ACT_SHIELD_UP +ACT_SHIELD_DOWN = GameActivity_t.ACT_SHIELD_DOWN +ACT_SHIELD_UP_IDLE = GameActivity_t.ACT_SHIELD_UP_IDLE +ACT_SHIELD_ATTACK = GameActivity_t.ACT_SHIELD_ATTACK +ACT_SHIELD_KNOCKBACK = GameActivity_t.ACT_SHIELD_KNOCKBACK +ACT_CROUCHING_SHIELD_UP = GameActivity_t.ACT_CROUCHING_SHIELD_UP +ACT_CROUCHING_SHIELD_DOWN = GameActivity_t.ACT_CROUCHING_SHIELD_DOWN +ACT_CROUCHING_SHIELD_UP_IDLE = GameActivity_t.ACT_CROUCHING_SHIELD_UP_IDLE +ACT_CROUCHING_SHIELD_ATTACK = GameActivity_t.ACT_CROUCHING_SHIELD_ATTACK +ACT_CROUCHING_SHIELD_KNOCKBACK = GameActivity_t.ACT_CROUCHING_SHIELD_KNOCKBACK +ACT_TURNRIGHT45 = GameActivity_t.ACT_TURNRIGHT45 +ACT_TURNLEFT45 = GameActivity_t.ACT_TURNLEFT45 +ACT_TURN = GameActivity_t.ACT_TURN +ACT_OBJ_ASSEMBLING = GameActivity_t.ACT_OBJ_ASSEMBLING +ACT_OBJ_DISMANTLING = GameActivity_t.ACT_OBJ_DISMANTLING +ACT_OBJ_STARTUP = GameActivity_t.ACT_OBJ_STARTUP +ACT_OBJ_RUNNING = GameActivity_t.ACT_OBJ_RUNNING +ACT_OBJ_IDLE = GameActivity_t.ACT_OBJ_IDLE +ACT_OBJ_PLACING = GameActivity_t.ACT_OBJ_PLACING +ACT_OBJ_DETERIORATING = GameActivity_t.ACT_OBJ_DETERIORATING +ACT_OBJ_UPGRADING = GameActivity_t.ACT_OBJ_UPGRADING +ACT_DEPLOY = GameActivity_t.ACT_DEPLOY +ACT_DEPLOY_IDLE = GameActivity_t.ACT_DEPLOY_IDLE +ACT_UNDEPLOY = GameActivity_t.ACT_UNDEPLOY +ACT_CROSSBOW_DRAW_UNLOADED = GameActivity_t.ACT_CROSSBOW_DRAW_UNLOADED +ACT_GAUSS_SPINUP = GameActivity_t.ACT_GAUSS_SPINUP +ACT_GAUSS_SPINCYCLE = GameActivity_t.ACT_GAUSS_SPINCYCLE +ACT_VM_PRIMARYATTACK_SILENCED = GameActivity_t.ACT_VM_PRIMARYATTACK_SILENCED +ACT_VM_RELOAD_SILENCED = GameActivity_t.ACT_VM_RELOAD_SILENCED +ACT_VM_DRYFIRE_SILENCED = GameActivity_t.ACT_VM_DRYFIRE_SILENCED +ACT_VM_IDLE_SILENCED = GameActivity_t.ACT_VM_IDLE_SILENCED +ACT_VM_DRAW_SILENCED = GameActivity_t.ACT_VM_DRAW_SILENCED +ACT_VM_IDLE_EMPTY_LEFT = GameActivity_t.ACT_VM_IDLE_EMPTY_LEFT +ACT_VM_DRYFIRE_LEFT = GameActivity_t.ACT_VM_DRYFIRE_LEFT +ACT_VM_IS_DRAW = GameActivity_t.ACT_VM_IS_DRAW +ACT_VM_IS_HOLSTER = GameActivity_t.ACT_VM_IS_HOLSTER +ACT_VM_IS_IDLE = GameActivity_t.ACT_VM_IS_IDLE +ACT_VM_IS_PRIMARYATTACK = GameActivity_t.ACT_VM_IS_PRIMARYATTACK +ACT_PLAYER_IDLE_FIRE = GameActivity_t.ACT_PLAYER_IDLE_FIRE +ACT_PLAYER_CROUCH_FIRE = GameActivity_t.ACT_PLAYER_CROUCH_FIRE +ACT_PLAYER_CROUCH_WALK_FIRE = GameActivity_t.ACT_PLAYER_CROUCH_WALK_FIRE +ACT_PLAYER_WALK_FIRE = GameActivity_t.ACT_PLAYER_WALK_FIRE +ACT_PLAYER_RUN_FIRE = GameActivity_t.ACT_PLAYER_RUN_FIRE +ACT_IDLETORUN = GameActivity_t.ACT_IDLETORUN +ACT_RUNTOIDLE = GameActivity_t.ACT_RUNTOIDLE +ACT_VM_DRAW_DEPLOYED = GameActivity_t.ACT_VM_DRAW_DEPLOYED +ACT_HL2MP_IDLE_MELEE = GameActivity_t.ACT_HL2MP_IDLE_MELEE +ACT_HL2MP_RUN_MELEE = GameActivity_t.ACT_HL2MP_RUN_MELEE +ACT_HL2MP_IDLE_CROUCH_MELEE = GameActivity_t.ACT_HL2MP_IDLE_CROUCH_MELEE +ACT_HL2MP_WALK_CROUCH_MELEE = GameActivity_t.ACT_HL2MP_WALK_CROUCH_MELEE +ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE = GameActivity_t.ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE +ACT_HL2MP_GESTURE_RELOAD_MELEE = GameActivity_t.ACT_HL2MP_GESTURE_RELOAD_MELEE +ACT_HL2MP_JUMP_MELEE = GameActivity_t.ACT_HL2MP_JUMP_MELEE +ACT_MP_STAND_IDLE = GameActivity_t.ACT_MP_STAND_IDLE +ACT_MP_CROUCH_IDLE = GameActivity_t.ACT_MP_CROUCH_IDLE +ACT_MP_CROUCH_DEPLOYED_IDLE = GameActivity_t.ACT_MP_CROUCH_DEPLOYED_IDLE +ACT_MP_CROUCH_DEPLOYED = GameActivity_t.ACT_MP_CROUCH_DEPLOYED +ACT_MP_DEPLOYED_IDLE = GameActivity_t.ACT_MP_DEPLOYED_IDLE +ACT_MP_RUN = GameActivity_t.ACT_MP_RUN +ACT_MP_WALK = GameActivity_t.ACT_MP_WALK +ACT_MP_AIRWALK = GameActivity_t.ACT_MP_AIRWALK +ACT_MP_CROUCHWALK = GameActivity_t.ACT_MP_CROUCHWALK +ACT_MP_SPRINT = GameActivity_t.ACT_MP_SPRINT +ACT_MP_JUMP = GameActivity_t.ACT_MP_JUMP +ACT_MP_JUMP_START = GameActivity_t.ACT_MP_JUMP_START +ACT_MP_JUMP_FLOAT = GameActivity_t.ACT_MP_JUMP_FLOAT +ACT_MP_JUMP_LAND = GameActivity_t.ACT_MP_JUMP_LAND +ACT_MP_DOUBLEJUMP = GameActivity_t.ACT_MP_DOUBLEJUMP +ACT_MP_SWIM = GameActivity_t.ACT_MP_SWIM +ACT_MP_DEPLOYED = GameActivity_t.ACT_MP_DEPLOYED +ACT_MP_SWIM_DEPLOYED = GameActivity_t.ACT_MP_SWIM_DEPLOYED +ACT_MP_VCD = GameActivity_t.ACT_MP_VCD +ACT_MP_ATTACK_STAND_PRIMARYFIRE = GameActivity_t.ACT_MP_ATTACK_STAND_PRIMARYFIRE +ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED = GameActivity_t.ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED +ACT_MP_ATTACK_STAND_SECONDARYFIRE = GameActivity_t.ACT_MP_ATTACK_STAND_SECONDARYFIRE +ACT_MP_ATTACK_STAND_GRENADE = GameActivity_t.ACT_MP_ATTACK_STAND_GRENADE +ACT_MP_ATTACK_CROUCH_PRIMARYFIRE = GameActivity_t.ACT_MP_ATTACK_CROUCH_PRIMARYFIRE +ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED = GameActivity_t.ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED +ACT_MP_ATTACK_CROUCH_SECONDARYFIRE = GameActivity_t.ACT_MP_ATTACK_CROUCH_SECONDARYFIRE +ACT_MP_ATTACK_CROUCH_GRENADE = GameActivity_t.ACT_MP_ATTACK_CROUCH_GRENADE +ACT_MP_ATTACK_SWIM_PRIMARYFIRE = GameActivity_t.ACT_MP_ATTACK_SWIM_PRIMARYFIRE +ACT_MP_ATTACK_SWIM_SECONDARYFIRE = GameActivity_t.ACT_MP_ATTACK_SWIM_SECONDARYFIRE +ACT_MP_ATTACK_SWIM_GRENADE = GameActivity_t.ACT_MP_ATTACK_SWIM_GRENADE +ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE = GameActivity_t.ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE +ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE = GameActivity_t.ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE +ACT_MP_ATTACK_AIRWALK_GRENADE = GameActivity_t.ACT_MP_ATTACK_AIRWALK_GRENADE +ACT_MP_RELOAD_STAND = GameActivity_t.ACT_MP_RELOAD_STAND +ACT_MP_RELOAD_STAND_LOOP = GameActivity_t.ACT_MP_RELOAD_STAND_LOOP +ACT_MP_RELOAD_STAND_END = GameActivity_t.ACT_MP_RELOAD_STAND_END +ACT_MP_RELOAD_CROUCH = GameActivity_t.ACT_MP_RELOAD_CROUCH +ACT_MP_RELOAD_CROUCH_LOOP = GameActivity_t.ACT_MP_RELOAD_CROUCH_LOOP +ACT_MP_RELOAD_CROUCH_END = GameActivity_t.ACT_MP_RELOAD_CROUCH_END +ACT_MP_RELOAD_SWIM = GameActivity_t.ACT_MP_RELOAD_SWIM +ACT_MP_RELOAD_SWIM_LOOP = GameActivity_t.ACT_MP_RELOAD_SWIM_LOOP +ACT_MP_RELOAD_SWIM_END = GameActivity_t.ACT_MP_RELOAD_SWIM_END +ACT_MP_RELOAD_AIRWALK = GameActivity_t.ACT_MP_RELOAD_AIRWALK +ACT_MP_RELOAD_AIRWALK_LOOP = GameActivity_t.ACT_MP_RELOAD_AIRWALK_LOOP +ACT_MP_RELOAD_AIRWALK_END = GameActivity_t.ACT_MP_RELOAD_AIRWALK_END +ACT_MP_ATTACK_STAND_PREFIRE = GameActivity_t.ACT_MP_ATTACK_STAND_PREFIRE +ACT_MP_ATTACK_STAND_POSTFIRE = GameActivity_t.ACT_MP_ATTACK_STAND_POSTFIRE +ACT_MP_ATTACK_STAND_STARTFIRE = GameActivity_t.ACT_MP_ATTACK_STAND_STARTFIRE +ACT_MP_ATTACK_CROUCH_PREFIRE = GameActivity_t.ACT_MP_ATTACK_CROUCH_PREFIRE +ACT_MP_ATTACK_CROUCH_POSTFIRE = GameActivity_t.ACT_MP_ATTACK_CROUCH_POSTFIRE +ACT_MP_ATTACK_SWIM_PREFIRE = GameActivity_t.ACT_MP_ATTACK_SWIM_PREFIRE +ACT_MP_ATTACK_SWIM_POSTFIRE = GameActivity_t.ACT_MP_ATTACK_SWIM_POSTFIRE +ACT_MP_STAND_PRIMARY = GameActivity_t.ACT_MP_STAND_PRIMARY +ACT_MP_CROUCH_PRIMARY = GameActivity_t.ACT_MP_CROUCH_PRIMARY +ACT_MP_RUN_PRIMARY = GameActivity_t.ACT_MP_RUN_PRIMARY +ACT_MP_WALK_PRIMARY = GameActivity_t.ACT_MP_WALK_PRIMARY +ACT_MP_AIRWALK_PRIMARY = GameActivity_t.ACT_MP_AIRWALK_PRIMARY +ACT_MP_CROUCHWALK_PRIMARY = GameActivity_t.ACT_MP_CROUCHWALK_PRIMARY +ACT_MP_JUMP_PRIMARY = GameActivity_t.ACT_MP_JUMP_PRIMARY +ACT_MP_JUMP_START_PRIMARY = GameActivity_t.ACT_MP_JUMP_START_PRIMARY +ACT_MP_JUMP_FLOAT_PRIMARY = GameActivity_t.ACT_MP_JUMP_FLOAT_PRIMARY +ACT_MP_JUMP_LAND_PRIMARY = GameActivity_t.ACT_MP_JUMP_LAND_PRIMARY +ACT_MP_SWIM_PRIMARY = GameActivity_t.ACT_MP_SWIM_PRIMARY +ACT_MP_DEPLOYED_PRIMARY = GameActivity_t.ACT_MP_DEPLOYED_PRIMARY +ACT_MP_SWIM_DEPLOYED_PRIMARY = GameActivity_t.ACT_MP_SWIM_DEPLOYED_PRIMARY +ACT_MP_ATTACK_STAND_PRIMARY = GameActivity_t.ACT_MP_ATTACK_STAND_PRIMARY +ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED = GameActivity_t.ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED +ACT_MP_ATTACK_CROUCH_PRIMARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_PRIMARY +ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED = GameActivity_t.ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED +ACT_MP_ATTACK_SWIM_PRIMARY = GameActivity_t.ACT_MP_ATTACK_SWIM_PRIMARY +ACT_MP_ATTACK_AIRWALK_PRIMARY = GameActivity_t.ACT_MP_ATTACK_AIRWALK_PRIMARY +ACT_MP_RELOAD_STAND_PRIMARY = GameActivity_t.ACT_MP_RELOAD_STAND_PRIMARY +ACT_MP_RELOAD_STAND_PRIMARY_LOOP = GameActivity_t.ACT_MP_RELOAD_STAND_PRIMARY_LOOP +ACT_MP_RELOAD_STAND_PRIMARY_END = GameActivity_t.ACT_MP_RELOAD_STAND_PRIMARY_END +ACT_MP_RELOAD_CROUCH_PRIMARY = GameActivity_t.ACT_MP_RELOAD_CROUCH_PRIMARY +ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP = GameActivity_t.ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP +ACT_MP_RELOAD_CROUCH_PRIMARY_END = GameActivity_t.ACT_MP_RELOAD_CROUCH_PRIMARY_END +ACT_MP_RELOAD_SWIM_PRIMARY = GameActivity_t.ACT_MP_RELOAD_SWIM_PRIMARY +ACT_MP_RELOAD_SWIM_PRIMARY_LOOP = GameActivity_t.ACT_MP_RELOAD_SWIM_PRIMARY_LOOP +ACT_MP_RELOAD_SWIM_PRIMARY_END = GameActivity_t.ACT_MP_RELOAD_SWIM_PRIMARY_END +ACT_MP_RELOAD_AIRWALK_PRIMARY = GameActivity_t.ACT_MP_RELOAD_AIRWALK_PRIMARY +ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP = GameActivity_t.ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP +ACT_MP_RELOAD_AIRWALK_PRIMARY_END = GameActivity_t.ACT_MP_RELOAD_AIRWALK_PRIMARY_END +ACT_MP_ATTACK_STAND_GRENADE_PRIMARY = GameActivity_t.ACT_MP_ATTACK_STAND_GRENADE_PRIMARY +ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY +ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY = GameActivity_t.ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY +ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY = GameActivity_t.ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY +ACT_MP_STAND_SECONDARY = GameActivity_t.ACT_MP_STAND_SECONDARY +ACT_MP_CROUCH_SECONDARY = GameActivity_t.ACT_MP_CROUCH_SECONDARY +ACT_MP_RUN_SECONDARY = GameActivity_t.ACT_MP_RUN_SECONDARY +ACT_MP_WALK_SECONDARY = GameActivity_t.ACT_MP_WALK_SECONDARY +ACT_MP_AIRWALK_SECONDARY = GameActivity_t.ACT_MP_AIRWALK_SECONDARY +ACT_MP_CROUCHWALK_SECONDARY = GameActivity_t.ACT_MP_CROUCHWALK_SECONDARY +ACT_MP_JUMP_SECONDARY = GameActivity_t.ACT_MP_JUMP_SECONDARY +ACT_MP_JUMP_START_SECONDARY = GameActivity_t.ACT_MP_JUMP_START_SECONDARY +ACT_MP_JUMP_FLOAT_SECONDARY = GameActivity_t.ACT_MP_JUMP_FLOAT_SECONDARY +ACT_MP_JUMP_LAND_SECONDARY = GameActivity_t.ACT_MP_JUMP_LAND_SECONDARY +ACT_MP_SWIM_SECONDARY = GameActivity_t.ACT_MP_SWIM_SECONDARY +ACT_MP_ATTACK_STAND_SECONDARY = GameActivity_t.ACT_MP_ATTACK_STAND_SECONDARY +ACT_MP_ATTACK_CROUCH_SECONDARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_SECONDARY +ACT_MP_ATTACK_SWIM_SECONDARY = GameActivity_t.ACT_MP_ATTACK_SWIM_SECONDARY +ACT_MP_ATTACK_AIRWALK_SECONDARY = GameActivity_t.ACT_MP_ATTACK_AIRWALK_SECONDARY +ACT_MP_RELOAD_STAND_SECONDARY = GameActivity_t.ACT_MP_RELOAD_STAND_SECONDARY +ACT_MP_RELOAD_STAND_SECONDARY_LOOP = GameActivity_t.ACT_MP_RELOAD_STAND_SECONDARY_LOOP +ACT_MP_RELOAD_STAND_SECONDARY_END = GameActivity_t.ACT_MP_RELOAD_STAND_SECONDARY_END +ACT_MP_RELOAD_CROUCH_SECONDARY = GameActivity_t.ACT_MP_RELOAD_CROUCH_SECONDARY +ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP = GameActivity_t.ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP +ACT_MP_RELOAD_CROUCH_SECONDARY_END = GameActivity_t.ACT_MP_RELOAD_CROUCH_SECONDARY_END +ACT_MP_RELOAD_SWIM_SECONDARY = GameActivity_t.ACT_MP_RELOAD_SWIM_SECONDARY +ACT_MP_RELOAD_SWIM_SECONDARY_LOOP = GameActivity_t.ACT_MP_RELOAD_SWIM_SECONDARY_LOOP +ACT_MP_RELOAD_SWIM_SECONDARY_END = GameActivity_t.ACT_MP_RELOAD_SWIM_SECONDARY_END +ACT_MP_RELOAD_AIRWALK_SECONDARY = GameActivity_t.ACT_MP_RELOAD_AIRWALK_SECONDARY +ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP = GameActivity_t.ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP +ACT_MP_RELOAD_AIRWALK_SECONDARY_END = GameActivity_t.ACT_MP_RELOAD_AIRWALK_SECONDARY_END +ACT_MP_ATTACK_STAND_GRENADE_SECONDARY = GameActivity_t.ACT_MP_ATTACK_STAND_GRENADE_SECONDARY +ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY +ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY = GameActivity_t.ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY +ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY = GameActivity_t.ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY +ACT_MP_STAND_MELEE = GameActivity_t.ACT_MP_STAND_MELEE +ACT_MP_CROUCH_MELEE = GameActivity_t.ACT_MP_CROUCH_MELEE +ACT_MP_RUN_MELEE = GameActivity_t.ACT_MP_RUN_MELEE +ACT_MP_WALK_MELEE = GameActivity_t.ACT_MP_WALK_MELEE +ACT_MP_AIRWALK_MELEE = GameActivity_t.ACT_MP_AIRWALK_MELEE +ACT_MP_CROUCHWALK_MELEE = GameActivity_t.ACT_MP_CROUCHWALK_MELEE +ACT_MP_JUMP_MELEE = GameActivity_t.ACT_MP_JUMP_MELEE +ACT_MP_JUMP_START_MELEE = GameActivity_t.ACT_MP_JUMP_START_MELEE +ACT_MP_JUMP_FLOAT_MELEE = GameActivity_t.ACT_MP_JUMP_FLOAT_MELEE +ACT_MP_JUMP_LAND_MELEE = GameActivity_t.ACT_MP_JUMP_LAND_MELEE +ACT_MP_SWIM_MELEE = GameActivity_t.ACT_MP_SWIM_MELEE +ACT_MP_ATTACK_STAND_MELEE = GameActivity_t.ACT_MP_ATTACK_STAND_MELEE +ACT_MP_ATTACK_STAND_MELEE_SECONDARY = GameActivity_t.ACT_MP_ATTACK_STAND_MELEE_SECONDARY +ACT_MP_ATTACK_CROUCH_MELEE = GameActivity_t.ACT_MP_ATTACK_CROUCH_MELEE +ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY +ACT_MP_ATTACK_SWIM_MELEE = GameActivity_t.ACT_MP_ATTACK_SWIM_MELEE +ACT_MP_ATTACK_AIRWALK_MELEE = GameActivity_t.ACT_MP_ATTACK_AIRWALK_MELEE +ACT_MP_ATTACK_STAND_GRENADE_MELEE = GameActivity_t.ACT_MP_ATTACK_STAND_GRENADE_MELEE +ACT_MP_ATTACK_CROUCH_GRENADE_MELEE = GameActivity_t.ACT_MP_ATTACK_CROUCH_GRENADE_MELEE +ACT_MP_ATTACK_SWIM_GRENADE_MELEE = GameActivity_t.ACT_MP_ATTACK_SWIM_GRENADE_MELEE +ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE = GameActivity_t.ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE +ACT_MP_STAND_ITEM1 = GameActivity_t.ACT_MP_STAND_ITEM1 +ACT_MP_CROUCH_ITEM1 = GameActivity_t.ACT_MP_CROUCH_ITEM1 +ACT_MP_RUN_ITEM1 = GameActivity_t.ACT_MP_RUN_ITEM1 +ACT_MP_WALK_ITEM1 = GameActivity_t.ACT_MP_WALK_ITEM1 +ACT_MP_AIRWALK_ITEM1 = GameActivity_t.ACT_MP_AIRWALK_ITEM1 +ACT_MP_CROUCHWALK_ITEM1 = GameActivity_t.ACT_MP_CROUCHWALK_ITEM1 +ACT_MP_JUMP_ITEM1 = GameActivity_t.ACT_MP_JUMP_ITEM1 +ACT_MP_JUMP_START_ITEM1 = GameActivity_t.ACT_MP_JUMP_START_ITEM1 +ACT_MP_JUMP_FLOAT_ITEM1 = GameActivity_t.ACT_MP_JUMP_FLOAT_ITEM1 +ACT_MP_JUMP_LAND_ITEM1 = GameActivity_t.ACT_MP_JUMP_LAND_ITEM1 +ACT_MP_SWIM_ITEM1 = GameActivity_t.ACT_MP_SWIM_ITEM1 +ACT_MP_ATTACK_STAND_ITEM1 = GameActivity_t.ACT_MP_ATTACK_STAND_ITEM1 +ACT_MP_ATTACK_STAND_ITEM1_SECONDARY = GameActivity_t.ACT_MP_ATTACK_STAND_ITEM1_SECONDARY +ACT_MP_ATTACK_CROUCH_ITEM1 = GameActivity_t.ACT_MP_ATTACK_CROUCH_ITEM1 +ACT_MP_ATTACK_CROUCH_ITEM1_SECONDARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_ITEM1_SECONDARY +ACT_MP_ATTACK_SWIM_ITEM1 = GameActivity_t.ACT_MP_ATTACK_SWIM_ITEM1 +ACT_MP_ATTACK_AIRWALK_ITEM1 = GameActivity_t.ACT_MP_ATTACK_AIRWALK_ITEM1 +ACT_MP_STAND_ITEM2 = GameActivity_t.ACT_MP_STAND_ITEM2 +ACT_MP_CROUCH_ITEM2 = GameActivity_t.ACT_MP_CROUCH_ITEM2 +ACT_MP_RUN_ITEM2 = GameActivity_t.ACT_MP_RUN_ITEM2 +ACT_MP_WALK_ITEM2 = GameActivity_t.ACT_MP_WALK_ITEM2 +ACT_MP_AIRWALK_ITEM2 = GameActivity_t.ACT_MP_AIRWALK_ITEM2 +ACT_MP_CROUCHWALK_ITEM2 = GameActivity_t.ACT_MP_CROUCHWALK_ITEM2 +ACT_MP_JUMP_ITEM2 = GameActivity_t.ACT_MP_JUMP_ITEM2 +ACT_MP_JUMP_START_ITEM2 = GameActivity_t.ACT_MP_JUMP_START_ITEM2 +ACT_MP_JUMP_FLOAT_ITEM2 = GameActivity_t.ACT_MP_JUMP_FLOAT_ITEM2 +ACT_MP_JUMP_LAND_ITEM2 = GameActivity_t.ACT_MP_JUMP_LAND_ITEM2 +ACT_MP_SWIM_ITEM2 = GameActivity_t.ACT_MP_SWIM_ITEM2 +ACT_MP_ATTACK_STAND_ITEM2 = GameActivity_t.ACT_MP_ATTACK_STAND_ITEM2 +ACT_MP_ATTACK_STAND_ITEM2_SECONDARY = GameActivity_t.ACT_MP_ATTACK_STAND_ITEM2_SECONDARY +ACT_MP_ATTACK_CROUCH_ITEM2 = GameActivity_t.ACT_MP_ATTACK_CROUCH_ITEM2 +ACT_MP_ATTACK_CROUCH_ITEM2_SECONDARY = GameActivity_t.ACT_MP_ATTACK_CROUCH_ITEM2_SECONDARY +ACT_MP_ATTACK_SWIM_ITEM2 = GameActivity_t.ACT_MP_ATTACK_SWIM_ITEM2 +ACT_MP_ATTACK_AIRWALK_ITEM2 = GameActivity_t.ACT_MP_ATTACK_AIRWALK_ITEM2 +ACT_MP_GESTURE_FLINCH = GameActivity_t.ACT_MP_GESTURE_FLINCH +ACT_MP_GESTURE_FLINCH_PRIMARY = GameActivity_t.ACT_MP_GESTURE_FLINCH_PRIMARY +ACT_MP_GESTURE_FLINCH_SECONDARY = GameActivity_t.ACT_MP_GESTURE_FLINCH_SECONDARY +ACT_MP_GESTURE_FLINCH_MELEE = GameActivity_t.ACT_MP_GESTURE_FLINCH_MELEE +ACT_MP_GESTURE_FLINCH_ITEM1 = GameActivity_t.ACT_MP_GESTURE_FLINCH_ITEM1 +ACT_MP_GESTURE_FLINCH_ITEM2 = GameActivity_t.ACT_MP_GESTURE_FLINCH_ITEM2 +ACT_MP_GESTURE_FLINCH_HEAD = GameActivity_t.ACT_MP_GESTURE_FLINCH_HEAD +ACT_MP_GESTURE_FLINCH_CHEST = GameActivity_t.ACT_MP_GESTURE_FLINCH_CHEST +ACT_MP_GESTURE_FLINCH_STOMACH = GameActivity_t.ACT_MP_GESTURE_FLINCH_STOMACH +ACT_MP_GESTURE_FLINCH_LEFTARM = GameActivity_t.ACT_MP_GESTURE_FLINCH_LEFTARM +ACT_MP_GESTURE_FLINCH_RIGHTARM = GameActivity_t.ACT_MP_GESTURE_FLINCH_RIGHTARM +ACT_MP_GESTURE_FLINCH_LEFTLEG = GameActivity_t.ACT_MP_GESTURE_FLINCH_LEFTLEG +ACT_MP_GESTURE_FLINCH_RIGHTLEG = GameActivity_t.ACT_MP_GESTURE_FLINCH_RIGHTLEG +ACT_MP_GRENADE1_DRAW = GameActivity_t.ACT_MP_GRENADE1_DRAW +ACT_MP_GRENADE1_IDLE = GameActivity_t.ACT_MP_GRENADE1_IDLE +ACT_MP_GRENADE1_ATTACK = GameActivity_t.ACT_MP_GRENADE1_ATTACK +ACT_MP_GRENADE2_DRAW = GameActivity_t.ACT_MP_GRENADE2_DRAW +ACT_MP_GRENADE2_IDLE = GameActivity_t.ACT_MP_GRENADE2_IDLE +ACT_MP_GRENADE2_ATTACK = GameActivity_t.ACT_MP_GRENADE2_ATTACK +ACT_MP_PRIMARY_GRENADE1_DRAW = GameActivity_t.ACT_MP_PRIMARY_GRENADE1_DRAW +ACT_MP_PRIMARY_GRENADE1_IDLE = GameActivity_t.ACT_MP_PRIMARY_GRENADE1_IDLE +ACT_MP_PRIMARY_GRENADE1_ATTACK = GameActivity_t.ACT_MP_PRIMARY_GRENADE1_ATTACK +ACT_MP_PRIMARY_GRENADE2_DRAW = GameActivity_t.ACT_MP_PRIMARY_GRENADE2_DRAW +ACT_MP_PRIMARY_GRENADE2_IDLE = GameActivity_t.ACT_MP_PRIMARY_GRENADE2_IDLE +ACT_MP_PRIMARY_GRENADE2_ATTACK = GameActivity_t.ACT_MP_PRIMARY_GRENADE2_ATTACK +ACT_MP_SECONDARY_GRENADE1_DRAW = GameActivity_t.ACT_MP_SECONDARY_GRENADE1_DRAW +ACT_MP_SECONDARY_GRENADE1_IDLE = GameActivity_t.ACT_MP_SECONDARY_GRENADE1_IDLE +ACT_MP_SECONDARY_GRENADE1_ATTACK = GameActivity_t.ACT_MP_SECONDARY_GRENADE1_ATTACK +ACT_MP_SECONDARY_GRENADE2_DRAW = GameActivity_t.ACT_MP_SECONDARY_GRENADE2_DRAW +ACT_MP_SECONDARY_GRENADE2_IDLE = GameActivity_t.ACT_MP_SECONDARY_GRENADE2_IDLE +ACT_MP_SECONDARY_GRENADE2_ATTACK = GameActivity_t.ACT_MP_SECONDARY_GRENADE2_ATTACK +ACT_MP_MELEE_GRENADE1_DRAW = GameActivity_t.ACT_MP_MELEE_GRENADE1_DRAW +ACT_MP_MELEE_GRENADE1_IDLE = GameActivity_t.ACT_MP_MELEE_GRENADE1_IDLE +ACT_MP_MELEE_GRENADE1_ATTACK = GameActivity_t.ACT_MP_MELEE_GRENADE1_ATTACK +ACT_MP_MELEE_GRENADE2_DRAW = GameActivity_t.ACT_MP_MELEE_GRENADE2_DRAW +ACT_MP_MELEE_GRENADE2_IDLE = GameActivity_t.ACT_MP_MELEE_GRENADE2_IDLE +ACT_MP_MELEE_GRENADE2_ATTACK = GameActivity_t.ACT_MP_MELEE_GRENADE2_ATTACK +ACT_MP_ITEM1_GRENADE1_DRAW = GameActivity_t.ACT_MP_ITEM1_GRENADE1_DRAW +ACT_MP_ITEM1_GRENADE1_IDLE = GameActivity_t.ACT_MP_ITEM1_GRENADE1_IDLE +ACT_MP_ITEM1_GRENADE1_ATTACK = GameActivity_t.ACT_MP_ITEM1_GRENADE1_ATTACK +ACT_MP_ITEM1_GRENADE2_DRAW = GameActivity_t.ACT_MP_ITEM1_GRENADE2_DRAW +ACT_MP_ITEM1_GRENADE2_IDLE = GameActivity_t.ACT_MP_ITEM1_GRENADE2_IDLE +ACT_MP_ITEM1_GRENADE2_ATTACK = GameActivity_t.ACT_MP_ITEM1_GRENADE2_ATTACK +ACT_MP_ITEM2_GRENADE1_DRAW = GameActivity_t.ACT_MP_ITEM2_GRENADE1_DRAW +ACT_MP_ITEM2_GRENADE1_IDLE = GameActivity_t.ACT_MP_ITEM2_GRENADE1_IDLE +ACT_MP_ITEM2_GRENADE1_ATTACK = GameActivity_t.ACT_MP_ITEM2_GRENADE1_ATTACK +ACT_MP_ITEM2_GRENADE2_DRAW = GameActivity_t.ACT_MP_ITEM2_GRENADE2_DRAW +ACT_MP_ITEM2_GRENADE2_IDLE = GameActivity_t.ACT_MP_ITEM2_GRENADE2_IDLE +ACT_MP_ITEM2_GRENADE2_ATTACK = GameActivity_t.ACT_MP_ITEM2_GRENADE2_ATTACK +ACT_MP_STAND_BUILDING = GameActivity_t.ACT_MP_STAND_BUILDING +ACT_MP_CROUCH_BUILDING = GameActivity_t.ACT_MP_CROUCH_BUILDING +ACT_MP_RUN_BUILDING = GameActivity_t.ACT_MP_RUN_BUILDING +ACT_MP_WALK_BUILDING = GameActivity_t.ACT_MP_WALK_BUILDING +ACT_MP_AIRWALK_BUILDING = GameActivity_t.ACT_MP_AIRWALK_BUILDING +ACT_MP_CROUCHWALK_BUILDING = GameActivity_t.ACT_MP_CROUCHWALK_BUILDING +ACT_MP_JUMP_BUILDING = GameActivity_t.ACT_MP_JUMP_BUILDING +ACT_MP_JUMP_START_BUILDING = GameActivity_t.ACT_MP_JUMP_START_BUILDING +ACT_MP_JUMP_FLOAT_BUILDING = GameActivity_t.ACT_MP_JUMP_FLOAT_BUILDING +ACT_MP_JUMP_LAND_BUILDING = GameActivity_t.ACT_MP_JUMP_LAND_BUILDING +ACT_MP_SWIM_BUILDING = GameActivity_t.ACT_MP_SWIM_BUILDING +ACT_MP_ATTACK_STAND_BUILDING = GameActivity_t.ACT_MP_ATTACK_STAND_BUILDING +ACT_MP_ATTACK_CROUCH_BUILDING = GameActivity_t.ACT_MP_ATTACK_CROUCH_BUILDING +ACT_MP_ATTACK_SWIM_BUILDING = GameActivity_t.ACT_MP_ATTACK_SWIM_BUILDING +ACT_MP_ATTACK_AIRWALK_BUILDING = GameActivity_t.ACT_MP_ATTACK_AIRWALK_BUILDING +ACT_MP_ATTACK_STAND_GRENADE_BUILDING = GameActivity_t.ACT_MP_ATTACK_STAND_GRENADE_BUILDING +ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING = GameActivity_t.ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING +ACT_MP_ATTACK_SWIM_GRENADE_BUILDING = GameActivity_t.ACT_MP_ATTACK_SWIM_GRENADE_BUILDING +ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING = GameActivity_t.ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING +ACT_MP_STAND_PDA = GameActivity_t.ACT_MP_STAND_PDA +ACT_MP_CROUCH_PDA = GameActivity_t.ACT_MP_CROUCH_PDA +ACT_MP_RUN_PDA = GameActivity_t.ACT_MP_RUN_PDA +ACT_MP_WALK_PDA = GameActivity_t.ACT_MP_WALK_PDA +ACT_MP_AIRWALK_PDA = GameActivity_t.ACT_MP_AIRWALK_PDA +ACT_MP_CROUCHWALK_PDA = GameActivity_t.ACT_MP_CROUCHWALK_PDA +ACT_MP_JUMP_PDA = GameActivity_t.ACT_MP_JUMP_PDA +ACT_MP_JUMP_START_PDA = GameActivity_t.ACT_MP_JUMP_START_PDA +ACT_MP_JUMP_FLOAT_PDA = GameActivity_t.ACT_MP_JUMP_FLOAT_PDA +ACT_MP_JUMP_LAND_PDA = GameActivity_t.ACT_MP_JUMP_LAND_PDA +ACT_MP_SWIM_PDA = GameActivity_t.ACT_MP_SWIM_PDA +ACT_MP_ATTACK_STAND_PDA = GameActivity_t.ACT_MP_ATTACK_STAND_PDA +ACT_MP_ATTACK_SWIM_PDA = GameActivity_t.ACT_MP_ATTACK_SWIM_PDA +ACT_MP_GESTURE_VC_HANDMOUTH = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH +ACT_MP_GESTURE_VC_FINGERPOINT = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT +ACT_MP_GESTURE_VC_FISTPUMP = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP +ACT_MP_GESTURE_VC_THUMBSUP = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP +ACT_MP_GESTURE_VC_NODYES = GameActivity_t.ACT_MP_GESTURE_VC_NODYES +ACT_MP_GESTURE_VC_NODNO = GameActivity_t.ACT_MP_GESTURE_VC_NODNO +ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY +ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY +ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY +ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY +ACT_MP_GESTURE_VC_NODYES_PRIMARY = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_PRIMARY +ACT_MP_GESTURE_VC_NODNO_PRIMARY = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_PRIMARY +ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY +ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY +ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY +ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY +ACT_MP_GESTURE_VC_NODYES_SECONDARY = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_SECONDARY +ACT_MP_GESTURE_VC_NODNO_SECONDARY = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_SECONDARY +ACT_MP_GESTURE_VC_HANDMOUTH_MELEE = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_MELEE +ACT_MP_GESTURE_VC_FINGERPOINT_MELEE = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_MELEE +ACT_MP_GESTURE_VC_FISTPUMP_MELEE = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_MELEE +ACT_MP_GESTURE_VC_THUMBSUP_MELEE = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_MELEE +ACT_MP_GESTURE_VC_NODYES_MELEE = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_MELEE +ACT_MP_GESTURE_VC_NODNO_MELEE = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_MELEE +ACT_MP_GESTURE_VC_HANDMOUTH_ITEM1 = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_ITEM1 +ACT_MP_GESTURE_VC_FINGERPOINT_ITEM1 = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_ITEM1 +ACT_MP_GESTURE_VC_FISTPUMP_ITEM1 = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_ITEM1 +ACT_MP_GESTURE_VC_THUMBSUP_ITEM1 = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_ITEM1 +ACT_MP_GESTURE_VC_NODYES_ITEM1 = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_ITEM1 +ACT_MP_GESTURE_VC_NODNO_ITEM1 = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_ITEM1 +ACT_MP_GESTURE_VC_HANDMOUTH_ITEM2 = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_ITEM2 +ACT_MP_GESTURE_VC_FINGERPOINT_ITEM2 = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_ITEM2 +ACT_MP_GESTURE_VC_FISTPUMP_ITEM2 = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_ITEM2 +ACT_MP_GESTURE_VC_THUMBSUP_ITEM2 = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_ITEM2 +ACT_MP_GESTURE_VC_NODYES_ITEM2 = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_ITEM2 +ACT_MP_GESTURE_VC_NODNO_ITEM2 = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_ITEM2 +ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING +ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING +ACT_MP_GESTURE_VC_FISTPUMP_BUILDING = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_BUILDING +ACT_MP_GESTURE_VC_THUMBSUP_BUILDING = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_BUILDING +ACT_MP_GESTURE_VC_NODYES_BUILDING = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_BUILDING +ACT_MP_GESTURE_VC_NODNO_BUILDING = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_BUILDING +ACT_MP_GESTURE_VC_HANDMOUTH_PDA = GameActivity_t.ACT_MP_GESTURE_VC_HANDMOUTH_PDA +ACT_MP_GESTURE_VC_FINGERPOINT_PDA = GameActivity_t.ACT_MP_GESTURE_VC_FINGERPOINT_PDA +ACT_MP_GESTURE_VC_FISTPUMP_PDA = GameActivity_t.ACT_MP_GESTURE_VC_FISTPUMP_PDA +ACT_MP_GESTURE_VC_THUMBSUP_PDA = GameActivity_t.ACT_MP_GESTURE_VC_THUMBSUP_PDA +ACT_MP_GESTURE_VC_NODYES_PDA = GameActivity_t.ACT_MP_GESTURE_VC_NODYES_PDA +ACT_MP_GESTURE_VC_NODNO_PDA = GameActivity_t.ACT_MP_GESTURE_VC_NODNO_PDA +ACT_VM_UNUSABLE = GameActivity_t.ACT_VM_UNUSABLE +ACT_VM_UNUSABLE_TO_USABLE = GameActivity_t.ACT_VM_UNUSABLE_TO_USABLE +ACT_VM_USABLE_TO_UNUSABLE = GameActivity_t.ACT_VM_USABLE_TO_UNUSABLE +ACT_PRIMARY_VM_DRAW = GameActivity_t.ACT_PRIMARY_VM_DRAW +ACT_PRIMARY_VM_HOLSTER = GameActivity_t.ACT_PRIMARY_VM_HOLSTER +ACT_PRIMARY_VM_IDLE = GameActivity_t.ACT_PRIMARY_VM_IDLE +ACT_PRIMARY_VM_PULLBACK = GameActivity_t.ACT_PRIMARY_VM_PULLBACK +ACT_PRIMARY_VM_PRIMARYATTACK = GameActivity_t.ACT_PRIMARY_VM_PRIMARYATTACK +ACT_PRIMARY_VM_SECONDARYATTACK = GameActivity_t.ACT_PRIMARY_VM_SECONDARYATTACK +ACT_PRIMARY_VM_RELOAD = GameActivity_t.ACT_PRIMARY_VM_RELOAD +ACT_PRIMARY_VM_DRYFIRE = GameActivity_t.ACT_PRIMARY_VM_DRYFIRE +ACT_PRIMARY_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_PRIMARY_VM_IDLE_TO_LOWERED +ACT_PRIMARY_VM_IDLE_LOWERED = GameActivity_t.ACT_PRIMARY_VM_IDLE_LOWERED +ACT_PRIMARY_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_PRIMARY_VM_LOWERED_TO_IDLE +ACT_SECONDARY_VM_DRAW = GameActivity_t.ACT_SECONDARY_VM_DRAW +ACT_SECONDARY_VM_HOLSTER = GameActivity_t.ACT_SECONDARY_VM_HOLSTER +ACT_SECONDARY_VM_IDLE = GameActivity_t.ACT_SECONDARY_VM_IDLE +ACT_SECONDARY_VM_PULLBACK = GameActivity_t.ACT_SECONDARY_VM_PULLBACK +ACT_SECONDARY_VM_PRIMARYATTACK = GameActivity_t.ACT_SECONDARY_VM_PRIMARYATTACK +ACT_SECONDARY_VM_SECONDARYATTACK = GameActivity_t.ACT_SECONDARY_VM_SECONDARYATTACK +ACT_SECONDARY_VM_RELOAD = GameActivity_t.ACT_SECONDARY_VM_RELOAD +ACT_SECONDARY_VM_DRYFIRE = GameActivity_t.ACT_SECONDARY_VM_DRYFIRE +ACT_SECONDARY_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_SECONDARY_VM_IDLE_TO_LOWERED +ACT_SECONDARY_VM_IDLE_LOWERED = GameActivity_t.ACT_SECONDARY_VM_IDLE_LOWERED +ACT_SECONDARY_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_SECONDARY_VM_LOWERED_TO_IDLE +ACT_MELEE_VM_DRAW = GameActivity_t.ACT_MELEE_VM_DRAW +ACT_MELEE_VM_HOLSTER = GameActivity_t.ACT_MELEE_VM_HOLSTER +ACT_MELEE_VM_IDLE = GameActivity_t.ACT_MELEE_VM_IDLE +ACT_MELEE_VM_PULLBACK = GameActivity_t.ACT_MELEE_VM_PULLBACK +ACT_MELEE_VM_PRIMARYATTACK = GameActivity_t.ACT_MELEE_VM_PRIMARYATTACK +ACT_MELEE_VM_SECONDARYATTACK = GameActivity_t.ACT_MELEE_VM_SECONDARYATTACK +ACT_MELEE_VM_RELOAD = GameActivity_t.ACT_MELEE_VM_RELOAD +ACT_MELEE_VM_DRYFIRE = GameActivity_t.ACT_MELEE_VM_DRYFIRE +ACT_MELEE_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_MELEE_VM_IDLE_TO_LOWERED +ACT_MELEE_VM_IDLE_LOWERED = GameActivity_t.ACT_MELEE_VM_IDLE_LOWERED +ACT_MELEE_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_MELEE_VM_LOWERED_TO_IDLE +ACT_PDA_VM_DRAW = GameActivity_t.ACT_PDA_VM_DRAW +ACT_PDA_VM_HOLSTER = GameActivity_t.ACT_PDA_VM_HOLSTER +ACT_PDA_VM_IDLE = GameActivity_t.ACT_PDA_VM_IDLE +ACT_PDA_VM_PULLBACK = GameActivity_t.ACT_PDA_VM_PULLBACK +ACT_PDA_VM_PRIMARYATTACK = GameActivity_t.ACT_PDA_VM_PRIMARYATTACK +ACT_PDA_VM_SECONDARYATTACK = GameActivity_t.ACT_PDA_VM_SECONDARYATTACK +ACT_PDA_VM_RELOAD = GameActivity_t.ACT_PDA_VM_RELOAD +ACT_PDA_VM_DRYFIRE = GameActivity_t.ACT_PDA_VM_DRYFIRE +ACT_PDA_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_PDA_VM_IDLE_TO_LOWERED +ACT_PDA_VM_IDLE_LOWERED = GameActivity_t.ACT_PDA_VM_IDLE_LOWERED +ACT_PDA_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_PDA_VM_LOWERED_TO_IDLE +ACT_ITEM1_VM_DRAW = GameActivity_t.ACT_ITEM1_VM_DRAW +ACT_ITEM1_VM_HOLSTER = GameActivity_t.ACT_ITEM1_VM_HOLSTER +ACT_ITEM1_VM_IDLE = GameActivity_t.ACT_ITEM1_VM_IDLE +ACT_ITEM1_VM_PULLBACK = GameActivity_t.ACT_ITEM1_VM_PULLBACK +ACT_ITEM1_VM_PRIMARYATTACK = GameActivity_t.ACT_ITEM1_VM_PRIMARYATTACK +ACT_ITEM1_VM_SECONDARYATTACK = GameActivity_t.ACT_ITEM1_VM_SECONDARYATTACK +ACT_ITEM1_VM_RELOAD = GameActivity_t.ACT_ITEM1_VM_RELOAD +ACT_ITEM1_VM_DRYFIRE = GameActivity_t.ACT_ITEM1_VM_DRYFIRE +ACT_ITEM1_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_ITEM1_VM_IDLE_TO_LOWERED +ACT_ITEM1_VM_IDLE_LOWERED = GameActivity_t.ACT_ITEM1_VM_IDLE_LOWERED +ACT_ITEM1_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_ITEM1_VM_LOWERED_TO_IDLE +ACT_ITEM2_VM_DRAW = GameActivity_t.ACT_ITEM2_VM_DRAW +ACT_ITEM2_VM_HOLSTER = GameActivity_t.ACT_ITEM2_VM_HOLSTER +ACT_ITEM2_VM_IDLE = GameActivity_t.ACT_ITEM2_VM_IDLE +ACT_ITEM2_VM_PULLBACK = GameActivity_t.ACT_ITEM2_VM_PULLBACK +ACT_ITEM2_VM_PRIMARYATTACK = GameActivity_t.ACT_ITEM2_VM_PRIMARYATTACK +ACT_ITEM2_VM_SECONDARYATTACK = GameActivity_t.ACT_ITEM2_VM_SECONDARYATTACK +ACT_ITEM2_VM_RELOAD = GameActivity_t.ACT_ITEM2_VM_RELOAD +ACT_ITEM2_VM_DRYFIRE = GameActivity_t.ACT_ITEM2_VM_DRYFIRE +ACT_ITEM2_VM_IDLE_TO_LOWERED = GameActivity_t.ACT_ITEM2_VM_IDLE_TO_LOWERED +ACT_ITEM2_VM_IDLE_LOWERED = GameActivity_t.ACT_ITEM2_VM_IDLE_LOWERED +ACT_ITEM2_VM_LOWERED_TO_IDLE = GameActivity_t.ACT_ITEM2_VM_LOWERED_TO_IDLE +ACT_RELOAD_SUCCEED = GameActivity_t.ACT_RELOAD_SUCCEED +ACT_RELOAD_FAIL = GameActivity_t.ACT_RELOAD_FAIL +ACT_WALK_AIM_AUTOGUN = GameActivity_t.ACT_WALK_AIM_AUTOGUN +ACT_RUN_AIM_AUTOGUN = GameActivity_t.ACT_RUN_AIM_AUTOGUN +ACT_IDLE_AUTOGUN = GameActivity_t.ACT_IDLE_AUTOGUN +ACT_IDLE_AIM_AUTOGUN = GameActivity_t.ACT_IDLE_AIM_AUTOGUN +ACT_RELOAD_AUTOGUN = GameActivity_t.ACT_RELOAD_AUTOGUN +ACT_CROUCH_IDLE_AUTOGUN = GameActivity_t.ACT_CROUCH_IDLE_AUTOGUN +ACT_RANGE_ATTACK_AUTOGUN = GameActivity_t.ACT_RANGE_ATTACK_AUTOGUN +ACT_JUMP_AUTOGUN = GameActivity_t.ACT_JUMP_AUTOGUN +ACT_IDLE_AIM_PISTOL = GameActivity_t.ACT_IDLE_AIM_PISTOL +ACT_WALK_AIM_DUAL = GameActivity_t.ACT_WALK_AIM_DUAL +ACT_RUN_AIM_DUAL = GameActivity_t.ACT_RUN_AIM_DUAL +ACT_IDLE_DUAL = GameActivity_t.ACT_IDLE_DUAL +ACT_IDLE_AIM_DUAL = GameActivity_t.ACT_IDLE_AIM_DUAL +ACT_RELOAD_DUAL = GameActivity_t.ACT_RELOAD_DUAL +ACT_CROUCH_IDLE_DUAL = GameActivity_t.ACT_CROUCH_IDLE_DUAL +ACT_RANGE_ATTACK_DUAL = GameActivity_t.ACT_RANGE_ATTACK_DUAL +ACT_JUMP_DUAL = GameActivity_t.ACT_JUMP_DUAL +ACT_IDLE_AIM_SHOTGUN = GameActivity_t.ACT_IDLE_AIM_SHOTGUN +ACT_CROUCH_IDLE_SHOTGUN = GameActivity_t.ACT_CROUCH_IDLE_SHOTGUN +ACT_IDLE_AIM_RIFLE = GameActivity_t.ACT_IDLE_AIM_RIFLE +ACT_CROUCH_IDLE_RIFLE = GameActivity_t.ACT_CROUCH_IDLE_RIFLE +ACT_RANGE_ATTACK_RIFLE = GameActivity_t.ACT_RANGE_ATTACK_RIFLE +ACT_SLEEP = GameActivity_t.ACT_SLEEP +ACT_WAKE = GameActivity_t.ACT_WAKE +ACT_FLICK_LEFT = GameActivity_t.ACT_FLICK_LEFT +ACT_FLICK_LEFT_MIDDLE = GameActivity_t.ACT_FLICK_LEFT_MIDDLE +ACT_FLICK_RIGHT_MIDDLE = GameActivity_t.ACT_FLICK_RIGHT_MIDDLE +ACT_FLICK_RIGHT = GameActivity_t.ACT_FLICK_RIGHT +ACT_SPINAROUND = GameActivity_t.ACT_SPINAROUND +ACT_PREP_TO_FIRE = GameActivity_t.ACT_PREP_TO_FIRE +ACT_FIRE = GameActivity_t.ACT_FIRE +ACT_FIRE_RECOVER = GameActivity_t.ACT_FIRE_RECOVER +ACT_SPRAY = GameActivity_t.ACT_SPRAY +ACT_PREP_EXPLODE = GameActivity_t.ACT_PREP_EXPLODE +ACT_EXPLODE = GameActivity_t.ACT_EXPLODE +ACT_SCRIPT_CUSTOM_0 = GameActivity_t.ACT_SCRIPT_CUSTOM_0 +ACT_SCRIPT_CUSTOM_1 = GameActivity_t.ACT_SCRIPT_CUSTOM_1 +ACT_SCRIPT_CUSTOM_2 = GameActivity_t.ACT_SCRIPT_CUSTOM_2 +ACT_SCRIPT_CUSTOM_3 = GameActivity_t.ACT_SCRIPT_CUSTOM_3 +ACT_SCRIPT_CUSTOM_4 = GameActivity_t.ACT_SCRIPT_CUSTOM_4 +ACT_SCRIPT_CUSTOM_5 = GameActivity_t.ACT_SCRIPT_CUSTOM_5 +ACT_SCRIPT_CUSTOM_6 = GameActivity_t.ACT_SCRIPT_CUSTOM_6 +ACT_SCRIPT_CUSTOM_7 = GameActivity_t.ACT_SCRIPT_CUSTOM_7 +ACT_SCRIPT_CUSTOM_8 = GameActivity_t.ACT_SCRIPT_CUSTOM_8 +ACT_SCRIPT_CUSTOM_9 = GameActivity_t.ACT_SCRIPT_CUSTOM_9 +ACT_SCRIPT_CUSTOM_10 = GameActivity_t.ACT_SCRIPT_CUSTOM_10 +ACT_SCRIPT_CUSTOM_11 = GameActivity_t.ACT_SCRIPT_CUSTOM_11 +ACT_SCRIPT_CUSTOM_12 = GameActivity_t.ACT_SCRIPT_CUSTOM_12 +ACT_SCRIPT_CUSTOM_13 = GameActivity_t.ACT_SCRIPT_CUSTOM_13 +ACT_SCRIPT_CUSTOM_14 = GameActivity_t.ACT_SCRIPT_CUSTOM_14 +ACT_SCRIPT_CUSTOM_15 = GameActivity_t.ACT_SCRIPT_CUSTOM_15 +ACT_SCRIPT_CUSTOM_16 = GameActivity_t.ACT_SCRIPT_CUSTOM_16 +ACT_SCRIPT_CUSTOM_17 = GameActivity_t.ACT_SCRIPT_CUSTOM_17 +ACT_SCRIPT_CUSTOM_18 = GameActivity_t.ACT_SCRIPT_CUSTOM_18 +ACT_SCRIPT_CUSTOM_19 = GameActivity_t.ACT_SCRIPT_CUSTOM_19 +ACT_SCRIPT_CUSTOM_20 = GameActivity_t.ACT_SCRIPT_CUSTOM_20 +ACT_SCRIPT_CUSTOM_21 = GameActivity_t.ACT_SCRIPT_CUSTOM_21 +ACT_SCRIPT_CUSTOM_22 = GameActivity_t.ACT_SCRIPT_CUSTOM_22 +ACT_SCRIPT_CUSTOM_23 = GameActivity_t.ACT_SCRIPT_CUSTOM_23 +ACT_SCRIPT_CUSTOM_24 = GameActivity_t.ACT_SCRIPT_CUSTOM_24 +ACT_SCRIPT_CUSTOM_25 = GameActivity_t.ACT_SCRIPT_CUSTOM_25 +ACT_SCRIPT_CUSTOM_26 = GameActivity_t.ACT_SCRIPT_CUSTOM_26 +ACT_SCRIPT_CUSTOM_27 = GameActivity_t.ACT_SCRIPT_CUSTOM_27 +ACT_SCRIPT_CUSTOM_28 = GameActivity_t.ACT_SCRIPT_CUSTOM_28 +ACT_SCRIPT_CUSTOM_29 = GameActivity_t.ACT_SCRIPT_CUSTOM_29 +ACT_SCRIPT_CUSTOM_30 = GameActivity_t.ACT_SCRIPT_CUSTOM_30 +ACT_SCRIPT_CUSTOM_31 = GameActivity_t.ACT_SCRIPT_CUSTOM_31 +ACT_VR_PISTOL_LAST_SHOT = GameActivity_t.ACT_VR_PISTOL_LAST_SHOT +ACT_VR_PISTOL_SLIDE_RELEASE = GameActivity_t.ACT_VR_PISTOL_SLIDE_RELEASE +ACT_VR_PISTOL_CLIP_OUT_CHAMBERED = GameActivity_t.ACT_VR_PISTOL_CLIP_OUT_CHAMBERED +ACT_VR_PISTOL_CLIP_OUT_SLIDE_BACK = GameActivity_t.ACT_VR_PISTOL_CLIP_OUT_SLIDE_BACK +ACT_VR_PISTOL_CLIP_IN_CHAMBERED = GameActivity_t.ACT_VR_PISTOL_CLIP_IN_CHAMBERED +ACT_VR_PISTOL_CLIP_IN_SLIDE_BACK = GameActivity_t.ACT_VR_PISTOL_CLIP_IN_SLIDE_BACK +ACT_VR_PISTOL_IDLE_SLIDE_BACK = GameActivity_t.ACT_VR_PISTOL_IDLE_SLIDE_BACK +ACT_VR_PISTOL_IDLE_SLIDE_BACK_CLIP_READY = GameActivity_t.ACT_VR_PISTOL_IDLE_SLIDE_BACK_CLIP_READY +ACT_RAGDOLL_RECOVERY_FRONT = GameActivity_t.ACT_RAGDOLL_RECOVERY_FRONT +ACT_RAGDOLL_RECOVERY_BACK = GameActivity_t.ACT_RAGDOLL_RECOVERY_BACK +ACT_RAGDOLL_RECOVERY_LEFT = GameActivity_t.ACT_RAGDOLL_RECOVERY_LEFT +ACT_RAGDOLL_RECOVERY_RIGHT = GameActivity_t.ACT_RAGDOLL_RECOVERY_RIGHT +ACT_GRABBITYGLOVES_GRAB = GameActivity_t.ACT_GRABBITYGLOVES_GRAB +ACT_GRABBITYGLOVES_RELEASE = GameActivity_t.ACT_GRABBITYGLOVES_RELEASE +ACT_GRABBITYGLOVES_GRAB_IDLE = GameActivity_t.ACT_GRABBITYGLOVES_GRAB_IDLE +ACT_GRABBITYGLOVES_ACTIVE = GameActivity_t.ACT_GRABBITYGLOVES_ACTIVE +ACT_GRABBITYGLOVES_ACTIVE_IDLE = GameActivity_t.ACT_GRABBITYGLOVES_ACTIVE_IDLE +ACT_GRABBITYGLOVES_DEACTIVATE = GameActivity_t.ACT_GRABBITYGLOVES_DEACTIVATE +ACT_GRABBITYGLOVES_PULL = GameActivity_t.ACT_GRABBITYGLOVES_PULL +ACT_HEADCRAB_SMOKE_BOMB = GameActivity_t.ACT_HEADCRAB_SMOKE_BOMB +ACT_HEADCRAB_SPIT = GameActivity_t.ACT_HEADCRAB_SPIT +ACT_ZOMBIE_TRIP = GameActivity_t.ACT_ZOMBIE_TRIP +ACT_ZOMBIE_LUNGE = GameActivity_t.ACT_ZOMBIE_LUNGE +ACT_NEUTRAL_REF_POSE = GameActivity_t.ACT_NEUTRAL_REF_POSE +ACT_ANTLION_SCUTTLE_FORWARD = GameActivity_t.ACT_ANTLION_SCUTTLE_FORWARD +ACT_ANTLION_SCUTTLE_BACK = GameActivity_t.ACT_ANTLION_SCUTTLE_BACK +ACT_ANTLION_SCUTTLE_LEFT = GameActivity_t.ACT_ANTLION_SCUTTLE_LEFT +ACT_ANTLION_SCUTTLE_RIGHT = GameActivity_t.ACT_ANTLION_SCUTTLE_RIGHT +ACT_VR_PISTOL_EMPTY_CLIP_IN_SLIDE_BACK = GameActivity_t.ACT_VR_PISTOL_EMPTY_CLIP_IN_SLIDE_BACK +ACT_VR_SHOTGUN_IDLE = GameActivity_t.ACT_VR_SHOTGUN_IDLE +ACT_VR_SHOTGUN_OPEN_CHAMBER = GameActivity_t.ACT_VR_SHOTGUN_OPEN_CHAMBER +ACT_VR_SHOTGUN_RELOAD_1 = GameActivity_t.ACT_VR_SHOTGUN_RELOAD_1 +ACT_VR_SHOTGUN_RELOAD_2 = GameActivity_t.ACT_VR_SHOTGUN_RELOAD_2 +ACT_VR_SHOTGUN_RELOAD_3 = GameActivity_t.ACT_VR_SHOTGUN_RELOAD_3 +ACT_VR_SHOTGUN_CLOSE_CHAMBER = GameActivity_t.ACT_VR_SHOTGUN_CLOSE_CHAMBER +ACT_VR_SHOTGUN_TRIGGER_SQUEEZE = GameActivity_t.ACT_VR_SHOTGUN_TRIGGER_SQUEEZE +ACT_VR_SHOTGUN_SHOOT = GameActivity_t.ACT_VR_SHOTGUN_SHOOT +ACT_VR_SHOTGUN_SLIDE_BACK = GameActivity_t.ACT_VR_SHOTGUN_SLIDE_BACK +ACT_VR_SHOTGUN_SLIDE_FORWARD = GameActivity_t.ACT_VR_SHOTGUN_SLIDE_FORWARD +ACT_VR_PISTOL_LONG_CLIP_IN_CHAMBERED = GameActivity_t.ACT_VR_PISTOL_LONG_CLIP_IN_CHAMBERED +ACT_VR_PISTOL_LONG_CLIP_IN_SLIDE_BACK = GameActivity_t.ACT_VR_PISTOL_LONG_CLIP_IN_SLIDE_BACK +ACT_VR_PISTOL_BURST_TOGGLE = GameActivity_t.ACT_VR_PISTOL_BURST_TOGGLE +ACT_VR_PISTOL_LOW_KICK = GameActivity_t.ACT_VR_PISTOL_LOW_KICK +ACT_VR_PISTOL_BURST_ATTACK = GameActivity_t.ACT_VR_PISTOL_BURST_ATTACK +ACT_VR_SHOTGUN_GRENADE_TWIST = GameActivity_t.ACT_VR_SHOTGUN_GRENADE_TWIST +ACT_DIE_STAND = GameActivity_t.ACT_DIE_STAND +ACT_DIE_STAND_HEADSHOT = GameActivity_t.ACT_DIE_STAND_HEADSHOT +ACT_DIE_CROUCH = GameActivity_t.ACT_DIE_CROUCH +ACT_DIE_CROUCH_HEADSHOT = GameActivity_t.ACT_DIE_CROUCH_HEADSHOT +ACT_CSGO_NULL = GameActivity_t.ACT_CSGO_NULL +ACT_CSGO_DEFUSE = GameActivity_t.ACT_CSGO_DEFUSE +ACT_CSGO_DEFUSE_WITH_KIT = GameActivity_t.ACT_CSGO_DEFUSE_WITH_KIT +ACT_CSGO_FLASHBANG_REACTION = GameActivity_t.ACT_CSGO_FLASHBANG_REACTION +ACT_CSGO_FIRE_PRIMARY = GameActivity_t.ACT_CSGO_FIRE_PRIMARY +ACT_CSGO_FIRE_PRIMARY_OPT_1 = GameActivity_t.ACT_CSGO_FIRE_PRIMARY_OPT_1 +ACT_CSGO_FIRE_PRIMARY_OPT_2 = GameActivity_t.ACT_CSGO_FIRE_PRIMARY_OPT_2 +ACT_CSGO_FIRE_SECONDARY = GameActivity_t.ACT_CSGO_FIRE_SECONDARY +ACT_CSGO_FIRE_SECONDARY_OPT_1 = GameActivity_t.ACT_CSGO_FIRE_SECONDARY_OPT_1 +ACT_CSGO_FIRE_SECONDARY_OPT_2 = GameActivity_t.ACT_CSGO_FIRE_SECONDARY_OPT_2 +ACT_CSGO_RELOAD = GameActivity_t.ACT_CSGO_RELOAD +ACT_CSGO_RELOAD_START = GameActivity_t.ACT_CSGO_RELOAD_START +ACT_CSGO_RELOAD_LOOP = GameActivity_t.ACT_CSGO_RELOAD_LOOP +ACT_CSGO_RELOAD_END = GameActivity_t.ACT_CSGO_RELOAD_END +ACT_CSGO_OPERATE = GameActivity_t.ACT_CSGO_OPERATE +ACT_CSGO_DEPLOY = GameActivity_t.ACT_CSGO_DEPLOY +ACT_CSGO_CATCH = GameActivity_t.ACT_CSGO_CATCH +ACT_CSGO_SILENCER_DETACH = GameActivity_t.ACT_CSGO_SILENCER_DETACH +ACT_CSGO_SILENCER_ATTACH = GameActivity_t.ACT_CSGO_SILENCER_ATTACH +ACT_CSGO_TWITCH = GameActivity_t.ACT_CSGO_TWITCH +ACT_CSGO_TWITCH_BUYZONE = GameActivity_t.ACT_CSGO_TWITCH_BUYZONE +ACT_CSGO_PLANT_BOMB = GameActivity_t.ACT_CSGO_PLANT_BOMB +ACT_CSGO_IDLE_TURN_BALANCEADJUST = GameActivity_t.ACT_CSGO_IDLE_TURN_BALANCEADJUST +ACT_CSGO_IDLE_ADJUST_STOPPEDMOVING = GameActivity_t.ACT_CSGO_IDLE_ADJUST_STOPPEDMOVING +ACT_CSGO_ALIVE_LOOP = GameActivity_t.ACT_CSGO_ALIVE_LOOP +ACT_CSGO_FLINCH = GameActivity_t.ACT_CSGO_FLINCH +ACT_CSGO_FLINCH_HEAD = GameActivity_t.ACT_CSGO_FLINCH_HEAD +ACT_CSGO_FLINCH_MOLOTOV = GameActivity_t.ACT_CSGO_FLINCH_MOLOTOV +ACT_CSGO_JUMP = GameActivity_t.ACT_CSGO_JUMP +ACT_CSGO_FALL = GameActivity_t.ACT_CSGO_FALL +ACT_CSGO_CLIMB_LADDER = GameActivity_t.ACT_CSGO_CLIMB_LADDER +ACT_CSGO_LAND_LIGHT = GameActivity_t.ACT_CSGO_LAND_LIGHT +ACT_CSGO_LAND_HEAVY = GameActivity_t.ACT_CSGO_LAND_HEAVY +ACT_CSGO_EXIT_LADDER_TOP = GameActivity_t.ACT_CSGO_EXIT_LADDER_TOP +ACT_CSGO_EXIT_LADDER_BOTTOM = GameActivity_t.ACT_CSGO_EXIT_LADDER_BOTTOM +ACT_CSGO_PARACHUTE = GameActivity_t.ACT_CSGO_PARACHUTE +ACT_CSGO_TAUNT = GameActivity_t.ACT_CSGO_TAUNT +ACT_DOTA_IDLE = GameActivity_t.ACT_DOTA_IDLE +ACT_DOTA_IDLE_RARE = GameActivity_t.ACT_DOTA_IDLE_RARE +ACT_DOTA_RUN = GameActivity_t.ACT_DOTA_RUN +ACT_DOTA_ATTACK = GameActivity_t.ACT_DOTA_ATTACK +ACT_DOTA_ATTACK2 = GameActivity_t.ACT_DOTA_ATTACK2 +ACT_DOTA_ATTACK_EVENT = GameActivity_t.ACT_DOTA_ATTACK_EVENT +ACT_DOTA_DIE = GameActivity_t.ACT_DOTA_DIE +ACT_DOTA_FLINCH = GameActivity_t.ACT_DOTA_FLINCH +ACT_DOTA_FLAIL = GameActivity_t.ACT_DOTA_FLAIL +ACT_DOTA_DISABLED = GameActivity_t.ACT_DOTA_DISABLED +ACT_DOTA_CAST_ABILITY_1 = GameActivity_t.ACT_DOTA_CAST_ABILITY_1 +ACT_DOTA_CAST_ABILITY_2 = GameActivity_t.ACT_DOTA_CAST_ABILITY_2 +ACT_DOTA_CAST_ABILITY_3 = GameActivity_t.ACT_DOTA_CAST_ABILITY_3 +ACT_DOTA_CAST_ABILITY_4 = GameActivity_t.ACT_DOTA_CAST_ABILITY_4 +ACT_DOTA_CAST_ABILITY_5 = GameActivity_t.ACT_DOTA_CAST_ABILITY_5 +ACT_DOTA_CAST_ABILITY_6 = GameActivity_t.ACT_DOTA_CAST_ABILITY_6 +ACT_DOTA_OVERRIDE_ABILITY_1 = GameActivity_t.ACT_DOTA_OVERRIDE_ABILITY_1 +ACT_DOTA_OVERRIDE_ABILITY_2 = GameActivity_t.ACT_DOTA_OVERRIDE_ABILITY_2 +ACT_DOTA_OVERRIDE_ABILITY_3 = GameActivity_t.ACT_DOTA_OVERRIDE_ABILITY_3 +ACT_DOTA_OVERRIDE_ABILITY_4 = GameActivity_t.ACT_DOTA_OVERRIDE_ABILITY_4 +ACT_DOTA_CHANNEL_ABILITY_1 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_1 +ACT_DOTA_CHANNEL_ABILITY_2 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_2 +ACT_DOTA_CHANNEL_ABILITY_3 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_3 +ACT_DOTA_CHANNEL_ABILITY_4 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_4 +ACT_DOTA_CHANNEL_ABILITY_5 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_5 +ACT_DOTA_CHANNEL_ABILITY_6 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_6 +ACT_DOTA_CHANNEL_END_ABILITY_1 = GameActivity_t.ACT_DOTA_CHANNEL_END_ABILITY_1 +ACT_DOTA_CHANNEL_END_ABILITY_2 = GameActivity_t.ACT_DOTA_CHANNEL_END_ABILITY_2 +ACT_DOTA_CHANNEL_END_ABILITY_3 = GameActivity_t.ACT_DOTA_CHANNEL_END_ABILITY_3 +ACT_DOTA_CHANNEL_END_ABILITY_4 = GameActivity_t.ACT_DOTA_CHANNEL_END_ABILITY_4 +ACT_DOTA_CHANNEL_END_ABILITY_5 = GameActivity_t.ACT_DOTA_CHANNEL_END_ABILITY_5 +ACT_DOTA_CHANNEL_END_ABILITY_6 = GameActivity_t.ACT_DOTA_CHANNEL_END_ABILITY_6 +ACT_DOTA_CONSTANT_LAYER = GameActivity_t.ACT_DOTA_CONSTANT_LAYER +ACT_DOTA_CAPTURE = GameActivity_t.ACT_DOTA_CAPTURE +ACT_DOTA_SPAWN = GameActivity_t.ACT_DOTA_SPAWN +ACT_DOTA_KILLTAUNT = GameActivity_t.ACT_DOTA_KILLTAUNT +ACT_DOTA_TAUNT = GameActivity_t.ACT_DOTA_TAUNT +ACT_DOTA_THIRST = GameActivity_t.ACT_DOTA_THIRST +ACT_DOTA_CAST_DRAGONBREATH = GameActivity_t.ACT_DOTA_CAST_DRAGONBREATH +ACT_DOTA_ECHO_SLAM = GameActivity_t.ACT_DOTA_ECHO_SLAM +ACT_DOTA_CAST_ABILITY_1_END = GameActivity_t.ACT_DOTA_CAST_ABILITY_1_END +ACT_DOTA_CAST_ABILITY_2_END = GameActivity_t.ACT_DOTA_CAST_ABILITY_2_END +ACT_DOTA_CAST_ABILITY_3_END = GameActivity_t.ACT_DOTA_CAST_ABILITY_3_END +ACT_DOTA_CAST_ABILITY_4_END = GameActivity_t.ACT_DOTA_CAST_ABILITY_4_END +ACT_MIRANA_LEAP_END = GameActivity_t.ACT_MIRANA_LEAP_END +ACT_WAVEFORM_START = GameActivity_t.ACT_WAVEFORM_START +ACT_WAVEFORM_END = GameActivity_t.ACT_WAVEFORM_END +ACT_DOTA_CAST_ABILITY_ROT = GameActivity_t.ACT_DOTA_CAST_ABILITY_ROT +ACT_DOTA_DIE_SPECIAL = GameActivity_t.ACT_DOTA_DIE_SPECIAL +ACT_DOTA_RATTLETRAP_BATTERYASSAULT = GameActivity_t.ACT_DOTA_RATTLETRAP_BATTERYASSAULT +ACT_DOTA_RATTLETRAP_POWERCOGS = GameActivity_t.ACT_DOTA_RATTLETRAP_POWERCOGS +ACT_DOTA_RATTLETRAP_HOOKSHOT_START = GameActivity_t.ACT_DOTA_RATTLETRAP_HOOKSHOT_START +ACT_DOTA_RATTLETRAP_HOOKSHOT_LOOP = GameActivity_t.ACT_DOTA_RATTLETRAP_HOOKSHOT_LOOP +ACT_DOTA_RATTLETRAP_HOOKSHOT_END = GameActivity_t.ACT_DOTA_RATTLETRAP_HOOKSHOT_END +ACT_STORM_SPIRIT_OVERLOAD_RUN_OVERRIDE = GameActivity_t.ACT_STORM_SPIRIT_OVERLOAD_RUN_OVERRIDE +ACT_DOTA_TINKER_REARM1 = GameActivity_t.ACT_DOTA_TINKER_REARM1 +ACT_DOTA_TINKER_REARM2 = GameActivity_t.ACT_DOTA_TINKER_REARM2 +ACT_DOTA_TINKER_REARM3 = GameActivity_t.ACT_DOTA_TINKER_REARM3 +ACT_TINY_AVALANCHE = GameActivity_t.ACT_TINY_AVALANCHE +ACT_TINY_TOSS = GameActivity_t.ACT_TINY_TOSS +ACT_TINY_GROWL = GameActivity_t.ACT_TINY_GROWL +ACT_DOTA_WEAVERBUG_ATTACH = GameActivity_t.ACT_DOTA_WEAVERBUG_ATTACH +ACT_DOTA_CAST_WILD_AXES_END = GameActivity_t.ACT_DOTA_CAST_WILD_AXES_END +ACT_DOTA_CAST_LIFE_BREAK_START = GameActivity_t.ACT_DOTA_CAST_LIFE_BREAK_START +ACT_DOTA_CAST_LIFE_BREAK_END = GameActivity_t.ACT_DOTA_CAST_LIFE_BREAK_END +ACT_DOTA_NIGHTSTALKER_TRANSITION = GameActivity_t.ACT_DOTA_NIGHTSTALKER_TRANSITION +ACT_DOTA_LIFESTEALER_RAGE = GameActivity_t.ACT_DOTA_LIFESTEALER_RAGE +ACT_DOTA_LIFESTEALER_OPEN_WOUNDS = GameActivity_t.ACT_DOTA_LIFESTEALER_OPEN_WOUNDS +ACT_DOTA_SAND_KING_BURROW_IN = GameActivity_t.ACT_DOTA_SAND_KING_BURROW_IN +ACT_DOTA_SAND_KING_BURROW_OUT = GameActivity_t.ACT_DOTA_SAND_KING_BURROW_OUT +ACT_DOTA_EARTHSHAKER_TOTEM_ATTACK = GameActivity_t.ACT_DOTA_EARTHSHAKER_TOTEM_ATTACK +ACT_DOTA_WHEEL_LAYER = GameActivity_t.ACT_DOTA_WHEEL_LAYER +ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START = GameActivity_t.ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START +ACT_DOTA_ALCHEMIST_CONCOCTION = GameActivity_t.ACT_DOTA_ALCHEMIST_CONCOCTION +ACT_DOTA_JAKIRO_LIQUIDFIRE_START = GameActivity_t.ACT_DOTA_JAKIRO_LIQUIDFIRE_START +ACT_DOTA_JAKIRO_LIQUIDFIRE_LOOP = GameActivity_t.ACT_DOTA_JAKIRO_LIQUIDFIRE_LOOP +ACT_DOTA_LIFESTEALER_INFEST = GameActivity_t.ACT_DOTA_LIFESTEALER_INFEST +ACT_DOTA_LIFESTEALER_INFEST_END = GameActivity_t.ACT_DOTA_LIFESTEALER_INFEST_END +ACT_DOTA_LASSO_LOOP = GameActivity_t.ACT_DOTA_LASSO_LOOP +ACT_DOTA_ALCHEMIST_CONCOCTION_THROW = GameActivity_t.ACT_DOTA_ALCHEMIST_CONCOCTION_THROW +ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END = GameActivity_t.ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END +ACT_DOTA_CAST_COLD_SNAP = GameActivity_t.ACT_DOTA_CAST_COLD_SNAP +ACT_DOTA_CAST_GHOST_WALK = GameActivity_t.ACT_DOTA_CAST_GHOST_WALK +ACT_DOTA_CAST_TORNADO = GameActivity_t.ACT_DOTA_CAST_TORNADO +ACT_DOTA_CAST_EMP = GameActivity_t.ACT_DOTA_CAST_EMP +ACT_DOTA_CAST_ALACRITY = GameActivity_t.ACT_DOTA_CAST_ALACRITY +ACT_DOTA_CAST_CHAOS_METEOR = GameActivity_t.ACT_DOTA_CAST_CHAOS_METEOR +ACT_DOTA_CAST_SUN_STRIKE = GameActivity_t.ACT_DOTA_CAST_SUN_STRIKE +ACT_DOTA_CAST_FORGE_SPIRIT = GameActivity_t.ACT_DOTA_CAST_FORGE_SPIRIT +ACT_DOTA_CAST_ICE_WALL = GameActivity_t.ACT_DOTA_CAST_ICE_WALL +ACT_DOTA_CAST_DEAFENING_BLAST = GameActivity_t.ACT_DOTA_CAST_DEAFENING_BLAST +ACT_DOTA_VICTORY = GameActivity_t.ACT_DOTA_VICTORY +ACT_DOTA_DEFEAT = GameActivity_t.ACT_DOTA_DEFEAT +ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE = GameActivity_t.ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE +ACT_DOTA_SPIRIT_BREAKER_CHARGE_END = GameActivity_t.ACT_DOTA_SPIRIT_BREAKER_CHARGE_END +ACT_DOTA_TELEPORT = GameActivity_t.ACT_DOTA_TELEPORT +ACT_DOTA_TELEPORT_END = GameActivity_t.ACT_DOTA_TELEPORT_END +ACT_DOTA_CAST_REFRACTION = GameActivity_t.ACT_DOTA_CAST_REFRACTION +ACT_DOTA_CAST_ABILITY_7 = GameActivity_t.ACT_DOTA_CAST_ABILITY_7 +ACT_DOTA_CANCEL_SIREN_SONG = GameActivity_t.ACT_DOTA_CANCEL_SIREN_SONG +ACT_DOTA_CHANNEL_ABILITY_7 = GameActivity_t.ACT_DOTA_CHANNEL_ABILITY_7 +ACT_DOTA_LOADOUT = GameActivity_t.ACT_DOTA_LOADOUT +ACT_DOTA_FORCESTAFF_END = GameActivity_t.ACT_DOTA_FORCESTAFF_END +ACT_DOTA_POOF_END = GameActivity_t.ACT_DOTA_POOF_END +ACT_DOTA_SLARK_POUNCE = GameActivity_t.ACT_DOTA_SLARK_POUNCE +ACT_DOTA_MAGNUS_SKEWER_START = GameActivity_t.ACT_DOTA_MAGNUS_SKEWER_START +ACT_DOTA_MAGNUS_SKEWER_END = GameActivity_t.ACT_DOTA_MAGNUS_SKEWER_END +ACT_DOTA_MEDUSA_STONE_GAZE = GameActivity_t.ACT_DOTA_MEDUSA_STONE_GAZE +ACT_DOTA_RELAX_START = GameActivity_t.ACT_DOTA_RELAX_START +ACT_DOTA_RELAX_LOOP = GameActivity_t.ACT_DOTA_RELAX_LOOP +ACT_DOTA_RELAX_END = GameActivity_t.ACT_DOTA_RELAX_END +ACT_DOTA_CENTAUR_STAMPEDE = GameActivity_t.ACT_DOTA_CENTAUR_STAMPEDE +ACT_DOTA_BELLYACHE_START = GameActivity_t.ACT_DOTA_BELLYACHE_START +ACT_DOTA_BELLYACHE_LOOP = GameActivity_t.ACT_DOTA_BELLYACHE_LOOP +ACT_DOTA_BELLYACHE_END = GameActivity_t.ACT_DOTA_BELLYACHE_END +ACT_DOTA_ROQUELAIRE_LAND = GameActivity_t.ACT_DOTA_ROQUELAIRE_LAND +ACT_DOTA_ROQUELAIRE_LAND_IDLE = GameActivity_t.ACT_DOTA_ROQUELAIRE_LAND_IDLE +ACT_DOTA_GREEVIL_CAST = GameActivity_t.ACT_DOTA_GREEVIL_CAST +ACT_DOTA_GREEVIL_OVERRIDE_ABILITY = GameActivity_t.ACT_DOTA_GREEVIL_OVERRIDE_ABILITY +ACT_DOTA_GREEVIL_HOOK_START = GameActivity_t.ACT_DOTA_GREEVIL_HOOK_START +ACT_DOTA_GREEVIL_HOOK_END = GameActivity_t.ACT_DOTA_GREEVIL_HOOK_END +ACT_DOTA_GREEVIL_BLINK_BONE = GameActivity_t.ACT_DOTA_GREEVIL_BLINK_BONE +ACT_DOTA_IDLE_SLEEPING = GameActivity_t.ACT_DOTA_IDLE_SLEEPING +ACT_DOTA_INTRO = GameActivity_t.ACT_DOTA_INTRO +ACT_DOTA_GESTURE_POINT = GameActivity_t.ACT_DOTA_GESTURE_POINT +ACT_DOTA_GESTURE_ACCENT = GameActivity_t.ACT_DOTA_GESTURE_ACCENT +ACT_DOTA_SLEEPING_END = GameActivity_t.ACT_DOTA_SLEEPING_END +ACT_DOTA_AMBUSH = GameActivity_t.ACT_DOTA_AMBUSH +ACT_DOTA_ITEM_LOOK = GameActivity_t.ACT_DOTA_ITEM_LOOK +ACT_DOTA_STARTLE = GameActivity_t.ACT_DOTA_STARTLE +ACT_DOTA_FRUSTRATION = GameActivity_t.ACT_DOTA_FRUSTRATION +ACT_DOTA_TELEPORT_REACT = GameActivity_t.ACT_DOTA_TELEPORT_REACT +ACT_DOTA_TELEPORT_END_REACT = GameActivity_t.ACT_DOTA_TELEPORT_END_REACT +ACT_DOTA_SHRUG = GameActivity_t.ACT_DOTA_SHRUG +ACT_DOTA_RELAX_LOOP_END = GameActivity_t.ACT_DOTA_RELAX_LOOP_END +ACT_DOTA_PRESENT_ITEM = GameActivity_t.ACT_DOTA_PRESENT_ITEM +ACT_DOTA_IDLE_IMPATIENT = GameActivity_t.ACT_DOTA_IDLE_IMPATIENT +ACT_DOTA_SHARPEN_WEAPON = GameActivity_t.ACT_DOTA_SHARPEN_WEAPON +ACT_DOTA_SHARPEN_WEAPON_OUT = GameActivity_t.ACT_DOTA_SHARPEN_WEAPON_OUT +ACT_DOTA_IDLE_SLEEPING_END = GameActivity_t.ACT_DOTA_IDLE_SLEEPING_END +ACT_DOTA_BRIDGE_DESTROY = GameActivity_t.ACT_DOTA_BRIDGE_DESTROY +ACT_DOTA_TAUNT_SNIPER = GameActivity_t.ACT_DOTA_TAUNT_SNIPER +ACT_DOTA_DEATH_BY_SNIPER = GameActivity_t.ACT_DOTA_DEATH_BY_SNIPER +ACT_DOTA_LOOK_AROUND = GameActivity_t.ACT_DOTA_LOOK_AROUND +ACT_DOTA_CAGED_CREEP_RAGE = GameActivity_t.ACT_DOTA_CAGED_CREEP_RAGE +ACT_DOTA_CAGED_CREEP_RAGE_OUT = GameActivity_t.ACT_DOTA_CAGED_CREEP_RAGE_OUT +ACT_DOTA_CAGED_CREEP_SMASH = GameActivity_t.ACT_DOTA_CAGED_CREEP_SMASH +ACT_DOTA_CAGED_CREEP_SMASH_OUT = GameActivity_t.ACT_DOTA_CAGED_CREEP_SMASH_OUT +ACT_DOTA_IDLE_IMPATIENT_SWORD_TAP = GameActivity_t.ACT_DOTA_IDLE_IMPATIENT_SWORD_TAP +ACT_DOTA_INTRO_LOOP = GameActivity_t.ACT_DOTA_INTRO_LOOP +ACT_DOTA_BRIDGE_THREAT = GameActivity_t.ACT_DOTA_BRIDGE_THREAT +ACT_DOTA_DAGON = GameActivity_t.ACT_DOTA_DAGON +ACT_DOTA_CAST_ABILITY_2_ES_ROLL_START = GameActivity_t.ACT_DOTA_CAST_ABILITY_2_ES_ROLL_START +ACT_DOTA_CAST_ABILITY_2_ES_ROLL = GameActivity_t.ACT_DOTA_CAST_ABILITY_2_ES_ROLL +ACT_DOTA_CAST_ABILITY_2_ES_ROLL_END = GameActivity_t.ACT_DOTA_CAST_ABILITY_2_ES_ROLL_END +ACT_DOTA_NIAN_PIN_START = GameActivity_t.ACT_DOTA_NIAN_PIN_START +ACT_DOTA_NIAN_PIN_LOOP = GameActivity_t.ACT_DOTA_NIAN_PIN_LOOP +ACT_DOTA_NIAN_PIN_END = GameActivity_t.ACT_DOTA_NIAN_PIN_END +ACT_DOTA_LEAP_STUN = GameActivity_t.ACT_DOTA_LEAP_STUN +ACT_DOTA_LEAP_SWIPE = GameActivity_t.ACT_DOTA_LEAP_SWIPE +ACT_DOTA_NIAN_INTRO_LEAP = GameActivity_t.ACT_DOTA_NIAN_INTRO_LEAP +ACT_DOTA_AREA_DENY = GameActivity_t.ACT_DOTA_AREA_DENY +ACT_DOTA_NIAN_PIN_TO_STUN = GameActivity_t.ACT_DOTA_NIAN_PIN_TO_STUN +ACT_DOTA_RAZE_1 = GameActivity_t.ACT_DOTA_RAZE_1 +ACT_DOTA_RAZE_2 = GameActivity_t.ACT_DOTA_RAZE_2 +ACT_DOTA_RAZE_3 = GameActivity_t.ACT_DOTA_RAZE_3 +ACT_DOTA_UNDYING_DECAY = GameActivity_t.ACT_DOTA_UNDYING_DECAY +ACT_DOTA_UNDYING_SOUL_RIP = GameActivity_t.ACT_DOTA_UNDYING_SOUL_RIP +ACT_DOTA_UNDYING_TOMBSTONE = GameActivity_t.ACT_DOTA_UNDYING_TOMBSTONE +ACT_DOTA_WHIRLING_AXES_RANGED = GameActivity_t.ACT_DOTA_WHIRLING_AXES_RANGED +ACT_DOTA_SHALLOW_GRAVE = GameActivity_t.ACT_DOTA_SHALLOW_GRAVE +ACT_DOTA_COLD_FEET = GameActivity_t.ACT_DOTA_COLD_FEET +ACT_DOTA_ICE_VORTEX = GameActivity_t.ACT_DOTA_ICE_VORTEX +ACT_DOTA_CHILLING_TOUCH = GameActivity_t.ACT_DOTA_CHILLING_TOUCH +ACT_DOTA_ENFEEBLE = GameActivity_t.ACT_DOTA_ENFEEBLE +ACT_DOTA_FATAL_BONDS = GameActivity_t.ACT_DOTA_FATAL_BONDS +ACT_DOTA_MIDNIGHT_PULSE = GameActivity_t.ACT_DOTA_MIDNIGHT_PULSE +ACT_DOTA_ANCESTRAL_SPIRIT = GameActivity_t.ACT_DOTA_ANCESTRAL_SPIRIT +ACT_DOTA_THUNDER_STRIKE = GameActivity_t.ACT_DOTA_THUNDER_STRIKE +ACT_DOTA_KINETIC_FIELD = GameActivity_t.ACT_DOTA_KINETIC_FIELD +ACT_DOTA_STATIC_STORM = GameActivity_t.ACT_DOTA_STATIC_STORM +ACT_DOTA_MINI_TAUNT = GameActivity_t.ACT_DOTA_MINI_TAUNT +ACT_DOTA_ARCTIC_BURN_END = GameActivity_t.ACT_DOTA_ARCTIC_BURN_END +ACT_DOTA_LOADOUT_RARE = GameActivity_t.ACT_DOTA_LOADOUT_RARE +ACT_DOTA_SWIM = GameActivity_t.ACT_DOTA_SWIM +ACT_DOTA_FLEE = GameActivity_t.ACT_DOTA_FLEE +ACT_DOTA_TROT = GameActivity_t.ACT_DOTA_TROT +ACT_DOTA_SHAKE = GameActivity_t.ACT_DOTA_SHAKE +ACT_DOTA_SWIM_IDLE = GameActivity_t.ACT_DOTA_SWIM_IDLE +ACT_DOTA_WAIT_IDLE = GameActivity_t.ACT_DOTA_WAIT_IDLE +ACT_DOTA_GREET = GameActivity_t.ACT_DOTA_GREET +ACT_DOTA_TELEPORT_COOP_START = GameActivity_t.ACT_DOTA_TELEPORT_COOP_START +ACT_DOTA_TELEPORT_COOP_WAIT = GameActivity_t.ACT_DOTA_TELEPORT_COOP_WAIT +ACT_DOTA_TELEPORT_COOP_END = GameActivity_t.ACT_DOTA_TELEPORT_COOP_END +ACT_DOTA_TELEPORT_COOP_EXIT = GameActivity_t.ACT_DOTA_TELEPORT_COOP_EXIT +ACT_DOTA_SHOPKEEPER_PET_INTERACT = GameActivity_t.ACT_DOTA_SHOPKEEPER_PET_INTERACT +ACT_DOTA_ITEM_PICKUP = GameActivity_t.ACT_DOTA_ITEM_PICKUP +ACT_DOTA_ITEM_DROP = GameActivity_t.ACT_DOTA_ITEM_DROP +ACT_DOTA_CAPTURE_PET = GameActivity_t.ACT_DOTA_CAPTURE_PET +ACT_DOTA_PET_WARD_OBSERVER = GameActivity_t.ACT_DOTA_PET_WARD_OBSERVER +ACT_DOTA_PET_WARD_SENTRY = GameActivity_t.ACT_DOTA_PET_WARD_SENTRY +ACT_DOTA_PET_LEVEL = GameActivity_t.ACT_DOTA_PET_LEVEL +ACT_DOTA_CAST_BURROW_END = GameActivity_t.ACT_DOTA_CAST_BURROW_END +ACT_DOTA_LIFESTEALER_ASSIMILATE = GameActivity_t.ACT_DOTA_LIFESTEALER_ASSIMILATE +ACT_DOTA_LIFESTEALER_EJECT = GameActivity_t.ACT_DOTA_LIFESTEALER_EJECT +ACT_DOTA_ATTACK_EVENT_BASH = GameActivity_t.ACT_DOTA_ATTACK_EVENT_BASH +ACT_DOTA_CAPTURE_RARE = GameActivity_t.ACT_DOTA_CAPTURE_RARE +ACT_DOTA_AW_MAGNETIC_FIELD = GameActivity_t.ACT_DOTA_AW_MAGNETIC_FIELD +ACT_DOTA_CAST_GHOST_SHIP = GameActivity_t.ACT_DOTA_CAST_GHOST_SHIP +ACT_DOTA_FXANIM = GameActivity_t.ACT_DOTA_FXANIM +ACT_DOTA_VICTORY_START = GameActivity_t.ACT_DOTA_VICTORY_START +ACT_DOTA_DEFEAT_START = GameActivity_t.ACT_DOTA_DEFEAT_START +ACT_DOTA_DP_SPIRIT_SIPHON = GameActivity_t.ACT_DOTA_DP_SPIRIT_SIPHON +ACT_DOTA_TRICKS_END = GameActivity_t.ACT_DOTA_TRICKS_END +ACT_DOTA_ES_STONE_CALLER = GameActivity_t.ACT_DOTA_ES_STONE_CALLER +ACT_DOTA_MK_STRIKE = GameActivity_t.ACT_DOTA_MK_STRIKE +ACT_DOTA_VERSUS = GameActivity_t.ACT_DOTA_VERSUS +ACT_DOTA_CAPTURE_CARD = GameActivity_t.ACT_DOTA_CAPTURE_CARD +ACT_DOTA_MK_SPRING_SOAR = GameActivity_t.ACT_DOTA_MK_SPRING_SOAR +ACT_DOTA_MK_SPRING_END = GameActivity_t.ACT_DOTA_MK_SPRING_END +ACT_DOTA_MK_TREE_SOAR = GameActivity_t.ACT_DOTA_MK_TREE_SOAR +ACT_DOTA_MK_TREE_END = GameActivity_t.ACT_DOTA_MK_TREE_END +ACT_DOTA_MK_FUR_ARMY = GameActivity_t.ACT_DOTA_MK_FUR_ARMY +ACT_DOTA_MK_SPRING_CAST = GameActivity_t.ACT_DOTA_MK_SPRING_CAST +ACT_DOTA_NECRO_GHOST_SHROUD = GameActivity_t.ACT_DOTA_NECRO_GHOST_SHROUD +ACT_DOTA_OVERRIDE_ARCANA = GameActivity_t.ACT_DOTA_OVERRIDE_ARCANA +ACT_DOTA_SLIDE = GameActivity_t.ACT_DOTA_SLIDE +ACT_DOTA_SLIDE_LOOP = GameActivity_t.ACT_DOTA_SLIDE_LOOP +ACT_DOTA_GENERIC_CHANNEL_1 = GameActivity_t.ACT_DOTA_GENERIC_CHANNEL_1 +ACT_DOTA_GS_SOUL_CHAIN = GameActivity_t.ACT_DOTA_GS_SOUL_CHAIN +ACT_DOTA_GS_INK_CREATURE = GameActivity_t.ACT_DOTA_GS_INK_CREATURE +ACT_DOTA_TRANSITION = GameActivity_t.ACT_DOTA_TRANSITION +ACT_DOTA_BLINK_DAGGER = GameActivity_t.ACT_DOTA_BLINK_DAGGER +ACT_DOTA_BLINK_DAGGER_END = GameActivity_t.ACT_DOTA_BLINK_DAGGER_END +ACT_DOTA_CUSTOM_TOWER_ATTACK = GameActivity_t.ACT_DOTA_CUSTOM_TOWER_ATTACK +ACT_DOTA_CUSTOM_TOWER_IDLE = GameActivity_t.ACT_DOTA_CUSTOM_TOWER_IDLE +ACT_DOTA_CUSTOM_TOWER_DIE = GameActivity_t.ACT_DOTA_CUSTOM_TOWER_DIE +ACT_DOTA_CAST_COLD_SNAP_ORB = GameActivity_t.ACT_DOTA_CAST_COLD_SNAP_ORB +ACT_DOTA_CAST_GHOST_WALK_ORB = GameActivity_t.ACT_DOTA_CAST_GHOST_WALK_ORB +ACT_DOTA_CAST_TORNADO_ORB = GameActivity_t.ACT_DOTA_CAST_TORNADO_ORB +ACT_DOTA_CAST_EMP_ORB = GameActivity_t.ACT_DOTA_CAST_EMP_ORB +ACT_DOTA_CAST_ALACRITY_ORB = GameActivity_t.ACT_DOTA_CAST_ALACRITY_ORB +ACT_DOTA_CAST_CHAOS_METEOR_ORB = GameActivity_t.ACT_DOTA_CAST_CHAOS_METEOR_ORB +ACT_DOTA_CAST_SUN_STRIKE_ORB = GameActivity_t.ACT_DOTA_CAST_SUN_STRIKE_ORB +ACT_DOTA_CAST_FORGE_SPIRIT_ORB = GameActivity_t.ACT_DOTA_CAST_FORGE_SPIRIT_ORB +ACT_DOTA_CAST_ICE_WALL_ORB = GameActivity_t.ACT_DOTA_CAST_ICE_WALL_ORB +ACT_DOTA_CAST_DEAFENING_BLAST_ORB = GameActivity_t.ACT_DOTA_CAST_DEAFENING_BLAST_ORB +ACT_DOTA_NOTICE = GameActivity_t.ACT_DOTA_NOTICE +ACT_DOTA_CAST_ABILITY_2_ALLY = GameActivity_t.ACT_DOTA_CAST_ABILITY_2_ALLY +ACT_DOTA_SHUFFLE_L = GameActivity_t.ACT_DOTA_SHUFFLE_L +ACT_DOTA_SHUFFLE_R = GameActivity_t.ACT_DOTA_SHUFFLE_R +ACT_DOTA_OVERRIDE_LOADOUT = GameActivity_t.ACT_DOTA_OVERRIDE_LOADOUT +ACT_DOTA_TAUNT_SPECIAL = GameActivity_t.ACT_DOTA_TAUNT_SPECIAL +ACT_DOTA_TELEPORT_START = GameActivity_t.ACT_DOTA_TELEPORT_START +ACT_DOTA_GENERIC_CHANNEL_1_START = GameActivity_t.ACT_DOTA_GENERIC_CHANNEL_1_START +ACT_DOTA_CUSTOM_TOWER_IDLE_RARE = GameActivity_t.ACT_DOTA_CUSTOM_TOWER_IDLE_RARE +ACT_DOTA_CUSTOM_TOWER_TAUNT = GameActivity_t.ACT_DOTA_CUSTOM_TOWER_TAUNT +ACT_DOTA_CUSTOM_TOWER_HIGH_FIVE = GameActivity_t.ACT_DOTA_CUSTOM_TOWER_HIGH_FIVE +ACT_DOTA_ATTACK_SPECIAL = GameActivity_t.ACT_DOTA_ATTACK_SPECIAL +ACT_DOTA_TRANSITION_IDLE = GameActivity_t.ACT_DOTA_TRANSITION_IDLE +ACT_DOTA_PIERCE_THE_VEIL = GameActivity_t.ACT_DOTA_PIERCE_THE_VEIL +ACT_DOTA_RUN_RARE = GameActivity_t.ACT_DOTA_RUN_RARE +ACT_DOTA_VIPER_DIVE = GameActivity_t.ACT_DOTA_VIPER_DIVE +ACT_DOTA_VIPER_DIVE_END = GameActivity_t.ACT_DOTA_VIPER_DIVE_END +ACT_DOTA_MK_STRIKE_END = GameActivity_t.ACT_DOTA_MK_STRIKE_END +ACT_DOTA_SHADOW_VAULT = GameActivity_t.ACT_DOTA_SHADOW_VAULT +ACT_DOTA_KEZ_KATANA_ULT_START = GameActivity_t.ACT_DOTA_KEZ_KATANA_ULT_START +ACT_DOTA_KEZ_KATANA_ULT_CHAIN_A = GameActivity_t.ACT_DOTA_KEZ_KATANA_ULT_CHAIN_A +ACT_DOTA_KEZ_KATANA_ULT_CHAIN_B = GameActivity_t.ACT_DOTA_KEZ_KATANA_ULT_CHAIN_B +ACT_DOTA_KEZ_KATANA_ULT_END = GameActivity_t.ACT_DOTA_KEZ_KATANA_ULT_END +ACT_DOTA_KEZ_KATANA_IMPALE = GameActivity_t.ACT_DOTA_KEZ_KATANA_IMPALE +ACT_DOTA_KEZ_KATANA_IMPALE_FAST = GameActivity_t.ACT_DOTA_KEZ_KATANA_IMPALE_FAST +ACT_DOTA_UNICYCLE = GameActivity_t.ACT_DOTA_UNICYCLE +ACT_DOTA_UNICYCLE_END = GameActivity_t.ACT_DOTA_UNICYCLE_END +ACT_DOTA_MVP_SCREEN = GameActivity_t.ACT_DOTA_MVP_SCREEN +ACT_DOTA_RUN_STATUE = GameActivity_t.ACT_DOTA_RUN_STATUE +ACT_DOTA_CAST1_STATUE = GameActivity_t.ACT_DOTA_CAST1_STATUE +ACT_DOTA_CAST2_STATUE = GameActivity_t.ACT_DOTA_CAST2_STATUE +ACT_DOTA_STUN_STATUE = GameActivity_t.ACT_DOTA_STUN_STATUE +ACT_DOTA_FLAIL_STATUE = GameActivity_t.ACT_DOTA_FLAIL_STATUE +ACT_DOTA_SPAWN_STATUE = GameActivity_t.ACT_DOTA_SPAWN_STATUE +ACT_DOTA_TELEPORT_END_STATUE = GameActivity_t.ACT_DOTA_TELEPORT_END_STATUE +ACT_DOTA_ATTACK_STATUE = GameActivity_t.ACT_DOTA_ATTACK_STATUE +ACT_DOTA_FORCESTAFF_STATUE = GameActivity_t.ACT_DOTA_FORCESTAFF_STATUE +ACT_DOTA_TELEPORT_STATUE = GameActivity_t.ACT_DOTA_TELEPORT_STATUE +ACT_DOTA_VICTORY_STATUE = GameActivity_t.ACT_DOTA_VICTORY_STATUE +ACT_DOTA_TAUNT_STATUE = GameActivity_t.ACT_DOTA_TAUNT_STATUE +ACT_DOTA_DISABLED_END = GameActivity_t.ACT_DOTA_DISABLED_END +ACT_DOTA_CYCLONE = GameActivity_t.ACT_DOTA_CYCLONE +ACT_DOTA_IMPALE = GameActivity_t.ACT_DOTA_IMPALE +ACT_DOTA_TORRENT = GameActivity_t.ACT_DOTA_TORRENT +ACT_DOTA_VOODOO_REST = GameActivity_t.ACT_DOTA_VOODOO_REST +ACT_DOTA_RUN_ALT = GameActivity_t.ACT_DOTA_RUN_ALT +ACT_DOTA_RADIANT_CREEP_HAMMER = GameActivity_t.ACT_DOTA_RADIANT_CREEP_HAMMER +ACT_DOTA_RELAX_IN = GameActivity_t.ACT_DOTA_RELAX_IN +ACT_DOTA_RELAX_OUT = GameActivity_t.ACT_DOTA_RELAX_OUT +ACT_DOTA_CAST_FENCE = GameActivity_t.ACT_DOTA_CAST_FENCE +ACT_DOTA_SPWN = GameActivity_t.ACT_DOTA_SPWN --- (availability: server & client) ---- @alias LuaModifierType ---- | `LUA_MODIFIER_MOTION_NONE` ---- | `LUA_MODIFIER_MOTION_HORIZONTAL` ---- | `LUA_MODIFIER_MOTION_VERTICAL` ---- | `LUA_MODIFIER_MOTION_BOTH` ---- | `LUA_MODIFIER_INVALID` - ---- @type LuaModifierType -LUA_MODIFIER_MOTION_NONE = 0 ---- @type LuaModifierType -LUA_MODIFIER_MOTION_HORIZONTAL = 1 ---- @type LuaModifierType -LUA_MODIFIER_MOTION_VERTICAL = 2 ---- @type LuaModifierType -LUA_MODIFIER_MOTION_BOTH = 3 ---- @type LuaModifierType -LUA_MODIFIER_INVALID = 4 +--- @enum LuaModifierType +--- @field LUA_MODIFIER_MOTION_NONE 0 +--- @field LUA_MODIFIER_MOTION_HORIZONTAL 1 +--- @field LUA_MODIFIER_MOTION_VERTICAL 2 +--- @field LUA_MODIFIER_MOTION_BOTH 3 +--- @field LUA_MODIFIER_INVALID 4 +local LuaModifierType = {} +LUA_MODIFIER_MOTION_NONE = LuaModifierType.LUA_MODIFIER_MOTION_NONE +LUA_MODIFIER_MOTION_HORIZONTAL = LuaModifierType.LUA_MODIFIER_MOTION_HORIZONTAL +LUA_MODIFIER_MOTION_VERTICAL = LuaModifierType.LUA_MODIFIER_MOTION_VERTICAL +LUA_MODIFIER_MOTION_BOTH = LuaModifierType.LUA_MODIFIER_MOTION_BOTH +LUA_MODIFIER_INVALID = LuaModifierType.LUA_MODIFIER_INVALID --- (availability: server & client) ---- @alias modifierfunction ---- | `MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE` # Method Name: `GetModifierPreAttack_BonusDamage` ---- | `MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_TARGET` # Method Name: `GetModifierPreAttack_BonusDamage_Target` ---- | `MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_PROC` # Method Name: `GetModifierPreAttack_BonusDamage_Proc` ---- | `MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_POST_CRIT` # Method Name: `GetModifierPreAttack_BonusDamagePostCrit` ---- | `MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE` # Method Name: `GetModifierBaseAttack_BonusDamage` ---- | `MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PHYSICAL` # Method Name: `GetModifierProcAttack_BonusDamage_Physical` ---- | `MODIFIER_PROPERTY_PROCATTACK_CONVERT_PHYSICAL_TO_MAGICAL` # Method Name: `GetModifierProcAttack_ConvertPhysicalToMagical` ---- | `MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL` # Method Name: `GetModifierProcAttack_BonusDamage_Magical` ---- | `MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PURE` # Method Name: `GetModifierProcAttack_BonusDamage_Pure` ---- | `MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL_TARGET` # Method Name: `GetModifierProcAttack_BonusDamage_Magical_Target` ---- | `MODIFIER_PROPERTY_PROCATTACK_FEEDBACK` # Method Name: `GetModifierProcAttack_Feedback` ---- | `MODIFIER_PROPERTY_OVERRIDE_ATTACK_DAMAGE` # Method Name: `GetModifierOverrideAttackDamage` ---- | `MODIFIER_PROPERTY_PRE_ATTACK` # Method Name: `GetModifierPreAttack` ---- | `MODIFIER_PROPERTY_INVISIBILITY_LEVEL` # Method Name: `GetModifierInvisibilityLevel` ---- | `MODIFIER_PROPERTY_INVISIBILITY_ATTACK_BEHAVIOR_EXCEPTION` # Method Name: `GetModifierInvisibilityAttackBehaviorException` ---- | `MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY` # Method Name: `GetModifierPersistentInvisibility` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT` # Method Name: `GetModifierMoveSpeedBonus_Constant` ---- | `MODIFIER_PROPERTY_MOVESPEED_BASE_OVERRIDE` # Method Name: `GetModifierMoveSpeedOverride` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE` # Method Name: `GetModifierMoveSpeedBonus_Percentage` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE_UNIQUE` # Method Name: `GetModifierMoveSpeedBonus_Percentage_Unique` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE` # Method Name: `GetModifierMoveSpeedBonus_Special_Boots` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE_2` # Method Name: `GetModifierMoveSpeedBonus_Special_Boots_2` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE` # Method Name: `GetModifierMoveSpeedBonus_Constant_Unique` ---- | `MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE_2` # Method Name: `GetModifierMoveSpeedBonus_Constant_Unique_2` ---- | `MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE` # Method Name: `GetModifierMoveSpeed_Absolute` ---- | `MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MIN` # Method Name: `GetModifierMoveSpeed_AbsoluteMin` ---- | `MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MAX` # Method Name: `GetModifierMoveSpeed_AbsoluteMax` ---- | `MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT` # Method Name: `GetModifierIgnoreMovespeedLimit` ---- | `MODIFIER_PROPERTY_MOVESPEED_LIMIT` # Method Name: `GetModifierMoveSpeed_Limit` ---- | `MODIFIER_PROPERTY_ATTACKSPEED_BASE_OVERRIDE` # Method Name: `GetModifierAttackSpeedBaseOverride` ---- | `MODIFIER_PROPERTY_FIXED_ATTACK_RATE` # Method Name: `GetModifierFixedAttackRate` ---- | `MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT` # Method Name: `GetModifierAttackSpeedBonus_Constant` ---- | `MODIFIER_PROPERTY_IGNORE_ATTACKSPEED_LIMIT` # Method Name: `GetModifierAttackSpeed_Limit` ---- | `MODIFIER_PROPERTY_COOLDOWN_REDUCTION_CONSTANT` # Method Name: `GetModifierCooldownReduction_Constant` ---- | `MODIFIER_PROPERTY_MANACOST_REDUCTION_CONSTANT` # Method Name: `GetModifierManacostReduction_Constant` ---- | `MODIFIER_PROPERTY_HEALTHCOST_REDUCTION_CONSTANT` # Method Name: `GetModifierHealthcostReduction_Constant` ---- | `MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT` # Method Name: `GetModifierBaseAttackTimeConstant` ---- | `MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT_ADJUST` # Method Name: `GetModifierBaseAttackTimeConstant_Adjust` ---- | `MODIFIER_PROPERTY_BASE_ATTACK_TIME_PERCENTAGE` # Method Name: `GetModifierBaseAttackTimePercentage` ---- | `MODIFIER_PROPERTY_ATTACK_POINT_CONSTANT` # Method Name: `GetModifierAttackPointConstant` ---- | `MODIFIER_PROPERTY_BONUSDAMAGEOUTGOING_PERCENTAGE` # Method Name: `GetModifierBonusDamageOutgoing_Percentage` ---- | `MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE` # Method Name: `GetModifierDamageOutgoing_Percentage` ---- | `MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION` # Method Name: `GetModifierDamageOutgoing_Percentage_Illusion` ---- | `MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION_AMPLIFY` # Method Name: `GetModifierDamageOutgoing_Percentage_Illusion_Amplify` ---- | `MODIFIER_PROPERTY_TOTALDAMAGEOUTGOING_PERCENTAGE` # Method Name: `GetModifierTotalDamageOutgoing_Percentage` ---- | `MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_CREEP` # Method Name: `GetModifierSpellAmplify_PercentageCreep` ---- | `MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE` # Method Name: `GetModifierSpellAmplify_Percentage` ---- | `MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_UNIQUE` # Method Name: `GetModifierSpellAmplify_PercentageUnique` ---- | `MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE` # Method Name: `GetModifierHealAmplify_PercentageSource` ---- | `MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET` # Method Name: `GetModifierHealAmplify_PercentageTarget` ---- | `MODIFIER_PROPERTY_HP_REGEN_CAN_BE_NEGATIVE` # Method Name: `GetModifierHPRegen_CanBeNegative` ---- | `MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE` # Method Name: `GetModifierHPRegenAmplify_Percentage` ---- | `MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE` # Method Name: `GetModifierLifestealRegenAmplify_Percentage` ---- | `MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE` # Method Name: `GetModifierSpellLifestealRegenAmplify_Percentage` ---- | `MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE` # Method Name: `GetModifierMPRegenAmplify_Percentage` ---- | `MODIFIER_PROPERTY_MANA_DRAIN_AMPLIFY_PERCENTAGE` # Method Name: `GetModifierManaDrainAmplify_Percentage` ---- | `MODIFIER_PROPERTY_MP_RESTORE_AMPLIFY_PERCENTAGE` # Total amplify value is clamped to 0. Method Name: `GetModifierMPRestoreAmplify_Percentage`. ---- | `MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE` # Method Name: `GetModifierBaseDamageOutgoing_Percentage` ---- | `MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE_UNIQUE` # Method Name: `GetModifierBaseDamageOutgoing_PercentageUnique` ---- | `MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE` # Method Name: `GetModifierIncomingDamage_Percentage` ---- | `MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE` # Method Name: `GetModifierIncomingPhysicalDamage_Percentage` ---- | `MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_CONSTANT` # This property controls 'physical' shield, if defined both on client and server. Return value on client should be current shield health, as a positive integer, on server - amount of damage blocked. Method Name: `GetModifierIncomingPhysicalDamageConstant`. ---- | `MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT` # This property controls 'spell' shield, if defined both on client and server. Return value on client should be current shield health, as a positive integer, on server - amount of damage blocked. Method Name: `GetModifierIncomingSpellDamageConstant`. ---- | `MODIFIER_PROPERTY_EVASION_CONSTANT` # Method Name: `GetModifierEvasion_Constant` ---- | `MODIFIER_PROPERTY_NEGATIVE_EVASION_CONSTANT` # Method Name: `GetModifierNegativeEvasion_Constant` ---- | `MODIFIER_PROPERTY_STATUS_RESISTANCE` # Method Name: `GetModifierStatusResistance` ---- | `MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING` # Method Name: `GetModifierStatusResistanceStacking` ---- | `MODIFIER_PROPERTY_STATUS_RESISTANCE_CASTER` # Method Name: `GetModifierStatusResistanceCaster` ---- | `MODIFIER_PROPERTY_AVOID_DAMAGE` # Method Name: `GetModifierAvoidDamage` ---- | `MODIFIER_PROPERTY_AVOID_SPELL` # Method Name: `GetModifierAvoidSpell` ---- | `MODIFIER_PROPERTY_MISS_PERCENTAGE` # Method Name: `GetModifierMiss_Percentage` ---- | `MODIFIER_PROPERTY_PHYSICAL_ARMOR_BASE_PERCENTAGE` # Values above 100% are ignored. Method Name: `GetModifierPhysicalArmorBase_Percentage`. ---- | `MODIFIER_PROPERTY_PHYSICAL_ARMOR_TOTAL_PERCENTAGE` # Method Name: `GetModifierPhysicalArmorTotal_Percentage` ---- | `MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS` # Method Name: `GetModifierPhysicalArmorBonus` ---- | `MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE` # Method Name: `GetModifierPhysicalArmorBonusUnique` ---- | `MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE` # Method Name: `GetModifierPhysicalArmorBonusUniqueActive` ---- | `MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_POST` # Method Name: `GetModifierPhysicalArmorBonusPost` ---- | `MODIFIER_PROPERTY_MIN_PHYSICAL_ARMOR` # Method Name: `GetModifierMinPhysicalArmor` ---- | `MODIFIER_PROPERTY_IGNORE_PHYSICAL_ARMOR` # Method Name: `GetModifierIgnorePhysicalArmor` ---- | `MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BASE_REDUCTION` # Method Name: `GetModifierMagicalResistanceBaseReduction` ---- | `MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DIRECT_MODIFICATION` # Method Name: `GetModifierMagicalResistanceDirectModification` ---- | `MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS` # Method Name: `GetModifierMagicalResistanceBonus` ---- | `MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_ILLUSIONS` # Method Name: `GetModifierMagicalResistanceBonusIllusions` ---- | `MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_UNIQUE` # Method Name: `GetModifierMagicalResistanceBonusUnique` ---- | `MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE` # Method Name: `GetModifierMagicalResistanceDecrepifyUnique` ---- | `MODIFIER_PROPERTY_BASE_MANA_REGEN` # Method Name: `GetModifierBaseRegen` ---- | `MODIFIER_PROPERTY_MANA_REGEN_CONSTANT` # Method Name: `GetModifierConstantManaRegen` ---- | `MODIFIER_PROPERTY_MANA_REGEN_CONSTANT_UNIQUE` # Method Name: `GetModifierConstantManaRegenUnique` ---- | `MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE` # Method Name: `GetModifierTotalPercentageManaRegen` ---- | `MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT` # Method Name: `GetModifierConstantHealthRegen` ---- | `MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE` # Method Name: `GetModifierHealthRegenPercentage` ---- | `MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE_UNIQUE` # Method Name: `GetModifierHealthRegenPercentageUnique` ---- | `MODIFIER_PROPERTY_HEALTH_BONUS` # Method Name: `GetModifierHealthBonus` ---- | `MODIFIER_PROPERTY_MANA_BONUS` # Method Name: `GetModifierManaBonus` ---- | `MODIFIER_PROPERTY_EXTRA_STRENGTH_BONUS` # Method Name: `GetModifierExtraStrengthBonus` ---- | `MODIFIER_PROPERTY_EXTRA_HEALTH_BONUS` # Method Name: `GetModifierExtraHealthBonus` ---- | `MODIFIER_PROPERTY_EXTRA_MANA_BONUS` # Method Name: `GetModifierExtraManaBonus` ---- | `MODIFIER_PROPERTY_EXTRA_MANA_BONUS_PERCENTAGE` # Method Name: `GetModifierExtraManaBonusPercentage` ---- | `MODIFIER_PROPERTY_EXTRA_HEALTH_PERCENTAGE` # Method Name: `GetModifierExtraHealthPercentage` ---- | `MODIFIER_PROPERTY_EXTRA_MANA_PERCENTAGE` # Method Name: `GetModifierExtraManaPercentage` ---- | `MODIFIER_PROPERTY_STATS_STRENGTH_BONUS` # Method Name: `GetModifierBonusStats_Strength` ---- | `MODIFIER_PROPERTY_STATS_AGILITY_BONUS` # Method Name: `GetModifierBonusStats_Agility` ---- | `MODIFIER_PROPERTY_STATS_INTELLECT_BONUS` # Method Name: `GetModifierBonusStats_Intellect` ---- | `MODIFIER_PROPERTY_STATS_STRENGTH_BONUS_PERCENTAGE` # Method Name: `GetModifierBonusStats_Strength_Percentage` ---- | `MODIFIER_PROPERTY_STATS_AGILITY_BONUS_PERCENTAGE` # Method Name: `GetModifierBonusStats_Agility_Percentage` ---- | `MODIFIER_PROPERTY_STATS_INTELLECT_BONUS_PERCENTAGE` # Method Name: `GetModifierBonusStats_Intellect_Percentage` ---- | `MODIFIER_PROPERTY_CAST_RANGE_BONUS` # Method Name: `GetModifierCastRangeBonus` ---- | `MODIFIER_PROPERTY_CAST_RANGE_BONUS_PERCENTAGE` # Method Name: `GetModifierCastRangeBonusPercentage` ---- | `MODIFIER_PROPERTY_CAST_RANGE_BONUS_TARGET` # Method Name: `GetModifierCastRangeBonusTarget` ---- | `MODIFIER_PROPERTY_CAST_RANGE_BONUS_STACKING` # Method Name: `GetModifierCastRangeBonusStacking` ---- | `MODIFIER_PROPERTY_ATTACK_RANGE_BASE_OVERRIDE` # Method Name: `GetModifierAttackRangeOverride` ---- | `MODIFIER_PROPERTY_ATTACK_RANGE_BONUS` # Method Name: `GetModifierAttackRangeBonus` ---- | `MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_UNIQUE` # Method Name: `GetModifierAttackRangeBonusUnique` ---- | `MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_PERCENTAGE` # Method Name: `GetModifierAttackRangeBonusPercentage` ---- | `MODIFIER_PROPERTY_MAX_ATTACK_RANGE` # Method Name: `GetModifierMaxAttackRange` ---- | `MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS` # Method Name: `GetModifierProjectileSpeedBonus` ---- | `MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS_PERCENTAGE` # Method Name: `GetModifierProjectileSpeedBonusPercentage` ---- | `MODIFIER_PROPERTY_PROJECTILE_NAME` # Method Name: `GetModifierProjectileName` ---- | `MODIFIER_PROPERTY_REINCARNATION` # Method Name: `ReincarnateTime` ---- | `MODIFIER_PROPERTY_REINCARNATION_SUPPRESS_FX` # Method Name: `ReincarnateSuppressFX` ---- | `MODIFIER_PROPERTY_RESPAWNTIME` # Method Name: `GetModifierConstantRespawnTime` ---- | `MODIFIER_PROPERTY_RESPAWNTIME_PERCENTAGE` # Method Name: `GetModifierPercentageRespawnTime` ---- | `MODIFIER_PROPERTY_RESPAWNTIME_STACKING` # Method Name: `GetModifierStackingRespawnTime` ---- | `MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE` # Method Name: `GetModifierPercentageCooldown` ---- | `MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_ONGOING` # Method Name: `GetModifierPercentageCooldownOngoing` ---- | `MODIFIER_PROPERTY_CASTTIME_PERCENTAGE` # Method Name: `GetModifierPercentageCasttime` ---- | `MODIFIER_PROPERTY_ATTACK_ANIM_TIME_PERCENTAGE` # Method Name: `GetModifierPercentageAttackAnimTime` ---- | `MODIFIER_PROPERTY_MANACOST_PERCENTAGE` # Method Name: `GetModifierPercentageManacost` ---- | `MODIFIER_PROPERTY_MANACOST_PERCENTAGE_STACKING` # Method Name: `GetModifierPercentageManacostStacking` ---- | `MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE` # Method Name: `GetModifierPercentageHealthcost` ---- | `MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE_STACKING` # Method Name: `GetModifierPercentageHealthcostStacking` ---- | `MODIFIER_PROPERTY_DEATHGOLDCOST` # Method Name: `GetModifierConstantDeathGoldCost` ---- | `MODIFIER_PROPERTY_EXP_RATE_BOOST` # Method Name: `GetModifierPercentageExpRateBoost` ---- | `MODIFIER_PROPERTY_GOLD_RATE_BOOST` # Method Name: `GetModifierPercentageGoldRateBoost` ---- | `MODIFIER_PROPERTY_PREATTACK_CRITICALSTRIKE` # Method Name: `GetModifierPreAttack_CriticalStrike` ---- | `MODIFIER_PROPERTY_PREATTACK_TARGET_CRITICALSTRIKE` # Method Name: `GetModifierPreAttack_Target_CriticalStrike` ---- | `MODIFIER_PROPERTY_MAGICAL_CONSTANT_BLOCK` # Method Name: `GetModifierMagical_ConstantBlock` ---- | `MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK` # Method Name: `GetModifierPhysical_ConstantBlock` ---- | `MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK_SPECIAL` # Method Name: `GetModifierPhysical_ConstantBlockSpecial` ---- | `MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR` # Method Name: `GetModifierPhysical_ConstantBlockUnavoidablePreArmor` ---- | `MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK` # Method Name: `GetModifierTotal_ConstantBlock` ---- | `MODIFIER_PROPERTY_OVERRIDE_ANIMATION` # Method Name: `GetOverrideAnimation` ---- | `MODIFIER_PROPERTY_OVERRIDE_ANIMATION_WEIGHT` # Method Name: `GetOverrideAnimationWeight` ---- | `MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE` # Method Name: `GetOverrideAnimationRate` ---- | `MODIFIER_PROPERTY_ABSORB_SPELL` # Method Name: `GetAbsorbSpell` ---- | `MODIFIER_PROPERTY_REFLECT_SPELL` # Method Name: `GetReflectSpell` ---- | `MODIFIER_PROPERTY_DISABLE_AUTOATTACK` # Method Name: `GetDisableAutoAttack` ---- | `MODIFIER_PROPERTY_BONUS_DAY_VISION` # Method Name: `GetBonusDayVision` ---- | `MODIFIER_PROPERTY_BONUS_DAY_VISION_PERCENTAGE` # Method Name: `GetBonusDayVisionPercentage` ---- | `MODIFIER_PROPERTY_BONUS_NIGHT_VISION` # Method Name: `GetBonusNightVision` ---- | `MODIFIER_PROPERTY_BONUS_NIGHT_VISION_UNIQUE` # Method Name: `GetBonusNightVisionUnique` ---- | `MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE` # Method Name: `GetBonusVisionPercentage` ---- | `MODIFIER_PROPERTY_FIXED_DAY_VISION` # Method Name: `GetFixedDayVision` ---- | `MODIFIER_PROPERTY_FIXED_NIGHT_VISION` # Method Name: `GetFixedNightVision` ---- | `MODIFIER_PROPERTY_MIN_HEALTH` # Method Name: `GetMinHealth` ---- | `MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL` # Method Name: `GetAbsoluteNoDamagePhysical` ---- | `MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL` # Method Name: `GetAbsoluteNoDamageMagical` ---- | `MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE` # Method Name: `GetAbsoluteNoDamagePure` ---- | `MODIFIER_PROPERTY_IS_ILLUSION` # Method Name: `GetIsIllusion` ---- | `MODIFIER_PROPERTY_ILLUSION_LABEL` # Method Name: `GetModifierIllusionLabel` ---- | `MODIFIER_PROPERTY_STRONG_ILLUSION` # Method Name: `GetModifierStrongIllusion` ---- | `MODIFIER_PROPERTY_SUPER_ILLUSION` # Method Name: `GetModifierSuperIllusion` ---- | `MODIFIER_PROPERTY_SUPER_ILLUSION_WITH_ULTIMATE` # Method Name: `GetModifierSuperIllusionWithUltimate` ---- | `MODIFIER_PROPERTY_XP_DURING_DEATH` # Method Name: `GetModifierXPDuringDeath` ---- | `MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE` # Method Name: `GetModifierTurnRate_Percentage` ---- | `MODIFIER_PROPERTY_TURN_RATE_OVERRIDE` # Method Name: `GetModifierTurnRate_Override` ---- | `MODIFIER_PROPERTY_DISABLE_HEALING` # Method Name: `GetDisableHealing` ---- | `MODIFIER_PROPERTY_ALWAYS_ALLOW_ATTACK` # Method Name: `GetAlwaysAllowAttack` ---- | `MODIFIER_PROPERTY_ALWAYS_ETHEREAL_ATTACK` # Method Name: `GetAllowEtherealAttack` ---- | `MODIFIER_PROPERTY_OVERRIDE_ATTACK_MAGICAL` # Method Name: `GetOverrideAttackMagical` ---- | `MODIFIER_PROPERTY_UNIT_STATS_NEEDS_REFRESH` # Method Name: `GetModifierUnitStatsNeedsRefresh` ---- | `MODIFIER_PROPERTY_BOUNTY_CREEP_MULTIPLIER` ---- | `MODIFIER_PROPERTY_BOUNTY_OTHER_MULTIPLIER` ---- | `MODIFIER_PROPERTY_UNIT_DISALLOW_UPGRADING` # Method Name: `GetModifierUnitDisllowUpgrading` ---- | `MODIFIER_PROPERTY_DODGE_PROJECTILE` # Method Name: `GetModifierDodgeProjectile` ---- | `MODIFIER_PROPERTY_TRIGGER_COSMETIC_AND_END_ATTACK` # Method Name: `GetTriggerCosmeticAndEndAttack` ---- | `MODIFIER_PROPERTY_MAX_DEBUFF_DURATION` # Method Name: `GetModifierMaxDebuffDuration` ---- | `MODIFIER_PROPERTY_PRIMARY_STAT_DAMAGE_MULTIPLIER` # Method Name: `GetPrimaryStatDamageMultiplier` ---- | `MODIFIER_PROPERTY_PREATTACK_DEADLY_BLOW` # Method Name: `GetModifierPreAttack_DeadlyBlow` ---- | `MODIFIER_PROPERTY_ALWAYS_AUTOATTACK_WHILE_HOLD_POSITION` # Method Name: `GetAlwaysAutoAttackWhileHoldPosition` ---- | `MODIFIER_EVENT_ON_SPELL_TARGET_READY` # Method Name: `OnSpellTargetReady` ---- | `MODIFIER_EVENT_ON_ATTACK_RECORD` # Method Name: `OnAttackRecord` ---- | `MODIFIER_EVENT_ON_ATTACK_START` # Method Name: `OnAttackStart` ---- | `MODIFIER_EVENT_ON_ATTACK` # Method Name: `OnAttack` ---- | `MODIFIER_EVENT_ON_ATTACK_LANDED` # Method Name: `OnAttackLanded` ---- | `MODIFIER_EVENT_ON_ATTACK_FAIL` # Method Name: `OnAttackFail` ---- | `MODIFIER_EVENT_ON_ATTACK_ALLIED` # Happens even if attack can't be issued. Method Name: `OnAttackAllied`. ---- | `MODIFIER_EVENT_ON_PROJECTILE_DODGE` # Method Name: `OnProjectileDodge` ---- | `MODIFIER_EVENT_ON_ORDER` # Method Name: `OnOrder` ---- | `MODIFIER_EVENT_ON_UNIT_MOVED` # Method Name: `OnUnitMoved` ---- | `MODIFIER_EVENT_ON_ABILITY_START` # Method Name: `OnAbilityStart` ---- | `MODIFIER_EVENT_ON_ABILITY_EXECUTED` # Method Name: `OnAbilityExecuted` ---- | `MODIFIER_EVENT_ON_ABILITY_FULLY_CAST` # Method Name: `OnAbilityFullyCast` ---- | `MODIFIER_EVENT_ON_BREAK_INVISIBILITY` # Method Name: `OnBreakInvisibility` ---- | `MODIFIER_EVENT_ON_ABILITY_END_CHANNEL` # Method Name: `OnAbilityEndChannel` ---- | `MODIFIER_EVENT_ON_PROCESS_UPGRADE` ---- | `MODIFIER_EVENT_ON_REFRESH` ---- | `MODIFIER_EVENT_ON_TAKEDAMAGE` # Method Name: `OnTakeDamage` ---- | `MODIFIER_EVENT_ON_DEATH_PREVENTED` # Method Name: `OnDamagePrevented` ---- | `MODIFIER_EVENT_ON_STATE_CHANGED` # Method Name: `OnStateChanged` ---- | `MODIFIER_EVENT_ON_ORB_EFFECT` ---- | `MODIFIER_EVENT_ON_PROCESS_CLEAVE` # Method Name: `OnProcessCleave` ---- | `MODIFIER_EVENT_ON_DAMAGE_CALCULATED` # Method Name: `OnDamageCalculated` ---- | `MODIFIER_EVENT_ON_MAGIC_DAMAGE_CALCULATED` # Method Name: `OnMagicDamageCalculated` ---- | `MODIFIER_EVENT_ON_ATTACKED` # Method Name: `OnAttacked` ---- | `MODIFIER_EVENT_ON_DEATH` # Method Name: `OnDeath` ---- | `MODIFIER_EVENT_ON_DEATH_COMPLETED` # Method Name: `OnDeathCompleted` ---- | `MODIFIER_EVENT_ON_RESPAWN` # Method Name: `OnRespawn` ---- | `MODIFIER_EVENT_ON_SPENT_MANA` # Method Name: `OnSpentMana` ---- | `MODIFIER_EVENT_ON_SPENT_HEALTH` # Method Name: `OnSpentHealth` ---- | `MODIFIER_EVENT_ON_TELEPORTING` # Method Name: `OnTeleporting` ---- | `MODIFIER_EVENT_ON_TELEPORTED` # Method Name: `OnTeleported` ---- | `MODIFIER_EVENT_ON_SET_LOCATION` # Method Name: `OnSetLocation` ---- | `MODIFIER_EVENT_ON_HEALTH_GAINED` # Method Name: `OnHealthGained` ---- | `MODIFIER_EVENT_ON_MANA_GAINED` # Method Name: `OnManaGained` ---- | `MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT` # Method Name: `OnTakeDamageKillCredit` ---- | `MODIFIER_EVENT_ON_HERO_KILLED` # Method Name: `OnHeroKilled` ---- | `MODIFIER_EVENT_ON_HEAL_RECEIVED` # Method Name: `OnHealReceived` ---- | `MODIFIER_EVENT_ON_BUILDING_KILLED` # Method Name: `OnBuildingKilled` ---- | `MODIFIER_EVENT_ON_MODEL_CHANGED` # Method Name: `OnModelChanged` ---- | `MODIFIER_EVENT_ON_MODIFIER_ADDED` # Method Name: `OnModifierAdded` ---- | `MODIFIER_PROPERTY_TOOLTIP` # Method Name: `OnTooltip` ---- | `MODIFIER_PROPERTY_MODEL_CHANGE` # Method Name: `GetModifierModelChange` ---- | `MODIFIER_PROPERTY_MODEL_SCALE` # Method Name: `GetModifierModelScale` ---- | `MODIFIER_PROPERTY_MODEL_SCALE_ANIMATE_TIME` # Method Name: `GetModifierModelScaleAnimateTime` ---- | `MODIFIER_PROPERTY_MODEL_SCALE_USE_IN_OUT_EASE` # Method Name: `GetModifierModelScaleUseInOutEase` ---- | `MODIFIER_PROPERTY_MODEL_SCALE_CONSTANT` # Method Name: `GetModifierModelScaleConstant` ---- | `MODIFIER_PROPERTY_IS_SCEPTER` # Applies scepter when this property is active Method Name: `GetModifierScepter`. ---- | `MODIFIER_PROPERTY_IS_SHARD` # Applies shard when this property is active Method Name: `GetModifierShard`. ---- | `MODIFIER_PROPERTY_RADAR_COOLDOWN_REDUCTION` # Method Name: `GetModifierRadarCooldownReduction` ---- | `MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS` # Method Name: `GetActivityTranslationModifiers` ---- | `MODIFIER_PROPERTY_TRANSLATE_ATTACK_SOUND` # Method Name: `GetAttackSound` ---- | `MODIFIER_PROPERTY_LIFETIME_FRACTION` # Method Name: `GetUnitLifetimeFraction` ---- | `MODIFIER_PROPERTY_PROVIDES_FOW_POSITION` # Method Name: `GetModifierProvidesFOWVision` ---- | `MODIFIER_PROPERTY_SPELLS_REQUIRE_HP` # Method Name: `GetModifierSpellsRequireHP` ---- | `MODIFIER_PROPERTY_FORCE_DRAW_MINIMAP` # Method Name: `GetForceDrawOnMinimap` ---- | `MODIFIER_PROPERTY_DISABLE_TURNING` # Method Name: `GetModifierDisableTurning` ---- | `MODIFIER_PROPERTY_IGNORE_CAST_ANGLE` # Method Name: `GetModifierIgnoreCastAngle` ---- | `MODIFIER_PROPERTY_CHANGE_ABILITY_VALUE` # Method Name: `GetModifierChangeAbilityValue` ---- | `MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL` # Method Name: `GetModifierOverrideAbilitySpecial` ---- | `MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL_VALUE` # Method Name: `GetModifierOverrideAbilitySpecialValue` ---- | `MODIFIER_PROPERTY_ABILITY_LAYOUT` # Method Name: `GetModifierAbilityLayout` ---- | `MODIFIER_EVENT_ON_DOMINATED` # Method Name: `OnDominated` ---- | `MODIFIER_EVENT_ON_KILL` # Method Name: `OnKill` ---- | `MODIFIER_EVENT_ON_ASSIST` # Method Name: `OnAssist` ---- | `MODIFIER_PROPERTY_TEMPEST_DOUBLE` # Method Name: `GetModifierTempestDouble` ---- | `MODIFIER_PROPERTY_PRESERVE_PARTICLES_ON_MODEL_CHANGE` # Method Name: `PreserveParticlesOnModelChanged` ---- | `MODIFIER_EVENT_ON_ATTACK_FINISHED` # Method Name: `OnAttackFinished` ---- | `MODIFIER_PROPERTY_IGNORE_COOLDOWN` # Method Name: `GetModifierIgnoreCooldown` ---- | `MODIFIER_PROPERTY_CAN_ATTACK_TREES` # Method Name: `GetModifierCanAttackTrees` ---- | `MODIFIER_PROPERTY_VISUAL_Z_DELTA` # Method Name: `GetVisualZDelta` ---- | `MODIFIER_PROPERTY_VISUAL_Z_SPEED_BASE_OVERRIDE` # Method Name: `GetVisualZSpeedBaseOverride` ---- | `MODIFIER_PROPERTY_INCOMING_DAMAGE_ILLUSION` ---- | `MODIFIER_PROPERTY_DONT_GIVE_VISION_OF_ATTACKER` # Method Name: `GetModifierNoVisionOfAttacker` ---- | `MODIFIER_PROPERTY_TOOLTIP2` # Method Name: `OnTooltip2` ---- | `MODIFIER_EVENT_ON_ATTACK_RECORD_DESTROY` # Method Name: `OnAttackRecordDestroy` ---- | `MODIFIER_EVENT_ON_PROJECTILE_OBSTRUCTION_HIT` # Method Name: `OnProjectileObstructionHit` ---- | `MODIFIER_PROPERTY_SUPPRESS_TELEPORT` # Method Name: `GetSuppressTeleport` ---- | `MODIFIER_EVENT_ON_ATTACK_CANCELLED` # Method Name: `OnAttackCancelled` ---- | `MODIFIER_PROPERTY_SUPPRESS_CLEAVE` # Method Name: `GetSuppressCleave` ---- | `MODIFIER_PROPERTY_BOT_ATTACK_SCORE_BONUS` # Method Name: `BotAttackScoreBonus` ---- | `MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE` # Method Name: `GetModifierAttackSpeedReductionPercentage` ---- | `MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE` # Method Name: `GetModifierMoveSpeedReductionPercentage` ---- | `MODIFIER_PROPERTY_ATTACK_WHILE_MOVING_TARGET` ---- | `MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE` # Method Name: `GetModifierAttackSpeedPercentage` ---- | `MODIFIER_EVENT_ON_ATTEMPT_PROJECTILE_DODGE` # Method Name: `OnAttemptProjectileDodge` ---- | `MODIFIER_EVENT_ON_PREDEBUFF_APPLIED` # Method Name: `OnPreDebuffApplied` ---- | `MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_STACKING` # Method Name: `GetModifierPercentageCooldownStacking` ---- | `MODIFIER_PROPERTY_SPELL_REDIRECT_TARGET` # Method Name: `GetModifierSpellRedirectTarget` ---- | `MODIFIER_PROPERTY_TURN_RATE_CONSTANT` # Method Name: `GetModifierTurnRateConstant` ---- | `MODIFIER_PROPERTY_RAT_PACK` # Method Name: `GetModifierIsRatPack` ---- | `MODIFIER_PROPERTY_PHYSICALDAMAGEOUTGOING_PERCENTAGE` # Method Name: `GetModifierPhysicalDamageOutgoing_Percentage` ---- | `MODIFIER_PROPERTY_KNOCKBACK_AMPLIFICATION_PERCENTAGE` # Method Name: `GetModifierKnockbackAmplification_Percentage` ---- | `MODIFIER_PROPERTY_HEALTHBAR_PIPS` # Return value is a count of pips. Method Name: `GetModifierHealthBarPips`. ---- | `MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT` # This property controls 'universal' shield, if defined both on client and server. Return value on client should be current shield health, as a positive integer, on server - amount of damage blocked. Method Name: `GetModifierIncomingDamageConstant`. ---- | `MODIFIER_EVENT_SPELL_APPLIED_SUCCESSFULLY` # Method Name: `OnSpellAppliedSuccessfully` ---- | `MODIFIER_PROPERTY_AVOID_DAMAGE_AFTER_REDUCTIONS` # Method Name: `GetModifierAvoidDamageAfterReductions` ---- | `MODIFIER_PROPERTY_FAIL_ATTACK` # Method Name: `GetModifierPropetyFailAttack` ---- | `MODIFIER_PROPERTY_PREREDUCE_INCOMING_DAMAGE_MULT` # Method Name: `GetModifierPrereduceIncomingDamage_Mult` ---- | `MODIFIER_PROPERTY_SUPPRESS_FULLSCREEN_DEATH_FX` # Method Name: `GetModifierSuppressFullscreenDeathFX` ---- | `MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST` # Method Name: `MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST` ---- | `MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_MULTIPLICATIVE` # Method Name: `GetModifierDamageOutgoing_PercentageMultiplicative` ---- | `MODIFIER_PROPERTY_TICK_GOLD_MULTIPLIER` # Method Name: `GetModifierTickGold_Multiplier` ---- | `MODIFIER_PROPERTY_SLOW_RESISTANCE` # Method Name: `GetModifierSlowResistance` ---- | `MODIFIER_PROPERTY_AOE_BONUS_PERCENTAGE` # Method Name: `GetModifierAoEBonusPercentage` ---- | `MODIFIER_PROPERTY_PROJECTILE_SPEED` # Method Name: `GetModifierProjectileSpeed` ---- | `MODIFIER_PROPERTY_BECOME_UNIVERSAL` # Method Name: `GetModifierBecomeUniversal` ---- | `MODIFIER_EVENT_ON_FORCE_PROC_MAGIC_STICK` # Method Name: `OnForceProcMagicStick` ---- | `MODIFIER_PROPERTY_DO_NOT_SINK_AFTER_DEATH` # Method Name: `GetModifierDoNotSinkAfterDeath` ---- | `MODIFIER_EVENT_ON_DAMAGE_HPLOSS` # Method Name: `OnDamageHPLoss` ---- | `MODIFIER_PROPERTY_FORCE_MAX_HEALTH` # Method Name: `GetModifierForceMaxHealth` ---- | `MODIFIER_PROPERTY_AOE_BONUS_CONSTANT` # Method Name: `GetModifierAoEBonusConstant` ---- | `MODIFIER_FUNCTION_LAST` ---- | `MODIFIER_FUNCTION_INVALID` - ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE = 0 ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_TARGET = 1 ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_PROC = 2 ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_POST_CRIT = 3 ---- @type modifierfunction -MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE = 4 ---- @type modifierfunction -MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PHYSICAL = 5 ---- @type modifierfunction -MODIFIER_PROPERTY_PROCATTACK_CONVERT_PHYSICAL_TO_MAGICAL = 6 ---- @type modifierfunction -MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL = 7 ---- @type modifierfunction -MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PURE = 8 ---- @type modifierfunction -MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL_TARGET = 9 ---- @type modifierfunction -MODIFIER_PROPERTY_PROCATTACK_FEEDBACK = 10 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ATTACK_DAMAGE = 11 ---- @type modifierfunction -MODIFIER_PROPERTY_PRE_ATTACK = 12 ---- @type modifierfunction -MODIFIER_PROPERTY_INVISIBILITY_LEVEL = 13 ---- @type modifierfunction -MODIFIER_PROPERTY_INVISIBILITY_ATTACK_BEHAVIOR_EXCEPTION = 14 ---- @type modifierfunction -MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY = 15 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT = 16 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BASE_OVERRIDE = 17 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE = 18 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE_UNIQUE = 19 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE = 20 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE_2 = 21 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE = 22 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE_2 = 23 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE = 24 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MIN = 25 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MAX = 26 ---- @type modifierfunction -MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT = 27 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_LIMIT = 28 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACKSPEED_BASE_OVERRIDE = 29 ---- @type modifierfunction -MODIFIER_PROPERTY_FIXED_ATTACK_RATE = 30 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT = 31 ---- @type modifierfunction -MODIFIER_PROPERTY_IGNORE_ATTACKSPEED_LIMIT = 32 ---- @type modifierfunction -MODIFIER_PROPERTY_COOLDOWN_REDUCTION_CONSTANT = 33 ---- @type modifierfunction -MODIFIER_PROPERTY_MANACOST_REDUCTION_CONSTANT = 34 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTHCOST_REDUCTION_CONSTANT = 35 ---- @type modifierfunction -MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT = 36 ---- @type modifierfunction -MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT_ADJUST = 37 ---- @type modifierfunction -MODIFIER_PROPERTY_BASE_ATTACK_TIME_PERCENTAGE = 38 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_POINT_CONSTANT = 39 ---- @type modifierfunction -MODIFIER_PROPERTY_BONUSDAMAGEOUTGOING_PERCENTAGE = 40 ---- @type modifierfunction -MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE = 41 ---- @type modifierfunction -MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION = 42 ---- @type modifierfunction -MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION_AMPLIFY = 43 ---- @type modifierfunction -MODIFIER_PROPERTY_TOTALDAMAGEOUTGOING_PERCENTAGE = 44 ---- @type modifierfunction -MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_CREEP = 45 ---- @type modifierfunction -MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE = 46 ---- @type modifierfunction -MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_UNIQUE = 47 ---- @type modifierfunction -MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE = 48 ---- @type modifierfunction -MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET = 49 ---- @type modifierfunction -MODIFIER_PROPERTY_HP_REGEN_CAN_BE_NEGATIVE = 50 ---- @type modifierfunction -MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE = 51 ---- @type modifierfunction -MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE = 52 ---- @type modifierfunction -MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE = 53 ---- @type modifierfunction -MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE = 54 ---- @type modifierfunction -MODIFIER_PROPERTY_MANA_DRAIN_AMPLIFY_PERCENTAGE = 55 ---- @type modifierfunction -MODIFIER_PROPERTY_MP_RESTORE_AMPLIFY_PERCENTAGE = 56 ---- @type modifierfunction -MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE = 57 ---- @type modifierfunction -MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE_UNIQUE = 58 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE = 59 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE = 60 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_CONSTANT = 61 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT = 62 ---- @type modifierfunction -MODIFIER_PROPERTY_EVASION_CONSTANT = 63 ---- @type modifierfunction -MODIFIER_PROPERTY_NEGATIVE_EVASION_CONSTANT = 64 ---- @type modifierfunction -MODIFIER_PROPERTY_STATUS_RESISTANCE = 65 ---- @type modifierfunction -MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING = 66 ---- @type modifierfunction -MODIFIER_PROPERTY_STATUS_RESISTANCE_CASTER = 67 ---- @type modifierfunction -MODIFIER_PROPERTY_AVOID_DAMAGE = 68 ---- @type modifierfunction -MODIFIER_PROPERTY_AVOID_SPELL = 69 ---- @type modifierfunction -MODIFIER_PROPERTY_MISS_PERCENTAGE = 70 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_ARMOR_BASE_PERCENTAGE = 71 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_ARMOR_TOTAL_PERCENTAGE = 72 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS = 73 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE = 74 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE = 75 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_POST = 76 ---- @type modifierfunction -MODIFIER_PROPERTY_MIN_PHYSICAL_ARMOR = 77 ---- @type modifierfunction -MODIFIER_PROPERTY_IGNORE_PHYSICAL_ARMOR = 78 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BASE_REDUCTION = 79 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DIRECT_MODIFICATION = 80 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS = 81 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_ILLUSIONS = 82 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_UNIQUE = 83 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE = 84 ---- @type modifierfunction -MODIFIER_PROPERTY_BASE_MANA_REGEN = 85 ---- @type modifierfunction -MODIFIER_PROPERTY_MANA_REGEN_CONSTANT = 86 ---- @type modifierfunction -MODIFIER_PROPERTY_MANA_REGEN_CONSTANT_UNIQUE = 87 ---- @type modifierfunction -MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE = 88 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT = 89 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE = 90 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE_UNIQUE = 91 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTH_BONUS = 92 ---- @type modifierfunction -MODIFIER_PROPERTY_MANA_BONUS = 93 ---- @type modifierfunction -MODIFIER_PROPERTY_EXTRA_STRENGTH_BONUS = 94 ---- @type modifierfunction -MODIFIER_PROPERTY_EXTRA_HEALTH_BONUS = 95 ---- @type modifierfunction -MODIFIER_PROPERTY_EXTRA_MANA_BONUS = 96 ---- @type modifierfunction -MODIFIER_PROPERTY_EXTRA_MANA_BONUS_PERCENTAGE = 97 ---- @type modifierfunction -MODIFIER_PROPERTY_EXTRA_HEALTH_PERCENTAGE = 98 ---- @type modifierfunction -MODIFIER_PROPERTY_EXTRA_MANA_PERCENTAGE = 99 ---- @type modifierfunction -MODIFIER_PROPERTY_STATS_STRENGTH_BONUS = 100 ---- @type modifierfunction -MODIFIER_PROPERTY_STATS_AGILITY_BONUS = 101 ---- @type modifierfunction -MODIFIER_PROPERTY_STATS_INTELLECT_BONUS = 102 ---- @type modifierfunction -MODIFIER_PROPERTY_STATS_STRENGTH_BONUS_PERCENTAGE = 103 ---- @type modifierfunction -MODIFIER_PROPERTY_STATS_AGILITY_BONUS_PERCENTAGE = 104 ---- @type modifierfunction -MODIFIER_PROPERTY_STATS_INTELLECT_BONUS_PERCENTAGE = 105 ---- @type modifierfunction -MODIFIER_PROPERTY_CAST_RANGE_BONUS = 106 ---- @type modifierfunction -MODIFIER_PROPERTY_CAST_RANGE_BONUS_PERCENTAGE = 107 ---- @type modifierfunction -MODIFIER_PROPERTY_CAST_RANGE_BONUS_TARGET = 108 ---- @type modifierfunction -MODIFIER_PROPERTY_CAST_RANGE_BONUS_STACKING = 109 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_RANGE_BASE_OVERRIDE = 110 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_RANGE_BONUS = 111 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_UNIQUE = 112 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_PERCENTAGE = 113 ---- @type modifierfunction -MODIFIER_PROPERTY_MAX_ATTACK_RANGE = 114 ---- @type modifierfunction -MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS = 115 ---- @type modifierfunction -MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS_PERCENTAGE = 116 ---- @type modifierfunction -MODIFIER_PROPERTY_PROJECTILE_NAME = 117 ---- @type modifierfunction -MODIFIER_PROPERTY_REINCARNATION = 118 ---- @type modifierfunction -MODIFIER_PROPERTY_REINCARNATION_SUPPRESS_FX = 119 ---- @type modifierfunction -MODIFIER_PROPERTY_RESPAWNTIME = 120 ---- @type modifierfunction -MODIFIER_PROPERTY_RESPAWNTIME_PERCENTAGE = 121 ---- @type modifierfunction -MODIFIER_PROPERTY_RESPAWNTIME_STACKING = 122 ---- @type modifierfunction -MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE = 123 ---- @type modifierfunction -MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_ONGOING = 124 ---- @type modifierfunction -MODIFIER_PROPERTY_CASTTIME_PERCENTAGE = 125 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_ANIM_TIME_PERCENTAGE = 126 ---- @type modifierfunction -MODIFIER_PROPERTY_MANACOST_PERCENTAGE = 127 ---- @type modifierfunction -MODIFIER_PROPERTY_MANACOST_PERCENTAGE_STACKING = 128 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE = 129 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE_STACKING = 130 ---- @type modifierfunction -MODIFIER_PROPERTY_DEATHGOLDCOST = 131 ---- @type modifierfunction -MODIFIER_PROPERTY_EXP_RATE_BOOST = 132 ---- @type modifierfunction -MODIFIER_PROPERTY_GOLD_RATE_BOOST = 133 ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_CRITICALSTRIKE = 134 ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_TARGET_CRITICALSTRIKE = 135 ---- @type modifierfunction -MODIFIER_PROPERTY_MAGICAL_CONSTANT_BLOCK = 136 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK = 137 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK_SPECIAL = 138 ---- @type modifierfunction -MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR = 139 ---- @type modifierfunction -MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK = 140 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ANIMATION = 141 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ANIMATION_WEIGHT = 142 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE = 143 ---- @type modifierfunction -MODIFIER_PROPERTY_ABSORB_SPELL = 144 ---- @type modifierfunction -MODIFIER_PROPERTY_REFLECT_SPELL = 145 ---- @type modifierfunction -MODIFIER_PROPERTY_DISABLE_AUTOATTACK = 146 ---- @type modifierfunction -MODIFIER_PROPERTY_BONUS_DAY_VISION = 147 ---- @type modifierfunction -MODIFIER_PROPERTY_BONUS_DAY_VISION_PERCENTAGE = 148 ---- @type modifierfunction -MODIFIER_PROPERTY_BONUS_NIGHT_VISION = 149 ---- @type modifierfunction -MODIFIER_PROPERTY_BONUS_NIGHT_VISION_UNIQUE = 150 ---- @type modifierfunction -MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE = 151 ---- @type modifierfunction -MODIFIER_PROPERTY_FIXED_DAY_VISION = 152 ---- @type modifierfunction -MODIFIER_PROPERTY_FIXED_NIGHT_VISION = 153 ---- @type modifierfunction -MODIFIER_PROPERTY_MIN_HEALTH = 154 ---- @type modifierfunction -MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL = 155 ---- @type modifierfunction -MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL = 156 ---- @type modifierfunction -MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE = 157 ---- @type modifierfunction -MODIFIER_PROPERTY_IS_ILLUSION = 158 ---- @type modifierfunction -MODIFIER_PROPERTY_ILLUSION_LABEL = 159 ---- @type modifierfunction -MODIFIER_PROPERTY_STRONG_ILLUSION = 160 ---- @type modifierfunction -MODIFIER_PROPERTY_SUPER_ILLUSION = 161 ---- @type modifierfunction -MODIFIER_PROPERTY_SUPER_ILLUSION_WITH_ULTIMATE = 162 ---- @type modifierfunction -MODIFIER_PROPERTY_XP_DURING_DEATH = 163 ---- @type modifierfunction -MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE = 164 ---- @type modifierfunction -MODIFIER_PROPERTY_TURN_RATE_OVERRIDE = 165 ---- @type modifierfunction -MODIFIER_PROPERTY_DISABLE_HEALING = 166 ---- @type modifierfunction -MODIFIER_PROPERTY_ALWAYS_ALLOW_ATTACK = 167 ---- @type modifierfunction -MODIFIER_PROPERTY_ALWAYS_ETHEREAL_ATTACK = 168 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ATTACK_MAGICAL = 169 ---- @type modifierfunction -MODIFIER_PROPERTY_UNIT_STATS_NEEDS_REFRESH = 170 ---- @type modifierfunction -MODIFIER_PROPERTY_BOUNTY_CREEP_MULTIPLIER = 171 ---- @type modifierfunction -MODIFIER_PROPERTY_BOUNTY_OTHER_MULTIPLIER = 172 ---- @type modifierfunction -MODIFIER_PROPERTY_UNIT_DISALLOW_UPGRADING = 173 ---- @type modifierfunction -MODIFIER_PROPERTY_DODGE_PROJECTILE = 174 ---- @type modifierfunction -MODIFIER_PROPERTY_TRIGGER_COSMETIC_AND_END_ATTACK = 175 ---- @type modifierfunction -MODIFIER_PROPERTY_MAX_DEBUFF_DURATION = 176 ---- @type modifierfunction -MODIFIER_PROPERTY_PRIMARY_STAT_DAMAGE_MULTIPLIER = 177 ---- @type modifierfunction -MODIFIER_PROPERTY_PREATTACK_DEADLY_BLOW = 178 ---- @type modifierfunction -MODIFIER_PROPERTY_ALWAYS_AUTOATTACK_WHILE_HOLD_POSITION = 179 ---- @type modifierfunction -MODIFIER_EVENT_ON_SPELL_TARGET_READY = 180 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_RECORD = 181 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_START = 182 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK = 183 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_LANDED = 184 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_FAIL = 185 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_ALLIED = 186 ---- @type modifierfunction -MODIFIER_EVENT_ON_PROJECTILE_DODGE = 187 ---- @type modifierfunction -MODIFIER_EVENT_ON_ORDER = 188 ---- @type modifierfunction -MODIFIER_EVENT_ON_UNIT_MOVED = 189 ---- @type modifierfunction -MODIFIER_EVENT_ON_ABILITY_START = 190 ---- @type modifierfunction -MODIFIER_EVENT_ON_ABILITY_EXECUTED = 191 ---- @type modifierfunction -MODIFIER_EVENT_ON_ABILITY_FULLY_CAST = 192 ---- @type modifierfunction -MODIFIER_EVENT_ON_BREAK_INVISIBILITY = 193 ---- @type modifierfunction -MODIFIER_EVENT_ON_ABILITY_END_CHANNEL = 194 ---- @type modifierfunction -MODIFIER_EVENT_ON_PROCESS_UPGRADE = 195 ---- @type modifierfunction -MODIFIER_EVENT_ON_REFRESH = 196 ---- @type modifierfunction -MODIFIER_EVENT_ON_TAKEDAMAGE = 197 ---- @type modifierfunction -MODIFIER_EVENT_ON_DEATH_PREVENTED = 198 ---- @type modifierfunction -MODIFIER_EVENT_ON_STATE_CHANGED = 199 ---- @type modifierfunction -MODIFIER_EVENT_ON_ORB_EFFECT = 200 ---- @type modifierfunction -MODIFIER_EVENT_ON_PROCESS_CLEAVE = 201 ---- @type modifierfunction -MODIFIER_EVENT_ON_DAMAGE_CALCULATED = 202 ---- @type modifierfunction -MODIFIER_EVENT_ON_MAGIC_DAMAGE_CALCULATED = 203 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACKED = 204 ---- @type modifierfunction -MODIFIER_EVENT_ON_DEATH = 205 ---- @type modifierfunction -MODIFIER_EVENT_ON_DEATH_COMPLETED = 206 ---- @type modifierfunction -MODIFIER_EVENT_ON_RESPAWN = 207 ---- @type modifierfunction -MODIFIER_EVENT_ON_SPENT_MANA = 208 ---- @type modifierfunction -MODIFIER_EVENT_ON_SPENT_HEALTH = 209 ---- @type modifierfunction -MODIFIER_EVENT_ON_TELEPORTING = 210 ---- @type modifierfunction -MODIFIER_EVENT_ON_TELEPORTED = 211 ---- @type modifierfunction -MODIFIER_EVENT_ON_SET_LOCATION = 212 ---- @type modifierfunction -MODIFIER_EVENT_ON_HEALTH_GAINED = 213 ---- @type modifierfunction -MODIFIER_EVENT_ON_MANA_GAINED = 214 ---- @type modifierfunction -MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT = 215 ---- @type modifierfunction -MODIFIER_EVENT_ON_HERO_KILLED = 216 ---- @type modifierfunction -MODIFIER_EVENT_ON_HEAL_RECEIVED = 217 ---- @type modifierfunction -MODIFIER_EVENT_ON_BUILDING_KILLED = 218 ---- @type modifierfunction -MODIFIER_EVENT_ON_MODEL_CHANGED = 219 ---- @type modifierfunction -MODIFIER_EVENT_ON_MODIFIER_ADDED = 220 ---- @type modifierfunction -MODIFIER_PROPERTY_TOOLTIP = 221 ---- @type modifierfunction -MODIFIER_PROPERTY_MODEL_CHANGE = 222 ---- @type modifierfunction -MODIFIER_PROPERTY_MODEL_SCALE = 223 ---- @type modifierfunction -MODIFIER_PROPERTY_MODEL_SCALE_ANIMATE_TIME = 224 ---- @type modifierfunction -MODIFIER_PROPERTY_MODEL_SCALE_USE_IN_OUT_EASE = 225 ---- @type modifierfunction -MODIFIER_PROPERTY_MODEL_SCALE_CONSTANT = 226 ---- @type modifierfunction -MODIFIER_PROPERTY_IS_SCEPTER = 227 ---- @type modifierfunction -MODIFIER_PROPERTY_IS_SHARD = 228 ---- @type modifierfunction -MODIFIER_PROPERTY_RADAR_COOLDOWN_REDUCTION = 229 ---- @type modifierfunction -MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS = 230 ---- @type modifierfunction -MODIFIER_PROPERTY_TRANSLATE_ATTACK_SOUND = 231 ---- @type modifierfunction -MODIFIER_PROPERTY_LIFETIME_FRACTION = 232 ---- @type modifierfunction -MODIFIER_PROPERTY_PROVIDES_FOW_POSITION = 233 ---- @type modifierfunction -MODIFIER_PROPERTY_SPELLS_REQUIRE_HP = 234 ---- @type modifierfunction -MODIFIER_PROPERTY_FORCE_DRAW_MINIMAP = 235 ---- @type modifierfunction -MODIFIER_PROPERTY_DISABLE_TURNING = 236 ---- @type modifierfunction -MODIFIER_PROPERTY_IGNORE_CAST_ANGLE = 237 ---- @type modifierfunction -MODIFIER_PROPERTY_CHANGE_ABILITY_VALUE = 238 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL = 239 ---- @type modifierfunction -MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL_VALUE = 240 ---- @type modifierfunction -MODIFIER_PROPERTY_ABILITY_LAYOUT = 241 ---- @type modifierfunction -MODIFIER_EVENT_ON_DOMINATED = 242 ---- @type modifierfunction -MODIFIER_EVENT_ON_KILL = 243 ---- @type modifierfunction -MODIFIER_EVENT_ON_ASSIST = 244 ---- @type modifierfunction -MODIFIER_PROPERTY_TEMPEST_DOUBLE = 245 ---- @type modifierfunction -MODIFIER_PROPERTY_PRESERVE_PARTICLES_ON_MODEL_CHANGE = 246 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_FINISHED = 247 ---- @type modifierfunction -MODIFIER_PROPERTY_IGNORE_COOLDOWN = 248 ---- @type modifierfunction -MODIFIER_PROPERTY_CAN_ATTACK_TREES = 249 ---- @type modifierfunction -MODIFIER_PROPERTY_VISUAL_Z_DELTA = 250 ---- @type modifierfunction -MODIFIER_PROPERTY_VISUAL_Z_SPEED_BASE_OVERRIDE = 251 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_DAMAGE_ILLUSION = 252 ---- @type modifierfunction -MODIFIER_PROPERTY_DONT_GIVE_VISION_OF_ATTACKER = 253 ---- @type modifierfunction -MODIFIER_PROPERTY_TOOLTIP2 = 254 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_RECORD_DESTROY = 255 ---- @type modifierfunction -MODIFIER_EVENT_ON_PROJECTILE_OBSTRUCTION_HIT = 256 ---- @type modifierfunction -MODIFIER_PROPERTY_SUPPRESS_TELEPORT = 257 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTACK_CANCELLED = 258 ---- @type modifierfunction -MODIFIER_PROPERTY_SUPPRESS_CLEAVE = 259 ---- @type modifierfunction -MODIFIER_PROPERTY_BOT_ATTACK_SCORE_BONUS = 260 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE = 261 ---- @type modifierfunction -MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE = 262 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACK_WHILE_MOVING_TARGET = 263 ---- @type modifierfunction -MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE = 264 ---- @type modifierfunction -MODIFIER_EVENT_ON_ATTEMPT_PROJECTILE_DODGE = 265 ---- @type modifierfunction -MODIFIER_EVENT_ON_PREDEBUFF_APPLIED = 266 ---- @type modifierfunction -MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_STACKING = 267 ---- @type modifierfunction -MODIFIER_PROPERTY_SPELL_REDIRECT_TARGET = 268 ---- @type modifierfunction -MODIFIER_PROPERTY_TURN_RATE_CONSTANT = 269 ---- @type modifierfunction -MODIFIER_PROPERTY_RAT_PACK = 270 ---- @type modifierfunction -MODIFIER_PROPERTY_PHYSICALDAMAGEOUTGOING_PERCENTAGE = 271 ---- @type modifierfunction -MODIFIER_PROPERTY_KNOCKBACK_AMPLIFICATION_PERCENTAGE = 272 ---- @type modifierfunction -MODIFIER_PROPERTY_HEALTHBAR_PIPS = 273 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT = 274 ---- @type modifierfunction -MODIFIER_EVENT_SPELL_APPLIED_SUCCESSFULLY = 275 ---- @type modifierfunction -MODIFIER_PROPERTY_AVOID_DAMAGE_AFTER_REDUCTIONS = 276 ---- @type modifierfunction -MODIFIER_PROPERTY_FAIL_ATTACK = 277 ---- @type modifierfunction -MODIFIER_PROPERTY_PREREDUCE_INCOMING_DAMAGE_MULT = 278 ---- @type modifierfunction -MODIFIER_PROPERTY_SUPPRESS_FULLSCREEN_DEATH_FX = 279 ---- @type modifierfunction -MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST = 280 ---- @type modifierfunction -MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_MULTIPLICATIVE = 281 ---- @type modifierfunction -MODIFIER_PROPERTY_TICK_GOLD_MULTIPLIER = 282 ---- @type modifierfunction -MODIFIER_PROPERTY_SLOW_RESISTANCE = 283 ---- @type modifierfunction -MODIFIER_PROPERTY_AOE_BONUS_PERCENTAGE = 284 ---- @type modifierfunction -MODIFIER_PROPERTY_PROJECTILE_SPEED = 285 ---- @type modifierfunction -MODIFIER_PROPERTY_BECOME_UNIVERSAL = 286 ---- @type modifierfunction -MODIFIER_EVENT_ON_FORCE_PROC_MAGIC_STICK = 287 ---- @type modifierfunction -MODIFIER_PROPERTY_DO_NOT_SINK_AFTER_DEATH = 288 ---- @type modifierfunction -MODIFIER_EVENT_ON_DAMAGE_HPLOSS = 289 ---- @type modifierfunction -MODIFIER_PROPERTY_FORCE_MAX_HEALTH = 290 ---- @type modifierfunction -MODIFIER_PROPERTY_AOE_BONUS_CONSTANT = 291 ---- @type modifierfunction -MODIFIER_FUNCTION_LAST = 292 ---- @type modifierfunction -MODIFIER_FUNCTION_INVALID = 65535 +--- @enum modifierfunction +--- @field MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE 0 Method Name: `GetModifierPreAttack_BonusDamage` +--- @field MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_TARGET 1 Method Name: `GetModifierPreAttack_BonusDamage_Target` +--- @field MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_PROC 2 Method Name: `GetModifierPreAttack_BonusDamage_Proc` +--- @field MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_POST_CRIT 3 Method Name: `GetModifierPreAttack_BonusDamagePostCrit` +--- @field MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE 4 Method Name: `GetModifierBaseAttack_BonusDamage` +--- @field MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PHYSICAL 5 Method Name: `GetModifierProcAttack_BonusDamage_Physical` +--- @field MODIFIER_PROPERTY_PROCATTACK_CONVERT_PHYSICAL_TO_MAGICAL 6 Method Name: `GetModifierProcAttack_ConvertPhysicalToMagical` +--- @field MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL 7 Method Name: `GetModifierProcAttack_BonusDamage_Magical` +--- @field MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PURE 8 Method Name: `GetModifierProcAttack_BonusDamage_Pure` +--- @field MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL_TARGET 9 Method Name: `GetModifierProcAttack_BonusDamage_Magical_Target` +--- @field MODIFIER_PROPERTY_PROCATTACK_FEEDBACK 10 Method Name: `GetModifierProcAttack_Feedback` +--- @field MODIFIER_PROPERTY_OVERRIDE_ATTACK_DAMAGE 11 Method Name: `GetModifierOverrideAttackDamage` +--- @field MODIFIER_PROPERTY_PRE_ATTACK 12 Method Name: `GetModifierPreAttack` +--- @field MODIFIER_PROPERTY_INVISIBILITY_LEVEL 13 Method Name: `GetModifierInvisibilityLevel` +--- @field MODIFIER_PROPERTY_INVISIBILITY_ATTACK_BEHAVIOR_EXCEPTION 14 Method Name: `GetModifierInvisibilityAttackBehaviorException` +--- @field MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY 15 Method Name: `GetModifierPersistentInvisibility` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT 16 Method Name: `GetModifierMoveSpeedBonus_Constant` +--- @field MODIFIER_PROPERTY_MOVESPEED_BASE_OVERRIDE 17 Method Name: `GetModifierMoveSpeedOverride` +--- @field MODIFIER_PROPERTY_MOVESPEED_MIN_OVERRIDE 18 Method Name: `GetModifierMoveSpeed_MinOverride` +--- @field MODIFIER_PROPERTY_MOVESPEED_MAX_OVERRIDE 19 Method Name: `GetModifierMoveSpeed_MaxOverride` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE 20 Method Name: `GetModifierMoveSpeedBonus_Percentage` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE_UNIQUE 21 Method Name: `GetModifierMoveSpeedBonus_Percentage_Unique` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE 22 Method Name: `GetModifierMoveSpeedBonus_Special_Boots` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE_2 23 Method Name: `GetModifierMoveSpeedBonus_Special_Boots_2` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE 24 Method Name: `GetModifierMoveSpeedBonus_Constant_Unique` +--- @field MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE_2 25 Method Name: `GetModifierMoveSpeedBonus_Constant_Unique_2` +--- @field MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE 26 Method Name: `GetModifierMoveSpeed_Absolute` +--- @field MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MIN 27 Method Name: `GetModifierMoveSpeed_AbsoluteMin` +--- @field MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MAX 28 Method Name: `GetModifierMoveSpeed_AbsoluteMax` +--- @field MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT 29 Method Name: `GetModifierIgnoreMovespeedLimit` +--- @field MODIFIER_PROPERTY_MOVESPEED_LIMIT 30 Method Name: `GetModifierMoveSpeed_Limit` +--- @field MODIFIER_PROPERTY_ATTACKSPEED_BASE_OVERRIDE 31 Method Name: `GetModifierAttackSpeedBaseOverride` +--- @field MODIFIER_PROPERTY_FIXED_ATTACK_RATE 32 Method Name: `GetModifierFixedAttackRate` +--- @field MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT 33 Method Name: `GetModifierAttackSpeedBonus_Constant` +--- @field MODIFIER_PROPERTY_IGNORE_ATTACKSPEED_LIMIT 34 Method Name: `GetModifierAttackSpeed_Limit` +--- @field MODIFIER_PROPERTY_COOLDOWN_REDUCTION_CONSTANT 35 Method Name: `GetModifierCooldownReduction_Constant` +--- @field MODIFIER_PROPERTY_MANACOST_REDUCTION_CONSTANT 36 Method Name: `GetModifierManacostReduction_Constant` +--- @field MODIFIER_PROPERTY_HEALTHCOST_REDUCTION_CONSTANT 37 Method Name: `GetModifierHealthcostReduction_Constant` +--- @field MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT 38 Method Name: `GetModifierBaseAttackTimeConstant` +--- @field MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT_ADJUST 39 Method Name: `GetModifierBaseAttackTimeConstant_Adjust` +--- @field MODIFIER_PROPERTY_BASE_ATTACK_TIME_PERCENTAGE 40 Method Name: `GetModifierBaseAttackTimePercentage` +--- @field MODIFIER_PROPERTY_ATTACK_POINT_CONSTANT 41 Method Name: `GetModifierAttackPointConstant` +--- @field MODIFIER_PROPERTY_BONUSDAMAGEOUTGOING_PERCENTAGE 42 Method Name: `GetModifierBonusDamageOutgoing_Percentage` +--- @field MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE 43 Method Name: `GetModifierDamageOutgoing_Percentage` +--- @field MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION 44 Method Name: `GetModifierDamageOutgoing_Percentage_Illusion` +--- @field MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION_AMPLIFY 45 Method Name: `GetModifierDamageOutgoing_Percentage_Illusion_Amplify` +--- @field MODIFIER_PROPERTY_TOTALDAMAGEOUTGOING_PERCENTAGE 46 Method Name: `GetModifierTotalDamageOutgoing_Percentage` +--- @field MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_CREEP 47 Method Name: `GetModifierSpellAmplify_PercentageCreep` +--- @field MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE 48 Method Name: `GetModifierSpellAmplify_Percentage` +--- @field MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_UNIQUE 49 Method Name: `GetModifierSpellAmplify_PercentageUnique` +--- @field MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_TARGET 50 Method Name: `GetModifierSpellAmplify_PercentageTarget` +--- @field MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE 51 Method Name: `GetModifierHealAmplify_PercentageSource` +--- @field MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET 52 Method Name: `GetModifierHealAmplify_PercentageTarget` +--- @field MODIFIER_PROPERTY_HP_REGEN_CAN_BE_NEGATIVE 53 Method Name: `GetModifierHPRegen_CanBeNegative` +--- @field MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE 54 Method Name: `GetModifierHPRegenAmplify_Percentage` +--- @field MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE 55 Method Name: `GetModifierLifestealRegenAmplify_Percentage` +--- @field MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE 56 Method Name: `GetModifierSpellLifestealRegenAmplify_Percentage` +--- @field MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE_UNIQUE 57 Method Name: `GetModifierSpellLifestealRegenAmplify_Percentage_Unique` +--- @field MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE 58 Method Name: `GetModifierMPRegenAmplify_Percentage` +--- @field MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE_UNIQUE 59 Method Name: `GetModifierMPRegenAmplify_Percentage_Unique` +--- @field MODIFIER_PROPERTY_MANA_DRAIN_AMPLIFY_PERCENTAGE 60 Method Name: `GetModifierManaDrainAmplify_Percentage` +--- @field MODIFIER_PROPERTY_MP_RESTORE_AMPLIFY_PERCENTAGE 61 Total amplify value is clamped to 0. Method Name: `GetModifierMPRestoreAmplify_Percentage`. +--- @field MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE 62 Method Name: `GetModifierBaseDamageOutgoing_Percentage` +--- @field MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE_UNIQUE 63 Method Name: `GetModifierBaseDamageOutgoing_PercentageUnique` +--- @field MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE 64 Method Name: `GetModifierIncomingDamage_Percentage` +--- @field MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE 65 Method Name: `GetModifierIncomingPhysicalDamage_Percentage` +--- @field MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_CONSTANT 66 This property controls 'physical' shield, if defined both on client and server. Return value on client should be current shield health, as a positive integer, on server - amount of damage blocked. Method Name: `GetModifierIncomingPhysicalDamageConstant`. +--- @field MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT 67 This property controls 'spell' shield, if defined both on client and server. Return value on client should be current shield health, as a positive integer, on server - amount of damage blocked. Method Name: `GetModifierIncomingSpellDamageConstant`. +--- @field MODIFIER_PROPERTY_EVASION_CONSTANT 68 Method Name: `GetModifierEvasion_Constant` +--- @field MODIFIER_PROPERTY_NEGATIVE_EVASION_CONSTANT 69 Method Name: `GetModifierNegativeEvasion_Constant` +--- @field MODIFIER_PROPERTY_STATUS_RESISTANCE 70 Method Name: `GetModifierStatusResistance` +--- @field MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING 71 Method Name: `GetModifierStatusResistanceStacking` +--- @field MODIFIER_PROPERTY_STATUS_RESISTANCE_CASTER 72 Method Name: `GetModifierStatusResistanceCaster` +--- @field MODIFIER_PROPERTY_AVOID_DAMAGE 73 Method Name: `GetModifierAvoidDamage` +--- @field MODIFIER_PROPERTY_AVOID_SPELL 74 Method Name: `GetModifierAvoidSpell` +--- @field MODIFIER_PROPERTY_MISS_PERCENTAGE 75 Method Name: `GetModifierMiss_Percentage` +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_BASE_PERCENTAGE 76 Values above 100% are ignored. Method Name: `GetModifierPhysicalArmorBase_Percentage`. +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_TOTAL_PERCENTAGE 77 Method Name: `GetModifierPhysicalArmorTotal_Percentage` +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS 78 Method Name: `GetModifierPhysicalArmorBonus` +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE 79 Method Name: `GetModifierPhysicalArmorBonusUnique` +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE 80 Method Name: `GetModifierPhysicalArmorBonusUniqueActive` +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_POST 81 Method Name: `GetModifierPhysicalArmorBonusPost` +--- @field MODIFIER_PROPERTY_MIN_PHYSICAL_ARMOR 82 Method Name: `GetModifierMinPhysicalArmor` +--- @field MODIFIER_PROPERTY_IGNORE_PHYSICAL_ARMOR 83 Method Name: `GetModifierIgnorePhysicalArmor` +--- @field MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BASE_REDUCTION 84 Method Name: `GetModifierMagicalResistanceBaseReduction` +--- @field MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DIRECT_MODIFICATION 85 Method Name: `GetModifierMagicalResistanceDirectModification` +--- @field MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS 86 Method Name: `GetModifierMagicalResistanceBonus` +--- @field MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_ILLUSIONS 87 Method Name: `GetModifierMagicalResistanceBonusIllusions` +--- @field MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_UNIQUE 88 Method Name: `GetModifierMagicalResistanceBonusUnique` +--- @field MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE 89 Method Name: `GetModifierMagicalResistanceDecrepifyUnique` +--- @field MODIFIER_PROPERTY_BASE_MANA_REGEN 90 Method Name: `GetModifierBaseRegen` +--- @field MODIFIER_PROPERTY_MANA_REGEN_CONSTANT 91 Method Name: `GetModifierConstantManaRegen` +--- @field MODIFIER_PROPERTY_MANA_REGEN_CONSTANT_UNIQUE 92 Method Name: `GetModifierConstantManaRegenUnique` +--- @field MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE 93 Method Name: `GetModifierTotalPercentageManaRegen` +--- @field MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT 94 Method Name: `GetModifierConstantHealthRegen` +--- @field MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE 95 Method Name: `GetModifierHealthRegenPercentage` +--- @field MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE_UNIQUE 96 Method Name: `GetModifierHealthRegenPercentageUnique` +--- @field MODIFIER_PROPERTY_HEALTH_BONUS 97 Method Name: `GetModifierHealthBonus` +--- @field MODIFIER_PROPERTY_MANA_BONUS 98 Method Name: `GetModifierManaBonus` +--- @field MODIFIER_PROPERTY_EXTRA_STRENGTH_BONUS 99 Method Name: `GetModifierExtraStrengthBonus` +--- @field MODIFIER_PROPERTY_EXTRA_HEALTH_BONUS 100 Method Name: `GetModifierExtraHealthBonus` +--- @field MODIFIER_PROPERTY_EXTRA_MANA_BONUS 101 Method Name: `GetModifierExtraManaBonus` +--- @field MODIFIER_PROPERTY_EXTRA_MANA_BONUS_PERCENTAGE 102 Method Name: `GetModifierExtraManaBonusPercentage` +--- @field MODIFIER_PROPERTY_EXTRA_HEALTH_PERCENTAGE 103 Method Name: `GetModifierExtraHealthPercentage` +--- @field MODIFIER_PROPERTY_EXTRA_MANA_PERCENTAGE 104 Method Name: `GetModifierExtraManaPercentage` +--- @field MODIFIER_PROPERTY_STATS_STRENGTH_BONUS 105 Method Name: `GetModifierBonusStats_Strength` +--- @field MODIFIER_PROPERTY_STATS_AGILITY_BONUS 106 Method Name: `GetModifierBonusStats_Agility` +--- @field MODIFIER_PROPERTY_STATS_INTELLECT_BONUS 107 Method Name: `GetModifierBonusStats_Intellect` +--- @field MODIFIER_PROPERTY_STATS_STRENGTH_BONUS_PERCENTAGE 108 Method Name: `GetModifierBonusStats_Strength_Percentage` +--- @field MODIFIER_PROPERTY_STATS_AGILITY_BONUS_PERCENTAGE 109 Method Name: `GetModifierBonusStats_Agility_Percentage` +--- @field MODIFIER_PROPERTY_STATS_INTELLECT_BONUS_PERCENTAGE 110 Method Name: `GetModifierBonusStats_Intellect_Percentage` +--- @field MODIFIER_PROPERTY_CAST_RANGE_BONUS 111 Method Name: `GetModifierCastRangeBonus` +--- @field MODIFIER_PROPERTY_CAST_RANGE_BONUS_PERCENTAGE 112 Method Name: `GetModifierCastRangeBonusPercentage` +--- @field MODIFIER_PROPERTY_CAST_RANGE_BONUS_TARGET 113 Method Name: `GetModifierCastRangeBonusTarget` +--- @field MODIFIER_PROPERTY_CAST_RANGE_BONUS_STACKING 114 Method Name: `GetModifierCastRangeBonusStacking` +--- @field MODIFIER_PROPERTY_ATTACK_RANGE_BASE_OVERRIDE 115 Method Name: `GetModifierAttackRangeOverride` +--- @field MODIFIER_PROPERTY_ATTACK_RANGE_BONUS 116 Method Name: `GetModifierAttackRangeBonus` +--- @field MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_UNIQUE 117 Method Name: `GetModifierAttackRangeBonusUnique` +--- @field MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_PERCENTAGE 118 Method Name: `GetModifierAttackRangeBonusPercentage` +--- @field MODIFIER_PROPERTY_MAX_ATTACK_RANGE 119 Method Name: `GetModifierMaxAttackRange` +--- @field MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS 120 Method Name: `GetModifierProjectileSpeedBonus` +--- @field MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS_PERCENTAGE 121 Method Name: `GetModifierProjectileSpeedBonusPercentage` +--- @field MODIFIER_PROPERTY_PROJECTILE_NAME 122 Method Name: `GetModifierProjectileName` +--- @field MODIFIER_PROPERTY_REINCARNATION 123 Method Name: `ReincarnateTime` +--- @field MODIFIER_PROPERTY_REINCARNATION_SUPPRESS_FX 124 Method Name: `ReincarnateSuppressFX` +--- @field MODIFIER_PROPERTY_RESPAWNTIME 125 Method Name: `GetModifierConstantRespawnTime` +--- @field MODIFIER_PROPERTY_RESPAWNTIME_PERCENTAGE 126 Method Name: `GetModifierPercentageRespawnTime` +--- @field MODIFIER_PROPERTY_RESPAWNTIME_STACKING 127 Method Name: `GetModifierStackingRespawnTime` +--- @field MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE 128 Method Name: `GetModifierPercentageCooldown` +--- @field MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_ONGOING 129 Method Name: `GetModifierPercentageCooldownOngoing` +--- @field MODIFIER_PROPERTY_CASTTIME_PERCENTAGE 130 Method Name: `GetModifierPercentageCasttime` +--- @field MODIFIER_PROPERTY_ATTACK_ANIM_TIME_PERCENTAGE 131 Method Name: `GetModifierPercentageAttackAnimTime` +--- @field MODIFIER_PROPERTY_MANACOST_PERCENTAGE 132 Method Name: `GetModifierPercentageManacost` +--- @field MODIFIER_PROPERTY_MANACOST_PERCENTAGE_STACKING 133 Method Name: `GetModifierPercentageManacostStacking` +--- @field MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE 134 Method Name: `GetModifierPercentageHealthcost` +--- @field MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE_STACKING 135 Method Name: `GetModifierPercentageHealthcostStacking` +--- @field MODIFIER_PROPERTY_DEATHGOLDCOST 136 Method Name: `GetModifierConstantDeathGoldCost` +--- @field MODIFIER_PROPERTY_PERCENTAGE_DEATHGOLDCOST 137 Method Name: `GetModifierPercentageDeathGoldCost` +--- @field MODIFIER_PROPERTY_EXP_RATE_BOOST 138 Method Name: `GetModifierPercentageExpRateBoost` +--- @field MODIFIER_PROPERTY_GOLD_RATE_BOOST 139 Method Name: `GetModifierPercentageGoldRateBoost` +--- @field MODIFIER_PROPERTY_PREATTACK_CRITICALSTRIKE 140 Method Name: `GetModifierPreAttack_CriticalStrike` +--- @field MODIFIER_PROPERTY_PREATTACK_TARGET_CRITICALSTRIKE 141 Method Name: `GetModifierPreAttack_Target_CriticalStrike` +--- @field MODIFIER_PROPERTY_MAGICAL_CONSTANT_BLOCK 142 Method Name: `GetModifierMagical_ConstantBlock` +--- @field MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK 143 Method Name: `GetModifierPhysical_ConstantBlock` +--- @field MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK_SPECIAL 144 Method Name: `GetModifierPhysical_ConstantBlockSpecial` +--- @field MODIFIER_PROPERTY_INNATE_DAMAGE_BLOCK_PCT_OVERRIDE 145 Method Name: `GetModifierInnateDamageBlockPctOverride` +--- @field MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR 146 Method Name: `GetModifierPhysical_ConstantBlockUnavoidablePreArmor` +--- @field MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK 147 Method Name: `GetModifierTotal_ConstantBlock` +--- @field MODIFIER_PROPERTY_OVERRIDE_ANIMATION 148 Method Name: `GetOverrideAnimation` +--- @field MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE 149 Method Name: `GetOverrideAnimationRate` +--- @field MODIFIER_PROPERTY_ABSORB_SPELL 150 Method Name: `GetAbsorbSpell` +--- @field MODIFIER_PROPERTY_REFLECT_SPELL 151 Method Name: `GetReflectSpell` +--- @field MODIFIER_PROPERTY_DISABLE_AUTOATTACK 152 Method Name: `GetDisableAutoAttack` +--- @field MODIFIER_PROPERTY_BONUS_DAY_VISION 153 Method Name: `GetBonusDayVision` +--- @field MODIFIER_PROPERTY_BONUS_DAY_VISION_PERCENTAGE 154 Method Name: `GetBonusDayVisionPercentage` +--- @field MODIFIER_PROPERTY_BONUS_NIGHT_VISION 155 Method Name: `GetBonusNightVision` +--- @field MODIFIER_PROPERTY_BONUS_NIGHT_VISION_UNIQUE 156 Method Name: `GetBonusNightVisionUnique` +--- @field MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE 157 Method Name: `GetBonusVisionPercentage` +--- @field MODIFIER_PROPERTY_FIXED_DAY_VISION 158 Method Name: `GetFixedDayVision` +--- @field MODIFIER_PROPERTY_FIXED_NIGHT_VISION 159 Method Name: `GetFixedNightVision` +--- @field MODIFIER_PROPERTY_MIN_HEALTH 160 Method Name: `GetMinHealth` +--- @field MODIFIER_PROPERTY_MIN_MANA 161 Method Name: `GetMinMana` +--- @field MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL 162 Method Name: `GetAbsoluteNoDamagePhysical` +--- @field MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL 163 Method Name: `GetAbsoluteNoDamageMagical` +--- @field MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE 164 Method Name: `GetAbsoluteNoDamagePure` +--- @field MODIFIER_PROPERTY_IS_ILLUSION 165 Method Name: `GetIsIllusion` +--- @field MODIFIER_PROPERTY_ILLUSION_LABEL 166 Method Name: `GetModifierIllusionLabel` +--- @field MODIFIER_PROPERTY_STRONG_ILLUSION 167 Method Name: `GetModifierStrongIllusion` +--- @field MODIFIER_PROPERTY_SUPER_ILLUSION 168 Method Name: `GetModifierSuperIllusion` +--- @field MODIFIER_PROPERTY_SUPER_ILLUSION_WITH_ULTIMATE 169 Method Name: `GetModifierSuperIllusionWithUltimate` +--- @field MODIFIER_PROPERTY_XP_DURING_DEATH 170 Method Name: `GetModifierXPDuringDeath` +--- @field MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE 171 Method Name: `GetModifierTurnRate_Percentage` +--- @field MODIFIER_PROPERTY_TURN_RATE_OVERRIDE 172 Method Name: `GetModifierTurnRate_Override` +--- @field MODIFIER_PROPERTY_DISABLE_HEALING 173 Method Name: `GetDisableHealing` +--- @field MODIFIER_PROPERTY_DISABLE_MANA_GAIN 174 Method Name: `GetDisableManaGain` +--- @field MODIFIER_PROPERTY_ALWAYS_ALLOW_ATTACK 175 Method Name: `GetAlwaysAllowAttack` +--- @field MODIFIER_PROPERTY_ALWAYS_ETHEREAL_ATTACK 176 Method Name: `GetAllowEtherealAttack` +--- @field MODIFIER_PROPERTY_OVERRIDE_ATTACK_MAGICAL 177 Method Name: `GetOverrideAttackMagical` +--- @field MODIFIER_PROPERTY_UNIT_STATS_NEEDS_REFRESH 178 Method Name: `GetModifierUnitStatsNeedsRefresh` +--- @field MODIFIER_PROPERTY_BOUNTY_CREEP_MULTIPLIER 179 +--- @field MODIFIER_PROPERTY_BOUNTY_OTHER_MULTIPLIER 180 +--- @field MODIFIER_PROPERTY_UNIT_DISALLOW_UPGRADING 181 Method Name: `GetModifierUnitDisllowUpgrading` +--- @field MODIFIER_PROPERTY_DODGE_PROJECTILE 182 Method Name: `GetModifierDodgeProjectile` +--- @field MODIFIER_PROPERTY_TRIGGER_COSMETIC_AND_END_ATTACK 183 Method Name: `GetTriggerCosmeticAndEndAttack` +--- @field MODIFIER_PROPERTY_MAX_DEBUFF_DURATION 184 Method Name: `GetModifierMaxDebuffDuration` +--- @field MODIFIER_PROPERTY_PRIMARY_STAT_DAMAGE_MULTIPLIER 185 Method Name: `GetPrimaryStatDamageMultiplier` +--- @field MODIFIER_PROPERTY_PREATTACK_DEADLY_BLOW 186 Method Name: `GetModifierPreAttack_DeadlyBlow` +--- @field MODIFIER_PROPERTY_ALWAYS_AUTOATTACK_WHILE_HOLD_POSITION 187 Method Name: `GetAlwaysAutoAttackWhileHoldPosition` +--- @field MODIFIER_PROPERTY_PHYSICAL_ARMOR_PIERCING_PERCENTAGE_TARGET 188 Method Name: `GetPhysicalArmorPiercingPercentageTarget` +--- @field MODIFIER_PROPERTY_MAGICAL_ARMOR_PIERCING_PERCENTAGE_TARGET 189 Method Name: `GetMagicalArmorPiercingPercentageTarget` +--- @field MODIFIER_PROPERTY_CRITICAL_STRIKE_BONUS 190 Method Name: `GetCriticalStrikeBonus` +--- @field MODIFIER_PROPERTY_CONVERT_ATTACK_PHYSICAL_TO_PURE 191 Method Name: `GetConvertAttackPhysicalToPure` +--- @field MODIFIER_EVENT_ON_SPELL_TARGET_READY 192 Method Name: `OnSpellTargetReady` +--- @field MODIFIER_EVENT_ON_ATTACK_RECORD 193 Method Name: `OnAttackRecord` +--- @field MODIFIER_EVENT_ON_ATTACK_START 194 Method Name: `OnAttackStart` +--- @field MODIFIER_EVENT_ON_ATTACK 195 Method Name: `OnAttack` +--- @field MODIFIER_EVENT_ON_ATTACK_LANDED 196 Method Name: `OnAttackLanded` +--- @field MODIFIER_EVENT_ON_ATTACK_FAIL 197 Method Name: `OnAttackFail` +--- @field MODIFIER_EVENT_ON_ATTACK_ALLIED 198 Happens even if attack can't be issued. Method Name: `OnAttackAllied`. +--- @field MODIFIER_EVENT_ON_PROJECTILE_DODGE 199 Method Name: `OnProjectileDodge` +--- @field MODIFIER_EVENT_ON_ORDER 200 Method Name: `OnOrder` +--- @field MODIFIER_EVENT_ON_UNIT_MOVED 201 Method Name: `OnUnitMoved` +--- @field MODIFIER_EVENT_ON_ABILITY_START 202 Method Name: `OnAbilityStart` +--- @field MODIFIER_EVENT_ON_ABILITY_EXECUTED 203 Method Name: `OnAbilityExecuted` +--- @field MODIFIER_EVENT_ON_ABILITY_FULLY_CAST 204 Method Name: `OnAbilityFullyCast` +--- @field MODIFIER_EVENT_ON_BREAK_INVISIBILITY 205 Method Name: `OnBreakInvisibility` +--- @field MODIFIER_EVENT_ON_ABILITY_END_CHANNEL 206 Method Name: `OnAbilityEndChannel` +--- @field MODIFIER_EVENT_ON_PROCESS_UPGRADE 207 +--- @field MODIFIER_EVENT_ON_REFRESH 208 +--- @field MODIFIER_EVENT_ON_TAKEDAMAGE 209 Method Name: `OnTakeDamage` +--- @field MODIFIER_EVENT_ON_DEATH_PREVENTED 210 Method Name: `OnDamagePrevented` +--- @field MODIFIER_EVENT_ON_STATE_CHANGED 211 Method Name: `OnStateChanged` +--- @field MODIFIER_EVENT_ON_ORB_EFFECT 212 +--- @field MODIFIER_EVENT_ON_PROCESS_CLEAVE 213 Method Name: `OnProcessCleave` +--- @field MODIFIER_EVENT_ON_DAMAGE_CALCULATED 214 Method Name: `OnDamageCalculated` +--- @field MODIFIER_EVENT_ON_MAGIC_DAMAGE_CALCULATED 215 Method Name: `OnMagicDamageCalculated` +--- @field MODIFIER_EVENT_ON_ATTACKED 216 Method Name: `OnAttacked` +--- @field MODIFIER_EVENT_ON_DEATH 217 Method Name: `OnDeath` +--- @field MODIFIER_EVENT_ON_DEATH_COMPLETED 218 Method Name: `OnDeathCompleted` +--- @field MODIFIER_EVENT_ON_RESPAWN 219 Method Name: `OnRespawn` +--- @field MODIFIER_EVENT_ON_SPENT_MANA 220 Method Name: `OnSpentMana` +--- @field MODIFIER_EVENT_ON_SPENT_HEALTH 221 Method Name: `OnSpentHealth` +--- @field MODIFIER_EVENT_ON_TELEPORTING 222 Method Name: `OnTeleporting` +--- @field MODIFIER_EVENT_ON_TELEPORTED 223 Method Name: `OnTeleported` +--- @field MODIFIER_EVENT_ON_SET_LOCATION 224 Method Name: `OnSetLocation` +--- @field MODIFIER_EVENT_ON_HEALTH_GAINED 225 Method Name: `OnHealthGained` +--- @field MODIFIER_EVENT_ON_MANA_GAINED 226 Method Name: `OnManaGained` +--- @field MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT 227 Method Name: `OnTakeDamageKillCredit` +--- @field MODIFIER_EVENT_ON_HERO_KILLED 228 Method Name: `OnHeroKilled` +--- @field MODIFIER_EVENT_ON_HEAL_RECEIVED 229 Method Name: `OnHealReceived` +--- @field MODIFIER_EVENT_ON_BUILDING_KILLED 230 Method Name: `OnBuildingKilled` +--- @field MODIFIER_EVENT_ON_MODEL_CHANGED 231 Method Name: `OnModelChanged` +--- @field MODIFIER_EVENT_ON_MODIFIER_ADDED 232 Method Name: `OnModifierAdded` +--- @field MODIFIER_EVENT_ON_MODIFIER_REMOVED 233 Method Name: `OnModifierRemoved` +--- @field MODIFIER_PROPERTY_TOOLTIP 234 Method Name: `OnTooltip` +--- @field MODIFIER_PROPERTY_MODEL_CHANGE 235 Method Name: `GetModifierModelChange` +--- @field MODIFIER_PROPERTY_MODEL_SCALE 236 Method Name: `GetModifierModelScale` +--- @field MODIFIER_PROPERTY_MODEL_SCALE_ANIMATE_TIME 237 Method Name: `GetModifierModelScaleAnimateTime` +--- @field MODIFIER_PROPERTY_MODEL_SCALE_USE_IN_OUT_EASE 238 Method Name: `GetModifierModelScaleUseInOutEase` +--- @field MODIFIER_PROPERTY_MODEL_SCALE_CONSTANT 239 Method Name: `GetModifierModelScaleConstant` +--- @field MODIFIER_PROPERTY_IS_SCEPTER 240 Applies scepter when this property is active Method Name: `GetModifierScepter`. +--- @field MODIFIER_PROPERTY_IS_SHARD 241 Applies shard when this property is active Method Name: `GetModifierShard`. +--- @field MODIFIER_PROPERTY_RADAR_COOLDOWN_REDUCTION 242 Method Name: `GetModifierRadarCooldownReduction` +--- @field MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS 243 Method Name: `GetActivityTranslationModifiers` +--- @field MODIFIER_PROPERTY_TRANSLATE_ATTACK_SOUND 244 Method Name: `GetAttackSound` +--- @field MODIFIER_PROPERTY_LIFETIME_FRACTION 245 Method Name: `GetUnitLifetimeFraction` +--- @field MODIFIER_PROPERTY_PROVIDES_FOW_POSITION 246 Method Name: `GetModifierProvidesFOWVision` +--- @field MODIFIER_PROPERTY_SPELLS_REQUIRE_HP 247 Method Name: `GetModifierSpellsRequireHP` +--- @field MODIFIER_PROPERTY_CONVERT_MANA_COST_TO_HEALTH_COST 248 Method Name: `GetModifierConvertManaCostToHealthCost` +--- @field MODIFIER_PROPERTY_FORCE_DRAW_MINIMAP 249 Method Name: `GetForceDrawOnMinimap` +--- @field MODIFIER_PROPERTY_DISABLE_TURNING 250 Method Name: `GetModifierDisableTurning` +--- @field MODIFIER_PROPERTY_IGNORE_CAST_ANGLE 251 Method Name: `GetModifierIgnoreCastAngle` +--- @field MODIFIER_PROPERTY_CHANGE_ABILITY_VALUE 252 Method Name: `GetModifierChangeAbilityValue` +--- @field MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL 253 Method Name: `GetModifierOverrideAbilitySpecial` +--- @field MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL_VALUE 254 Method Name: `GetModifierOverrideAbilitySpecialValue` +--- @field MODIFIER_PROPERTY_ABILITY_LAYOUT 255 Method Name: `GetModifierAbilityLayout` +--- @field MODIFIER_EVENT_ON_DOMINATED 256 Method Name: `OnDominated` +--- @field MODIFIER_EVENT_ON_KILL 257 Method Name: `OnKill` +--- @field MODIFIER_EVENT_ON_ASSIST 258 Method Name: `OnAssist` +--- @field MODIFIER_PROPERTY_TEMPEST_DOUBLE 259 Method Name: `GetModifierTempestDouble` +--- @field MODIFIER_PROPERTY_PRESERVE_PARTICLES_ON_MODEL_CHANGE 260 Method Name: `PreserveParticlesOnModelChanged` +--- @field MODIFIER_EVENT_ON_ATTACK_FINISHED 261 Method Name: `OnAttackFinished` +--- @field MODIFIER_PROPERTY_IGNORE_COOLDOWN 262 Method Name: `GetModifierIgnoreCooldown` +--- @field MODIFIER_PROPERTY_CAN_ATTACK_TREES 263 Method Name: `GetModifierCanAttackTrees` +--- @field MODIFIER_PROPERTY_VISUAL_Z_DELTA 264 Method Name: `GetVisualZDelta` +--- @field MODIFIER_PROPERTY_VISUAL_Z_SPEED_BASE_OVERRIDE 265 Method Name: `GetVisualZSpeedBaseOverride` +--- @field MODIFIER_PROPERTY_INCOMING_DAMAGE_ILLUSION 266 +--- @field MODIFIER_PROPERTY_DONT_GIVE_VISION_OF_ATTACKER 267 Method Name: `GetModifierNoVisionOfAttacker` +--- @field MODIFIER_PROPERTY_TOOLTIP2 268 Method Name: `OnTooltip2` +--- @field MODIFIER_EVENT_ON_ATTACK_RECORD_DESTROY 269 Method Name: `OnAttackRecordDestroy` +--- @field MODIFIER_EVENT_ON_PROJECTILE_OBSTRUCTION_HIT 270 Method Name: `OnProjectileObstructionHit` +--- @field MODIFIER_PROPERTY_SUPPRESS_TELEPORT 271 Method Name: `GetSuppressTeleport` +--- @field MODIFIER_EVENT_ON_ATTACK_CANCELLED 272 Method Name: `OnAttackCancelled` +--- @field MODIFIER_PROPERTY_SUPPRESS_CLEAVE 273 Method Name: `GetSuppressCleave` +--- @field MODIFIER_PROPERTY_BOT_ATTACK_SCORE_BONUS 274 Method Name: `BotAttackScoreBonus` +--- @field MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE 275 Method Name: `GetModifierAttackSpeedReductionPercentage` +--- @field MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE 276 Method Name: `GetModifierMoveSpeedReductionPercentage` +--- @field MODIFIER_PROPERTY_ATTACK_WHILE_MOVING_TARGET 277 +--- @field MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE 278 Method Name: `GetModifierAttackSpeedPercentage` +--- @field MODIFIER_EVENT_ON_ATTEMPT_PROJECTILE_DODGE 279 Method Name: `OnAttemptProjectileDodge` +--- @field MODIFIER_EVENT_ON_PREDEBUFF_APPLIED 280 Method Name: `OnPreDebuffApplied` +--- @field MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_STACKING 281 Method Name: `GetModifierPercentageCooldownStacking` +--- @field MODIFIER_PROPERTY_SPELL_REDIRECT_TARGET 282 Method Name: `GetModifierSpellRedirectTarget` +--- @field MODIFIER_PROPERTY_TURN_RATE_CONSTANT 283 Method Name: `GetModifierTurnRateConstant` +--- @field MODIFIER_PROPERTY_PACK_RAT 284 Method Name: `GetModifierIsPackRat` +--- @field MODIFIER_PROPERTY_PHYSICALDAMAGEOUTGOING_PERCENTAGE 285 Method Name: `GetModifierPhysicalDamageOutgoing_Percentage` +--- @field MODIFIER_PROPERTY_KNOCKBACK_AMPLIFICATION_PERCENTAGE 286 Method Name: `GetModifierKnockbackAmplification_Percentage` +--- @field MODIFIER_PROPERTY_HEALTHBAR_PIPS 287 Return value is a count of pips. Method Name: `GetModifierHealthBarPips`. +--- @field MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT 288 This property controls 'universal' shield, if defined both on client and server. Return value on client should be current shield health, as a positive integer, on server - amount of damage blocked. Method Name: `GetModifierIncomingDamageConstant`. +--- @field MODIFIER_EVENT_SPELL_APPLIED_SUCCESSFULLY 289 Method Name: `OnSpellAppliedSuccessfully` +--- @field MODIFIER_PROPERTY_AVOID_DAMAGE_AFTER_REDUCTIONS 290 Method Name: `GetModifierAvoidDamageAfterReductions` +--- @field MODIFIER_PROPERTY_FAIL_ATTACK 291 Method Name: `GetModifierPropetyFailAttack` +--- @field MODIFIER_PROPERTY_PREREDUCE_INCOMING_DAMAGE_MULT 292 Method Name: `GetModifierPrereduceIncomingDamage_Mult` +--- @field MODIFIER_PROPERTY_SUPPRESS_FULLSCREEN_DEATH_FX 293 Method Name: `GetModifierSuppressFullscreenDeathFX` +--- @field MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST 294 Method Name: `MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST` +--- @field MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_MULTIPLICATIVE 295 Method Name: `GetModifierDamageOutgoing_PercentageMultiplicative` +--- @field MODIFIER_PROPERTY_TICK_GOLD_MULTIPLIER 296 Method Name: `GetModifierTickGold_Multiplier` +--- @field MODIFIER_PROPERTY_SLOW_RESISTANCE_UNIQUE 297 Method Name: `GEtModifierSlowResistance_Unique` +--- @field MODIFIER_PROPERTY_SLOW_RESISTANCE_STACKING 298 Method Name: `GetModifierSlowResistance_Stacking` +--- @field MODIFIER_PROPERTY_SLOW_RESISTANCE_APPLIES_TO_ATTACKS 299 Method Name: `GetModifierSlowResistanceAppliesToAttacks` +--- @field MODIFIER_PROPERTY_AOE_BONUS_PERCENTAGE 300 Method Name: `GetModifierAoEBonusPercentage` +--- @field MODIFIER_PROPERTY_PROJECTILE_SPEED 301 Method Name: `GetModifierProjectileSpeed` +--- @field MODIFIER_PROPERTY_PROJECTILE_SPEED_TARGET 302 Method Name: `GetModifierProjectileSpeedTarget` +--- @field MODIFIER_PROPERTY_BECOME_STRENGTH 303 Method Name: `GetModifierBecomeStrength` +--- @field MODIFIER_PROPERTY_BECOME_AGILITY 304 Method Name: `GetModifierBecomeAgility` +--- @field MODIFIER_PROPERTY_BECOME_INTELLIGENCE 305 Method Name: `GetModifierBecomeIntelligence` +--- @field MODIFIER_PROPERTY_BECOME_UNIVERSAL 306 Method Name: `GetModifierBecomeUniversal` +--- @field MODIFIER_EVENT_ON_FORCE_PROC_MAGIC_STICK 307 Method Name: `OnForceProcMagicStick` +--- @field MODIFIER_EVENT_ON_DAMAGE_HPLOSS 308 Method Name: `OnDamageHPLoss` +--- @field MODIFIER_PROPERTY_SHARE_XPRUNE 309 Method Name: `GetModifierShareXPRune` +--- @field MODIFIER_PROPERTY_XP_FOUNTAIN_COUNTDOWN_TIME_OVERRIDE 310 Method Name: `GetModifierXPFountainCountdownTimeOverride` +--- @field MODIFIER_PROPERTY_NO_FREE_TP_SCROLL_ON_DEATH 311 Method Name: `GetModifierNoFreeTPScrollOnDeath` +--- @field MODIFIER_PROPERTY_HAS_BONUS_NEUTRAL_ITEM_CHOICE 312 Method Name: `GetModifierHasBonusNeutralItemChoice` +--- @field MODIFIER_PROPERTY_PRESERVE_NEUTRAL_ITEM_PASSIVES 313 Method Name: `GetModifierPreserveNeutralItemPassives` +--- @field MODIFIER_PROPERTY_FORCE_MAX_HEALTH 314 Method Name: `GetModifierForceMaxHealth` +--- @field MODIFIER_PROPERTY_FORCE_MAX_MANA 315 Method Name: `GetModifierForceMaxMana` +--- @field MODIFIER_PROPERTY_AOE_BONUS_CONSTANT 316 Method Name: `GetModifierAoEBonusConstant` +--- @field MODIFIER_PROPERTY_AOE_BONUS_CONSTANT_STACKING 317 Method Name: `GetModifierAoEBonusConstantStacking` +--- @field MODIFIER_EVENT_ON_TAKEDAMAGE_POST_UNAVOIDABLE_BLOCK 318 Method Name: `OnTakeDamagePostUnavoidableBlock` +--- @field MODIFIER_EVENT_ON_MUTE_DAMAGE_ABILITIES 319 Method Name: `OnMuteDamageAbilities` +--- @field MODIFIER_PROPERTY_SUPPRESS_CRIT 320 Method Name: `GetSuppressCrit` +--- @field MODIFIER_PROPERTY_ABILITY_POINTS 321 Method Name: `GetModifierAbilityPoints` +--- @field MODIFIER_PROPERTY_BUYBACK_PENALTY_PERCENT 322 Method Name: `GetModifierBuybackPenaltyPercent` +--- @field MODIFIER_PROPERTY_ITEM_SELLBACK_COST 323 Method Name: `GetModifierItemSellbackCost` +--- @field MODIFIER_PROPERTY_DISASSEMBLE_ANYTHING 324 Method Name: `GetModifierDisassembleAnything` +--- @field MODIFIER_PROPERTY_FIXED_MANA_REGEN 325 Method Name: `GetModifierFixedManaRegen` +--- @field MODIFIER_PROPERTY_BONUS_UPHILL_MISS_CHANCE 326 Method Name: `GetModifierBonusUphillMissChance` +--- @field MODIFIER_PROPERTY_CREEP_DENY_PERCENT 327 Method Name: `GetModifierCreepDenyPercent` +--- @field MODIFIER_PROPERTY_ATTACKSPEED_ABSOLUTE_MAX 328 Method Name: `GetModifierAttackSpeedAbsoluteMax` +--- @field MODIFIER_PROPERTY_FOW_TEAM 329 Method Name: `GetModifierFoWTeam` +--- @field MODIFIER_EVENT_ON_HERO_BEGIN_DYING 330 Method Name: `OnHeroBeginDying` +--- @field MODIFIER_PROPERTY_BONUS_LOTUS_HEAL 331 Method Name: `GetModifierBonusLotusHeal` +--- @field MODIFIER_PROPERTY_BASE_HP_REGEN_PER_STR_BONUS_PERCENTAGE 332 Method Name: `GetModifierBonusLotusHeal` +--- @field MODIFIER_PROPERTY_BASE_ARMOR_PER_AGI_BONUS_PERCENTAGE 333 Method Name: `GetModifierBonusLotusHeal` +--- @field MODIFIER_PROPERTY_BASE_MP_REGEN_PER_INT_BONUS_PERCENTAGE 334 Method Name: `GetModifierBonusLotusHeal` +--- @field MODIFIER_PROPERTY_BASE_MRES_PER_INT_BONUS_PERCENTAGE 335 Method Name: `GetModifierBonusLotusHeal` +--- @field MODIFIER_EVENT_ON_DAY_STARTED 336 Method Name: `OnDayStarted` +--- @field MODIFIER_EVENT_ON_NIGHT_STARTED 337 Method Name: `OnNightStarted` +--- @field MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_CHANCE 338 Method Name: `GetModifierCreateBonusIllusionChance` +--- @field MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_COUNT 339 Method Name: `GetModifierCreateBonusIllusionCount` +--- @field MODIFIER_PROPERTY_PSEUDORANDOM_BONUS 340 Method Name: `GetModofierPropertyPseudoRandomBonus` +--- @field MODIFIER_PROPERTY_ATTACK_HEIGHT_BONUS 341 Method Name: `GetModifierAttackHeightBonus` +--- @field MODIFIER_PROPERTY_SKIP_ATTACK_REGULATOR 342 Method Name: `GetSkipAttackRegulator` +--- @field MODIFIER_PROPERTY_MISS_PERCENTAGE_TARGET 343 Method Name: `GetModifierMiss_Percentage_Target` +--- @field MODIFIER_PROPERTY_ADDITIONAL_NEUTRAL_ITEM_DROPS 344 Method Name: `GetModifierAdditionalNutralItemDrops` +--- @field MODIFIER_PROPERTY_KILL_STREAK_BONUS_GOLD_PERCENTAGE 345 Method Name: `GetModifierKillStreakBonusGoldPercentage` +--- @field MODIFIER_PROPERTY_HP_REGEN_MULTIPLIER_PRE_AMPLIFICATION 346 Method Name: `GetModifierHPRegenMultiplierPreAmplification` +--- @field MODIFIER_PROPERTY_HEROFACET_OVERRIDE 347 Method Name: `GetModifierHeroFacetOverride` +--- @field MODIFIER_EVENT_ON_TREE_CUT_DOWN 348 Method Name: `OnTreeCutDown` +--- @field MODIFIER_EVENT_ON_CLEAVE_ATTACK_LANDED 349 Method Name: `OnCleaveAttackLanded` +--- @field MODIFIER_PROPERTY_MIN_ATTRIBUTE_LEVEL 350 Method Name: `MinAttributeLevel` +--- @field MODIFIER_PROPERTY_TIER_TOKEN_REROLL 351 Method Name: `GetTierTokenReroll` +--- @field MODIFIER_PROPERTY_VISION_DEGREES_RESTRICTION 352 Method Name: `GetVisionDegreeRestriction` +--- @field MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_STACKING 353 Method Name: `GetModifierTotal_ConstantBlockStacking` +--- @field MODIFIER_PROPERTY_INVENTORY_SLOT_RESTRICTED 354 Method Name: `GetModifierInventorySlotRestricted` +--- @field MODIFIER_EVENT_ON_TIER_TOKEN_REROLLED 355 Method Name: `OnTierTokenRerolled` +--- @field MODIFIER_PROPERTY_REDIRECT_SPELL 356 Method Name: `GetRedirectSpell` +--- @field MODIFIER_PROPERTY_BASEATTACK_POSTBONUS 357 Method Name: `GetBaseAttackPostBonus` +--- @field MODIFIER_EVENT_ON_FOW_TEAM_CHANGED 358 Method Name: `OnFoWTeamChanged` +--- @field MODIFIER_PROPERTY_SUPPRESS_ATTACK_PROCS 359 Method Name: `GetSuppressAttackProcs` +--- @field MODIFIER_EVENT_ON_ABILITY_TOGGLED 360 Method Name: `OnAbilityToggled` +--- @field MODIFIER_PROPERTY_AVOID_ATTACK_PROCS 361 Method Name: `GetModifierAvoidAttackProcs` +--- @field MODIFIER_EVENT_ON_RUNE_SPAWN 362 Method Name: `OnRuneSpawn` +--- @field MODIFIER_PROPERTY_PHYSICAL_LIFESTEAL 363 Method Name: `GetModifierProperty_PhysicalLifesteal` +--- @field MODIFIER_PROPERTY_MAGICAL_LIFESTEAL 364 Method Name: `GetModifierProperty_MagicalLifesteal` +--- @field MODIFIER_EVENT_ON_PURE_DAMAGE_CALCULATED 365 Method Name: `OnPureDamageCalculated` +--- @field MODIFIER_EVENT_NEUTRAL_TRINKET_OPTIONS 366 Method Name: `GetModifierNeutralTrinketOptions` +--- @field MODIFIER_EVENT_NEUTRAL_ENHANCEMENT_OPTIONS 367 Method Name: `GetModifierNeutralEnhancementOptions` +--- @field MODIFIER_PROPERTY_MOVESPEED_MAX_BONUS_CONSTANT 368 Method Name: `GetModifierMoveSpeedMax_BonusConstant` +--- @field MODIFIER_PROPERTY_MOVESPEED_POST_MULTIPLIER_BONUS_CONSTANT 369 Method Name: `GetModifierMoveSpeedPostMultiplierBonus_Constant ` +--- @field MODIFIER_PROPERTY_FORBID_ILLUSIONS 370 Method Name: `GetModifierPropertyForbidIllusions` +--- @field MODIFIER_PROPERTY_MANACOST_OVERRIDE 371 Method Name: `GetModifierPropertyManacostOverride` +--- @field MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION 372 Method Name: `GetModifierPropertyRestorationAmplification` +--- @field MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION_UNIQUE 373 Method Name: `GetModifierPropertyRestorationAmplificationUnique` +--- @field MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE_UNIQUE 374 Method Name: `GetModifierPropertyHealingAmplificationUnique` +--- @field MODIFIER_PROPERTY_SUPPRESS_INCOMING_CRIT 375 Method Name: `GetSuppressIncomingCrit` +--- @field MODIFIER_PROPERTY_UPGRADE_NEUTRAL_ARTIFACTS 376 Method Name: `GetModifierPropertyUpgradeNeutralArtifacts` +--- @field MODIFIER_PROPERTY_CONSUMABLE_USE_SPEED 377 Method Name: `GetModifierPropertyConsumableUseSpeed` +--- @field MODIFIER_PROPERTY_FORCE_NETWORK_TRANSMIT 378 +--- @field MODIFIER_FUNCTION_LAST 379 +--- @field MODIFIER_FUNCTION_INVALID 65535 +local modifierfunction = {} +MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE = modifierfunction.MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE +MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_TARGET = modifierfunction.MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_TARGET +MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_PROC = modifierfunction.MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_PROC +MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_POST_CRIT = modifierfunction.MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_POST_CRIT +MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE = modifierfunction.MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE +MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PHYSICAL = modifierfunction.MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PHYSICAL +MODIFIER_PROPERTY_PROCATTACK_CONVERT_PHYSICAL_TO_MAGICAL = modifierfunction.MODIFIER_PROPERTY_PROCATTACK_CONVERT_PHYSICAL_TO_MAGICAL +MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL = modifierfunction.MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL +MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PURE = modifierfunction.MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PURE +MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL_TARGET = modifierfunction.MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_MAGICAL_TARGET +MODIFIER_PROPERTY_PROCATTACK_FEEDBACK = modifierfunction.MODIFIER_PROPERTY_PROCATTACK_FEEDBACK +MODIFIER_PROPERTY_OVERRIDE_ATTACK_DAMAGE = modifierfunction.MODIFIER_PROPERTY_OVERRIDE_ATTACK_DAMAGE +MODIFIER_PROPERTY_PRE_ATTACK = modifierfunction.MODIFIER_PROPERTY_PRE_ATTACK +MODIFIER_PROPERTY_INVISIBILITY_LEVEL = modifierfunction.MODIFIER_PROPERTY_INVISIBILITY_LEVEL +MODIFIER_PROPERTY_INVISIBILITY_ATTACK_BEHAVIOR_EXCEPTION = modifierfunction.MODIFIER_PROPERTY_INVISIBILITY_ATTACK_BEHAVIOR_EXCEPTION +MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY = modifierfunction.MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY +MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT +MODIFIER_PROPERTY_MOVESPEED_BASE_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BASE_OVERRIDE +MODIFIER_PROPERTY_MOVESPEED_MIN_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_MIN_OVERRIDE +MODIFIER_PROPERTY_MOVESPEED_MAX_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_MAX_OVERRIDE +MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE +MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE_UNIQUE +MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE +MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE_2 = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_UNIQUE_2 +MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE +MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE_2 = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT_UNIQUE_2 +MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE +MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MIN = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MIN +MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MAX = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MAX +MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT = modifierfunction.MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT +MODIFIER_PROPERTY_MOVESPEED_LIMIT = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_LIMIT +MODIFIER_PROPERTY_ATTACKSPEED_BASE_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_ATTACKSPEED_BASE_OVERRIDE +MODIFIER_PROPERTY_FIXED_ATTACK_RATE = modifierfunction.MODIFIER_PROPERTY_FIXED_ATTACK_RATE +MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT = modifierfunction.MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT +MODIFIER_PROPERTY_IGNORE_ATTACKSPEED_LIMIT = modifierfunction.MODIFIER_PROPERTY_IGNORE_ATTACKSPEED_LIMIT +MODIFIER_PROPERTY_COOLDOWN_REDUCTION_CONSTANT = modifierfunction.MODIFIER_PROPERTY_COOLDOWN_REDUCTION_CONSTANT +MODIFIER_PROPERTY_MANACOST_REDUCTION_CONSTANT = modifierfunction.MODIFIER_PROPERTY_MANACOST_REDUCTION_CONSTANT +MODIFIER_PROPERTY_HEALTHCOST_REDUCTION_CONSTANT = modifierfunction.MODIFIER_PROPERTY_HEALTHCOST_REDUCTION_CONSTANT +MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT = modifierfunction.MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT +MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT_ADJUST = modifierfunction.MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT_ADJUST +MODIFIER_PROPERTY_BASE_ATTACK_TIME_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BASE_ATTACK_TIME_PERCENTAGE +MODIFIER_PROPERTY_ATTACK_POINT_CONSTANT = modifierfunction.MODIFIER_PROPERTY_ATTACK_POINT_CONSTANT +MODIFIER_PROPERTY_BONUSDAMAGEOUTGOING_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BONUSDAMAGEOUTGOING_PERCENTAGE +MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE +MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION = modifierfunction.MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION +MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION_AMPLIFY = modifierfunction.MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION_AMPLIFY +MODIFIER_PROPERTY_TOTALDAMAGEOUTGOING_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_TOTALDAMAGEOUTGOING_PERCENTAGE +MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_CREEP = modifierfunction.MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_CREEP +MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_UNIQUE +MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_TARGET = modifierfunction.MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_TARGET +MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE = modifierfunction.MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE +MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET = modifierfunction.MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET +MODIFIER_PROPERTY_HP_REGEN_CAN_BE_NEGATIVE = modifierfunction.MODIFIER_PROPERTY_HP_REGEN_CAN_BE_NEGATIVE +MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE_UNIQUE +MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE_UNIQUE +MODIFIER_PROPERTY_MANA_DRAIN_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MANA_DRAIN_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_MP_RESTORE_AMPLIFY_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MP_RESTORE_AMPLIFY_PERCENTAGE +MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE +MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE_UNIQUE +MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE +MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE +MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_CONSTANT = modifierfunction.MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_CONSTANT +MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT = modifierfunction.MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT +MODIFIER_PROPERTY_EVASION_CONSTANT = modifierfunction.MODIFIER_PROPERTY_EVASION_CONSTANT +MODIFIER_PROPERTY_NEGATIVE_EVASION_CONSTANT = modifierfunction.MODIFIER_PROPERTY_NEGATIVE_EVASION_CONSTANT +MODIFIER_PROPERTY_STATUS_RESISTANCE = modifierfunction.MODIFIER_PROPERTY_STATUS_RESISTANCE +MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING = modifierfunction.MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING +MODIFIER_PROPERTY_STATUS_RESISTANCE_CASTER = modifierfunction.MODIFIER_PROPERTY_STATUS_RESISTANCE_CASTER +MODIFIER_PROPERTY_AVOID_DAMAGE = modifierfunction.MODIFIER_PROPERTY_AVOID_DAMAGE +MODIFIER_PROPERTY_AVOID_SPELL = modifierfunction.MODIFIER_PROPERTY_AVOID_SPELL +MODIFIER_PROPERTY_MISS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MISS_PERCENTAGE +MODIFIER_PROPERTY_PHYSICAL_ARMOR_BASE_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_BASE_PERCENTAGE +MODIFIER_PROPERTY_PHYSICAL_ARMOR_TOTAL_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_TOTAL_PERCENTAGE +MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS +MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE +MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE +MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_POST = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_POST +MODIFIER_PROPERTY_MIN_PHYSICAL_ARMOR = modifierfunction.MODIFIER_PROPERTY_MIN_PHYSICAL_ARMOR +MODIFIER_PROPERTY_IGNORE_PHYSICAL_ARMOR = modifierfunction.MODIFIER_PROPERTY_IGNORE_PHYSICAL_ARMOR +MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BASE_REDUCTION = modifierfunction.MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BASE_REDUCTION +MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DIRECT_MODIFICATION = modifierfunction.MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DIRECT_MODIFICATION +MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS = modifierfunction.MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS +MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_ILLUSIONS = modifierfunction.MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_ILLUSIONS +MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS_UNIQUE +MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE +MODIFIER_PROPERTY_BASE_MANA_REGEN = modifierfunction.MODIFIER_PROPERTY_BASE_MANA_REGEN +MODIFIER_PROPERTY_MANA_REGEN_CONSTANT = modifierfunction.MODIFIER_PROPERTY_MANA_REGEN_CONSTANT +MODIFIER_PROPERTY_MANA_REGEN_CONSTANT_UNIQUE = modifierfunction.MODIFIER_PROPERTY_MANA_REGEN_CONSTANT_UNIQUE +MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE +MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT = modifierfunction.MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT +MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE +MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_HEALTH_REGEN_PERCENTAGE_UNIQUE +MODIFIER_PROPERTY_HEALTH_BONUS = modifierfunction.MODIFIER_PROPERTY_HEALTH_BONUS +MODIFIER_PROPERTY_MANA_BONUS = modifierfunction.MODIFIER_PROPERTY_MANA_BONUS +MODIFIER_PROPERTY_EXTRA_STRENGTH_BONUS = modifierfunction.MODIFIER_PROPERTY_EXTRA_STRENGTH_BONUS +MODIFIER_PROPERTY_EXTRA_HEALTH_BONUS = modifierfunction.MODIFIER_PROPERTY_EXTRA_HEALTH_BONUS +MODIFIER_PROPERTY_EXTRA_MANA_BONUS = modifierfunction.MODIFIER_PROPERTY_EXTRA_MANA_BONUS +MODIFIER_PROPERTY_EXTRA_MANA_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_EXTRA_MANA_BONUS_PERCENTAGE +MODIFIER_PROPERTY_EXTRA_HEALTH_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_EXTRA_HEALTH_PERCENTAGE +MODIFIER_PROPERTY_EXTRA_MANA_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_EXTRA_MANA_PERCENTAGE +MODIFIER_PROPERTY_STATS_STRENGTH_BONUS = modifierfunction.MODIFIER_PROPERTY_STATS_STRENGTH_BONUS +MODIFIER_PROPERTY_STATS_AGILITY_BONUS = modifierfunction.MODIFIER_PROPERTY_STATS_AGILITY_BONUS +MODIFIER_PROPERTY_STATS_INTELLECT_BONUS = modifierfunction.MODIFIER_PROPERTY_STATS_INTELLECT_BONUS +MODIFIER_PROPERTY_STATS_STRENGTH_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_STATS_STRENGTH_BONUS_PERCENTAGE +MODIFIER_PROPERTY_STATS_AGILITY_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_STATS_AGILITY_BONUS_PERCENTAGE +MODIFIER_PROPERTY_STATS_INTELLECT_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_STATS_INTELLECT_BONUS_PERCENTAGE +MODIFIER_PROPERTY_CAST_RANGE_BONUS = modifierfunction.MODIFIER_PROPERTY_CAST_RANGE_BONUS +MODIFIER_PROPERTY_CAST_RANGE_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_CAST_RANGE_BONUS_PERCENTAGE +MODIFIER_PROPERTY_CAST_RANGE_BONUS_TARGET = modifierfunction.MODIFIER_PROPERTY_CAST_RANGE_BONUS_TARGET +MODIFIER_PROPERTY_CAST_RANGE_BONUS_STACKING = modifierfunction.MODIFIER_PROPERTY_CAST_RANGE_BONUS_STACKING +MODIFIER_PROPERTY_ATTACK_RANGE_BASE_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_ATTACK_RANGE_BASE_OVERRIDE +MODIFIER_PROPERTY_ATTACK_RANGE_BONUS = modifierfunction.MODIFIER_PROPERTY_ATTACK_RANGE_BONUS +MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_UNIQUE = modifierfunction.MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_UNIQUE +MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_ATTACK_RANGE_BONUS_PERCENTAGE +MODIFIER_PROPERTY_MAX_ATTACK_RANGE = modifierfunction.MODIFIER_PROPERTY_MAX_ATTACK_RANGE +MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS = modifierfunction.MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS +MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS_PERCENTAGE +MODIFIER_PROPERTY_PROJECTILE_NAME = modifierfunction.MODIFIER_PROPERTY_PROJECTILE_NAME +MODIFIER_PROPERTY_REINCARNATION = modifierfunction.MODIFIER_PROPERTY_REINCARNATION +MODIFIER_PROPERTY_REINCARNATION_SUPPRESS_FX = modifierfunction.MODIFIER_PROPERTY_REINCARNATION_SUPPRESS_FX +MODIFIER_PROPERTY_RESPAWNTIME = modifierfunction.MODIFIER_PROPERTY_RESPAWNTIME +MODIFIER_PROPERTY_RESPAWNTIME_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_RESPAWNTIME_PERCENTAGE +MODIFIER_PROPERTY_RESPAWNTIME_STACKING = modifierfunction.MODIFIER_PROPERTY_RESPAWNTIME_STACKING +MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE +MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_ONGOING = modifierfunction.MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_ONGOING +MODIFIER_PROPERTY_CASTTIME_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_CASTTIME_PERCENTAGE +MODIFIER_PROPERTY_ATTACK_ANIM_TIME_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_ATTACK_ANIM_TIME_PERCENTAGE +MODIFIER_PROPERTY_MANACOST_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MANACOST_PERCENTAGE +MODIFIER_PROPERTY_MANACOST_PERCENTAGE_STACKING = modifierfunction.MODIFIER_PROPERTY_MANACOST_PERCENTAGE_STACKING +MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE +MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE_STACKING = modifierfunction.MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE_STACKING +MODIFIER_PROPERTY_DEATHGOLDCOST = modifierfunction.MODIFIER_PROPERTY_DEATHGOLDCOST +MODIFIER_PROPERTY_PERCENTAGE_DEATHGOLDCOST = modifierfunction.MODIFIER_PROPERTY_PERCENTAGE_DEATHGOLDCOST +MODIFIER_PROPERTY_EXP_RATE_BOOST = modifierfunction.MODIFIER_PROPERTY_EXP_RATE_BOOST +MODIFIER_PROPERTY_GOLD_RATE_BOOST = modifierfunction.MODIFIER_PROPERTY_GOLD_RATE_BOOST +MODIFIER_PROPERTY_PREATTACK_CRITICALSTRIKE = modifierfunction.MODIFIER_PROPERTY_PREATTACK_CRITICALSTRIKE +MODIFIER_PROPERTY_PREATTACK_TARGET_CRITICALSTRIKE = modifierfunction.MODIFIER_PROPERTY_PREATTACK_TARGET_CRITICALSTRIKE +MODIFIER_PROPERTY_MAGICAL_CONSTANT_BLOCK = modifierfunction.MODIFIER_PROPERTY_MAGICAL_CONSTANT_BLOCK +MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK +MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK_SPECIAL = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK_SPECIAL +MODIFIER_PROPERTY_INNATE_DAMAGE_BLOCK_PCT_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_INNATE_DAMAGE_BLOCK_PCT_OVERRIDE +MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR = modifierfunction.MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR +MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK = modifierfunction.MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK +MODIFIER_PROPERTY_OVERRIDE_ANIMATION = modifierfunction.MODIFIER_PROPERTY_OVERRIDE_ANIMATION +MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE = modifierfunction.MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE +MODIFIER_PROPERTY_ABSORB_SPELL = modifierfunction.MODIFIER_PROPERTY_ABSORB_SPELL +MODIFIER_PROPERTY_REFLECT_SPELL = modifierfunction.MODIFIER_PROPERTY_REFLECT_SPELL +MODIFIER_PROPERTY_DISABLE_AUTOATTACK = modifierfunction.MODIFIER_PROPERTY_DISABLE_AUTOATTACK +MODIFIER_PROPERTY_BONUS_DAY_VISION = modifierfunction.MODIFIER_PROPERTY_BONUS_DAY_VISION +MODIFIER_PROPERTY_BONUS_DAY_VISION_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BONUS_DAY_VISION_PERCENTAGE +MODIFIER_PROPERTY_BONUS_NIGHT_VISION = modifierfunction.MODIFIER_PROPERTY_BONUS_NIGHT_VISION +MODIFIER_PROPERTY_BONUS_NIGHT_VISION_UNIQUE = modifierfunction.MODIFIER_PROPERTY_BONUS_NIGHT_VISION_UNIQUE +MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE +MODIFIER_PROPERTY_FIXED_DAY_VISION = modifierfunction.MODIFIER_PROPERTY_FIXED_DAY_VISION +MODIFIER_PROPERTY_FIXED_NIGHT_VISION = modifierfunction.MODIFIER_PROPERTY_FIXED_NIGHT_VISION +MODIFIER_PROPERTY_MIN_HEALTH = modifierfunction.MODIFIER_PROPERTY_MIN_HEALTH +MODIFIER_PROPERTY_MIN_MANA = modifierfunction.MODIFIER_PROPERTY_MIN_MANA +MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL = modifierfunction.MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL +MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL = modifierfunction.MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL +MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE = modifierfunction.MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PURE +MODIFIER_PROPERTY_IS_ILLUSION = modifierfunction.MODIFIER_PROPERTY_IS_ILLUSION +MODIFIER_PROPERTY_ILLUSION_LABEL = modifierfunction.MODIFIER_PROPERTY_ILLUSION_LABEL +MODIFIER_PROPERTY_STRONG_ILLUSION = modifierfunction.MODIFIER_PROPERTY_STRONG_ILLUSION +MODIFIER_PROPERTY_SUPER_ILLUSION = modifierfunction.MODIFIER_PROPERTY_SUPER_ILLUSION +MODIFIER_PROPERTY_SUPER_ILLUSION_WITH_ULTIMATE = modifierfunction.MODIFIER_PROPERTY_SUPER_ILLUSION_WITH_ULTIMATE +MODIFIER_PROPERTY_XP_DURING_DEATH = modifierfunction.MODIFIER_PROPERTY_XP_DURING_DEATH +MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_TURN_RATE_PERCENTAGE +MODIFIER_PROPERTY_TURN_RATE_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_TURN_RATE_OVERRIDE +MODIFIER_PROPERTY_DISABLE_HEALING = modifierfunction.MODIFIER_PROPERTY_DISABLE_HEALING +MODIFIER_PROPERTY_DISABLE_MANA_GAIN = modifierfunction.MODIFIER_PROPERTY_DISABLE_MANA_GAIN +MODIFIER_PROPERTY_ALWAYS_ALLOW_ATTACK = modifierfunction.MODIFIER_PROPERTY_ALWAYS_ALLOW_ATTACK +MODIFIER_PROPERTY_ALWAYS_ETHEREAL_ATTACK = modifierfunction.MODIFIER_PROPERTY_ALWAYS_ETHEREAL_ATTACK +MODIFIER_PROPERTY_OVERRIDE_ATTACK_MAGICAL = modifierfunction.MODIFIER_PROPERTY_OVERRIDE_ATTACK_MAGICAL +MODIFIER_PROPERTY_UNIT_STATS_NEEDS_REFRESH = modifierfunction.MODIFIER_PROPERTY_UNIT_STATS_NEEDS_REFRESH +MODIFIER_PROPERTY_BOUNTY_CREEP_MULTIPLIER = modifierfunction.MODIFIER_PROPERTY_BOUNTY_CREEP_MULTIPLIER +MODIFIER_PROPERTY_BOUNTY_OTHER_MULTIPLIER = modifierfunction.MODIFIER_PROPERTY_BOUNTY_OTHER_MULTIPLIER +MODIFIER_PROPERTY_UNIT_DISALLOW_UPGRADING = modifierfunction.MODIFIER_PROPERTY_UNIT_DISALLOW_UPGRADING +MODIFIER_PROPERTY_DODGE_PROJECTILE = modifierfunction.MODIFIER_PROPERTY_DODGE_PROJECTILE +MODIFIER_PROPERTY_TRIGGER_COSMETIC_AND_END_ATTACK = modifierfunction.MODIFIER_PROPERTY_TRIGGER_COSMETIC_AND_END_ATTACK +MODIFIER_PROPERTY_MAX_DEBUFF_DURATION = modifierfunction.MODIFIER_PROPERTY_MAX_DEBUFF_DURATION +MODIFIER_PROPERTY_PRIMARY_STAT_DAMAGE_MULTIPLIER = modifierfunction.MODIFIER_PROPERTY_PRIMARY_STAT_DAMAGE_MULTIPLIER +MODIFIER_PROPERTY_PREATTACK_DEADLY_BLOW = modifierfunction.MODIFIER_PROPERTY_PREATTACK_DEADLY_BLOW +MODIFIER_PROPERTY_ALWAYS_AUTOATTACK_WHILE_HOLD_POSITION = modifierfunction.MODIFIER_PROPERTY_ALWAYS_AUTOATTACK_WHILE_HOLD_POSITION +MODIFIER_PROPERTY_PHYSICAL_ARMOR_PIERCING_PERCENTAGE_TARGET = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_ARMOR_PIERCING_PERCENTAGE_TARGET +MODIFIER_PROPERTY_MAGICAL_ARMOR_PIERCING_PERCENTAGE_TARGET = modifierfunction.MODIFIER_PROPERTY_MAGICAL_ARMOR_PIERCING_PERCENTAGE_TARGET +MODIFIER_PROPERTY_CRITICAL_STRIKE_BONUS = modifierfunction.MODIFIER_PROPERTY_CRITICAL_STRIKE_BONUS +MODIFIER_PROPERTY_CONVERT_ATTACK_PHYSICAL_TO_PURE = modifierfunction.MODIFIER_PROPERTY_CONVERT_ATTACK_PHYSICAL_TO_PURE +MODIFIER_EVENT_ON_SPELL_TARGET_READY = modifierfunction.MODIFIER_EVENT_ON_SPELL_TARGET_READY +MODIFIER_EVENT_ON_ATTACK_RECORD = modifierfunction.MODIFIER_EVENT_ON_ATTACK_RECORD +MODIFIER_EVENT_ON_ATTACK_START = modifierfunction.MODIFIER_EVENT_ON_ATTACK_START +MODIFIER_EVENT_ON_ATTACK = modifierfunction.MODIFIER_EVENT_ON_ATTACK +MODIFIER_EVENT_ON_ATTACK_LANDED = modifierfunction.MODIFIER_EVENT_ON_ATTACK_LANDED +MODIFIER_EVENT_ON_ATTACK_FAIL = modifierfunction.MODIFIER_EVENT_ON_ATTACK_FAIL +MODIFIER_EVENT_ON_ATTACK_ALLIED = modifierfunction.MODIFIER_EVENT_ON_ATTACK_ALLIED +MODIFIER_EVENT_ON_PROJECTILE_DODGE = modifierfunction.MODIFIER_EVENT_ON_PROJECTILE_DODGE +MODIFIER_EVENT_ON_ORDER = modifierfunction.MODIFIER_EVENT_ON_ORDER +MODIFIER_EVENT_ON_UNIT_MOVED = modifierfunction.MODIFIER_EVENT_ON_UNIT_MOVED +MODIFIER_EVENT_ON_ABILITY_START = modifierfunction.MODIFIER_EVENT_ON_ABILITY_START +MODIFIER_EVENT_ON_ABILITY_EXECUTED = modifierfunction.MODIFIER_EVENT_ON_ABILITY_EXECUTED +MODIFIER_EVENT_ON_ABILITY_FULLY_CAST = modifierfunction.MODIFIER_EVENT_ON_ABILITY_FULLY_CAST +MODIFIER_EVENT_ON_BREAK_INVISIBILITY = modifierfunction.MODIFIER_EVENT_ON_BREAK_INVISIBILITY +MODIFIER_EVENT_ON_ABILITY_END_CHANNEL = modifierfunction.MODIFIER_EVENT_ON_ABILITY_END_CHANNEL +MODIFIER_EVENT_ON_PROCESS_UPGRADE = modifierfunction.MODIFIER_EVENT_ON_PROCESS_UPGRADE +MODIFIER_EVENT_ON_REFRESH = modifierfunction.MODIFIER_EVENT_ON_REFRESH +MODIFIER_EVENT_ON_TAKEDAMAGE = modifierfunction.MODIFIER_EVENT_ON_TAKEDAMAGE +MODIFIER_EVENT_ON_DEATH_PREVENTED = modifierfunction.MODIFIER_EVENT_ON_DEATH_PREVENTED +MODIFIER_EVENT_ON_STATE_CHANGED = modifierfunction.MODIFIER_EVENT_ON_STATE_CHANGED +MODIFIER_EVENT_ON_ORB_EFFECT = modifierfunction.MODIFIER_EVENT_ON_ORB_EFFECT +MODIFIER_EVENT_ON_PROCESS_CLEAVE = modifierfunction.MODIFIER_EVENT_ON_PROCESS_CLEAVE +MODIFIER_EVENT_ON_DAMAGE_CALCULATED = modifierfunction.MODIFIER_EVENT_ON_DAMAGE_CALCULATED +MODIFIER_EVENT_ON_MAGIC_DAMAGE_CALCULATED = modifierfunction.MODIFIER_EVENT_ON_MAGIC_DAMAGE_CALCULATED +MODIFIER_EVENT_ON_ATTACKED = modifierfunction.MODIFIER_EVENT_ON_ATTACKED +MODIFIER_EVENT_ON_DEATH = modifierfunction.MODIFIER_EVENT_ON_DEATH +MODIFIER_EVENT_ON_DEATH_COMPLETED = modifierfunction.MODIFIER_EVENT_ON_DEATH_COMPLETED +MODIFIER_EVENT_ON_RESPAWN = modifierfunction.MODIFIER_EVENT_ON_RESPAWN +MODIFIER_EVENT_ON_SPENT_MANA = modifierfunction.MODIFIER_EVENT_ON_SPENT_MANA +MODIFIER_EVENT_ON_SPENT_HEALTH = modifierfunction.MODIFIER_EVENT_ON_SPENT_HEALTH +MODIFIER_EVENT_ON_TELEPORTING = modifierfunction.MODIFIER_EVENT_ON_TELEPORTING +MODIFIER_EVENT_ON_TELEPORTED = modifierfunction.MODIFIER_EVENT_ON_TELEPORTED +MODIFIER_EVENT_ON_SET_LOCATION = modifierfunction.MODIFIER_EVENT_ON_SET_LOCATION +MODIFIER_EVENT_ON_HEALTH_GAINED = modifierfunction.MODIFIER_EVENT_ON_HEALTH_GAINED +MODIFIER_EVENT_ON_MANA_GAINED = modifierfunction.MODIFIER_EVENT_ON_MANA_GAINED +MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT = modifierfunction.MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT +MODIFIER_EVENT_ON_HERO_KILLED = modifierfunction.MODIFIER_EVENT_ON_HERO_KILLED +MODIFIER_EVENT_ON_HEAL_RECEIVED = modifierfunction.MODIFIER_EVENT_ON_HEAL_RECEIVED +MODIFIER_EVENT_ON_BUILDING_KILLED = modifierfunction.MODIFIER_EVENT_ON_BUILDING_KILLED +MODIFIER_EVENT_ON_MODEL_CHANGED = modifierfunction.MODIFIER_EVENT_ON_MODEL_CHANGED +MODIFIER_EVENT_ON_MODIFIER_ADDED = modifierfunction.MODIFIER_EVENT_ON_MODIFIER_ADDED +MODIFIER_EVENT_ON_MODIFIER_REMOVED = modifierfunction.MODIFIER_EVENT_ON_MODIFIER_REMOVED +MODIFIER_PROPERTY_TOOLTIP = modifierfunction.MODIFIER_PROPERTY_TOOLTIP +MODIFIER_PROPERTY_MODEL_CHANGE = modifierfunction.MODIFIER_PROPERTY_MODEL_CHANGE +MODIFIER_PROPERTY_MODEL_SCALE = modifierfunction.MODIFIER_PROPERTY_MODEL_SCALE +MODIFIER_PROPERTY_MODEL_SCALE_ANIMATE_TIME = modifierfunction.MODIFIER_PROPERTY_MODEL_SCALE_ANIMATE_TIME +MODIFIER_PROPERTY_MODEL_SCALE_USE_IN_OUT_EASE = modifierfunction.MODIFIER_PROPERTY_MODEL_SCALE_USE_IN_OUT_EASE +MODIFIER_PROPERTY_MODEL_SCALE_CONSTANT = modifierfunction.MODIFIER_PROPERTY_MODEL_SCALE_CONSTANT +MODIFIER_PROPERTY_IS_SCEPTER = modifierfunction.MODIFIER_PROPERTY_IS_SCEPTER +MODIFIER_PROPERTY_IS_SHARD = modifierfunction.MODIFIER_PROPERTY_IS_SHARD +MODIFIER_PROPERTY_RADAR_COOLDOWN_REDUCTION = modifierfunction.MODIFIER_PROPERTY_RADAR_COOLDOWN_REDUCTION +MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS = modifierfunction.MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS +MODIFIER_PROPERTY_TRANSLATE_ATTACK_SOUND = modifierfunction.MODIFIER_PROPERTY_TRANSLATE_ATTACK_SOUND +MODIFIER_PROPERTY_LIFETIME_FRACTION = modifierfunction.MODIFIER_PROPERTY_LIFETIME_FRACTION +MODIFIER_PROPERTY_PROVIDES_FOW_POSITION = modifierfunction.MODIFIER_PROPERTY_PROVIDES_FOW_POSITION +MODIFIER_PROPERTY_SPELLS_REQUIRE_HP = modifierfunction.MODIFIER_PROPERTY_SPELLS_REQUIRE_HP +MODIFIER_PROPERTY_CONVERT_MANA_COST_TO_HEALTH_COST = modifierfunction.MODIFIER_PROPERTY_CONVERT_MANA_COST_TO_HEALTH_COST +MODIFIER_PROPERTY_FORCE_DRAW_MINIMAP = modifierfunction.MODIFIER_PROPERTY_FORCE_DRAW_MINIMAP +MODIFIER_PROPERTY_DISABLE_TURNING = modifierfunction.MODIFIER_PROPERTY_DISABLE_TURNING +MODIFIER_PROPERTY_IGNORE_CAST_ANGLE = modifierfunction.MODIFIER_PROPERTY_IGNORE_CAST_ANGLE +MODIFIER_PROPERTY_CHANGE_ABILITY_VALUE = modifierfunction.MODIFIER_PROPERTY_CHANGE_ABILITY_VALUE +MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL = modifierfunction.MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL +MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL_VALUE = modifierfunction.MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL_VALUE +MODIFIER_PROPERTY_ABILITY_LAYOUT = modifierfunction.MODIFIER_PROPERTY_ABILITY_LAYOUT +MODIFIER_EVENT_ON_DOMINATED = modifierfunction.MODIFIER_EVENT_ON_DOMINATED +MODIFIER_EVENT_ON_KILL = modifierfunction.MODIFIER_EVENT_ON_KILL +MODIFIER_EVENT_ON_ASSIST = modifierfunction.MODIFIER_EVENT_ON_ASSIST +MODIFIER_PROPERTY_TEMPEST_DOUBLE = modifierfunction.MODIFIER_PROPERTY_TEMPEST_DOUBLE +MODIFIER_PROPERTY_PRESERVE_PARTICLES_ON_MODEL_CHANGE = modifierfunction.MODIFIER_PROPERTY_PRESERVE_PARTICLES_ON_MODEL_CHANGE +MODIFIER_EVENT_ON_ATTACK_FINISHED = modifierfunction.MODIFIER_EVENT_ON_ATTACK_FINISHED +MODIFIER_PROPERTY_IGNORE_COOLDOWN = modifierfunction.MODIFIER_PROPERTY_IGNORE_COOLDOWN +MODIFIER_PROPERTY_CAN_ATTACK_TREES = modifierfunction.MODIFIER_PROPERTY_CAN_ATTACK_TREES +MODIFIER_PROPERTY_VISUAL_Z_DELTA = modifierfunction.MODIFIER_PROPERTY_VISUAL_Z_DELTA +MODIFIER_PROPERTY_VISUAL_Z_SPEED_BASE_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_VISUAL_Z_SPEED_BASE_OVERRIDE +MODIFIER_PROPERTY_INCOMING_DAMAGE_ILLUSION = modifierfunction.MODIFIER_PROPERTY_INCOMING_DAMAGE_ILLUSION +MODIFIER_PROPERTY_DONT_GIVE_VISION_OF_ATTACKER = modifierfunction.MODIFIER_PROPERTY_DONT_GIVE_VISION_OF_ATTACKER +MODIFIER_PROPERTY_TOOLTIP2 = modifierfunction.MODIFIER_PROPERTY_TOOLTIP2 +MODIFIER_EVENT_ON_ATTACK_RECORD_DESTROY = modifierfunction.MODIFIER_EVENT_ON_ATTACK_RECORD_DESTROY +MODIFIER_EVENT_ON_PROJECTILE_OBSTRUCTION_HIT = modifierfunction.MODIFIER_EVENT_ON_PROJECTILE_OBSTRUCTION_HIT +MODIFIER_PROPERTY_SUPPRESS_TELEPORT = modifierfunction.MODIFIER_PROPERTY_SUPPRESS_TELEPORT +MODIFIER_EVENT_ON_ATTACK_CANCELLED = modifierfunction.MODIFIER_EVENT_ON_ATTACK_CANCELLED +MODIFIER_PROPERTY_SUPPRESS_CLEAVE = modifierfunction.MODIFIER_PROPERTY_SUPPRESS_CLEAVE +MODIFIER_PROPERTY_BOT_ATTACK_SCORE_BONUS = modifierfunction.MODIFIER_PROPERTY_BOT_ATTACK_SCORE_BONUS +MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_ATTACKSPEED_REDUCTION_PERCENTAGE +MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE +MODIFIER_PROPERTY_ATTACK_WHILE_MOVING_TARGET = modifierfunction.MODIFIER_PROPERTY_ATTACK_WHILE_MOVING_TARGET +MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE +MODIFIER_EVENT_ON_ATTEMPT_PROJECTILE_DODGE = modifierfunction.MODIFIER_EVENT_ON_ATTEMPT_PROJECTILE_DODGE +MODIFIER_EVENT_ON_PREDEBUFF_APPLIED = modifierfunction.MODIFIER_EVENT_ON_PREDEBUFF_APPLIED +MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_STACKING = modifierfunction.MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_STACKING +MODIFIER_PROPERTY_SPELL_REDIRECT_TARGET = modifierfunction.MODIFIER_PROPERTY_SPELL_REDIRECT_TARGET +MODIFIER_PROPERTY_TURN_RATE_CONSTANT = modifierfunction.MODIFIER_PROPERTY_TURN_RATE_CONSTANT +MODIFIER_PROPERTY_PACK_RAT = modifierfunction.MODIFIER_PROPERTY_PACK_RAT +MODIFIER_PROPERTY_PHYSICALDAMAGEOUTGOING_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_PHYSICALDAMAGEOUTGOING_PERCENTAGE +MODIFIER_PROPERTY_KNOCKBACK_AMPLIFICATION_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_KNOCKBACK_AMPLIFICATION_PERCENTAGE +MODIFIER_PROPERTY_HEALTHBAR_PIPS = modifierfunction.MODIFIER_PROPERTY_HEALTHBAR_PIPS +MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT = modifierfunction.MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT +MODIFIER_EVENT_SPELL_APPLIED_SUCCESSFULLY = modifierfunction.MODIFIER_EVENT_SPELL_APPLIED_SUCCESSFULLY +MODIFIER_PROPERTY_AVOID_DAMAGE_AFTER_REDUCTIONS = modifierfunction.MODIFIER_PROPERTY_AVOID_DAMAGE_AFTER_REDUCTIONS +MODIFIER_PROPERTY_FAIL_ATTACK = modifierfunction.MODIFIER_PROPERTY_FAIL_ATTACK +MODIFIER_PROPERTY_PREREDUCE_INCOMING_DAMAGE_MULT = modifierfunction.MODIFIER_PROPERTY_PREREDUCE_INCOMING_DAMAGE_MULT +MODIFIER_PROPERTY_SUPPRESS_FULLSCREEN_DEATH_FX = modifierfunction.MODIFIER_PROPERTY_SUPPRESS_FULLSCREEN_DEATH_FX +MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST = modifierfunction.MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST +MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_MULTIPLICATIVE = modifierfunction.MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_MULTIPLICATIVE +MODIFIER_PROPERTY_TICK_GOLD_MULTIPLIER = modifierfunction.MODIFIER_PROPERTY_TICK_GOLD_MULTIPLIER +MODIFIER_PROPERTY_SLOW_RESISTANCE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_SLOW_RESISTANCE_UNIQUE +MODIFIER_PROPERTY_SLOW_RESISTANCE_STACKING = modifierfunction.MODIFIER_PROPERTY_SLOW_RESISTANCE_STACKING +MODIFIER_PROPERTY_SLOW_RESISTANCE_APPLIES_TO_ATTACKS = modifierfunction.MODIFIER_PROPERTY_SLOW_RESISTANCE_APPLIES_TO_ATTACKS +MODIFIER_PROPERTY_AOE_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_AOE_BONUS_PERCENTAGE +MODIFIER_PROPERTY_PROJECTILE_SPEED = modifierfunction.MODIFIER_PROPERTY_PROJECTILE_SPEED +MODIFIER_PROPERTY_PROJECTILE_SPEED_TARGET = modifierfunction.MODIFIER_PROPERTY_PROJECTILE_SPEED_TARGET +MODIFIER_PROPERTY_BECOME_STRENGTH = modifierfunction.MODIFIER_PROPERTY_BECOME_STRENGTH +MODIFIER_PROPERTY_BECOME_AGILITY = modifierfunction.MODIFIER_PROPERTY_BECOME_AGILITY +MODIFIER_PROPERTY_BECOME_INTELLIGENCE = modifierfunction.MODIFIER_PROPERTY_BECOME_INTELLIGENCE +MODIFIER_PROPERTY_BECOME_UNIVERSAL = modifierfunction.MODIFIER_PROPERTY_BECOME_UNIVERSAL +MODIFIER_EVENT_ON_FORCE_PROC_MAGIC_STICK = modifierfunction.MODIFIER_EVENT_ON_FORCE_PROC_MAGIC_STICK +MODIFIER_EVENT_ON_DAMAGE_HPLOSS = modifierfunction.MODIFIER_EVENT_ON_DAMAGE_HPLOSS +MODIFIER_PROPERTY_SHARE_XPRUNE = modifierfunction.MODIFIER_PROPERTY_SHARE_XPRUNE +MODIFIER_PROPERTY_XP_FOUNTAIN_COUNTDOWN_TIME_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_XP_FOUNTAIN_COUNTDOWN_TIME_OVERRIDE +MODIFIER_PROPERTY_NO_FREE_TP_SCROLL_ON_DEATH = modifierfunction.MODIFIER_PROPERTY_NO_FREE_TP_SCROLL_ON_DEATH +MODIFIER_PROPERTY_HAS_BONUS_NEUTRAL_ITEM_CHOICE = modifierfunction.MODIFIER_PROPERTY_HAS_BONUS_NEUTRAL_ITEM_CHOICE +MODIFIER_PROPERTY_PRESERVE_NEUTRAL_ITEM_PASSIVES = modifierfunction.MODIFIER_PROPERTY_PRESERVE_NEUTRAL_ITEM_PASSIVES +MODIFIER_PROPERTY_FORCE_MAX_HEALTH = modifierfunction.MODIFIER_PROPERTY_FORCE_MAX_HEALTH +MODIFIER_PROPERTY_FORCE_MAX_MANA = modifierfunction.MODIFIER_PROPERTY_FORCE_MAX_MANA +MODIFIER_PROPERTY_AOE_BONUS_CONSTANT = modifierfunction.MODIFIER_PROPERTY_AOE_BONUS_CONSTANT +MODIFIER_PROPERTY_AOE_BONUS_CONSTANT_STACKING = modifierfunction.MODIFIER_PROPERTY_AOE_BONUS_CONSTANT_STACKING +MODIFIER_EVENT_ON_TAKEDAMAGE_POST_UNAVOIDABLE_BLOCK = modifierfunction.MODIFIER_EVENT_ON_TAKEDAMAGE_POST_UNAVOIDABLE_BLOCK +MODIFIER_EVENT_ON_MUTE_DAMAGE_ABILITIES = modifierfunction.MODIFIER_EVENT_ON_MUTE_DAMAGE_ABILITIES +MODIFIER_PROPERTY_SUPPRESS_CRIT = modifierfunction.MODIFIER_PROPERTY_SUPPRESS_CRIT +MODIFIER_PROPERTY_ABILITY_POINTS = modifierfunction.MODIFIER_PROPERTY_ABILITY_POINTS +MODIFIER_PROPERTY_BUYBACK_PENALTY_PERCENT = modifierfunction.MODIFIER_PROPERTY_BUYBACK_PENALTY_PERCENT +MODIFIER_PROPERTY_ITEM_SELLBACK_COST = modifierfunction.MODIFIER_PROPERTY_ITEM_SELLBACK_COST +MODIFIER_PROPERTY_DISASSEMBLE_ANYTHING = modifierfunction.MODIFIER_PROPERTY_DISASSEMBLE_ANYTHING +MODIFIER_PROPERTY_FIXED_MANA_REGEN = modifierfunction.MODIFIER_PROPERTY_FIXED_MANA_REGEN +MODIFIER_PROPERTY_BONUS_UPHILL_MISS_CHANCE = modifierfunction.MODIFIER_PROPERTY_BONUS_UPHILL_MISS_CHANCE +MODIFIER_PROPERTY_CREEP_DENY_PERCENT = modifierfunction.MODIFIER_PROPERTY_CREEP_DENY_PERCENT +MODIFIER_PROPERTY_ATTACKSPEED_ABSOLUTE_MAX = modifierfunction.MODIFIER_PROPERTY_ATTACKSPEED_ABSOLUTE_MAX +MODIFIER_PROPERTY_FOW_TEAM = modifierfunction.MODIFIER_PROPERTY_FOW_TEAM +MODIFIER_EVENT_ON_HERO_BEGIN_DYING = modifierfunction.MODIFIER_EVENT_ON_HERO_BEGIN_DYING +MODIFIER_PROPERTY_BONUS_LOTUS_HEAL = modifierfunction.MODIFIER_PROPERTY_BONUS_LOTUS_HEAL +MODIFIER_PROPERTY_BASE_HP_REGEN_PER_STR_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BASE_HP_REGEN_PER_STR_BONUS_PERCENTAGE +MODIFIER_PROPERTY_BASE_ARMOR_PER_AGI_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BASE_ARMOR_PER_AGI_BONUS_PERCENTAGE +MODIFIER_PROPERTY_BASE_MP_REGEN_PER_INT_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BASE_MP_REGEN_PER_INT_BONUS_PERCENTAGE +MODIFIER_PROPERTY_BASE_MRES_PER_INT_BONUS_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_BASE_MRES_PER_INT_BONUS_PERCENTAGE +MODIFIER_EVENT_ON_DAY_STARTED = modifierfunction.MODIFIER_EVENT_ON_DAY_STARTED +MODIFIER_EVENT_ON_NIGHT_STARTED = modifierfunction.MODIFIER_EVENT_ON_NIGHT_STARTED +MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_CHANCE = modifierfunction.MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_CHANCE +MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_COUNT = modifierfunction.MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_COUNT +MODIFIER_PROPERTY_PSEUDORANDOM_BONUS = modifierfunction.MODIFIER_PROPERTY_PSEUDORANDOM_BONUS +MODIFIER_PROPERTY_ATTACK_HEIGHT_BONUS = modifierfunction.MODIFIER_PROPERTY_ATTACK_HEIGHT_BONUS +MODIFIER_PROPERTY_SKIP_ATTACK_REGULATOR = modifierfunction.MODIFIER_PROPERTY_SKIP_ATTACK_REGULATOR +MODIFIER_PROPERTY_MISS_PERCENTAGE_TARGET = modifierfunction.MODIFIER_PROPERTY_MISS_PERCENTAGE_TARGET +MODIFIER_PROPERTY_ADDITIONAL_NEUTRAL_ITEM_DROPS = modifierfunction.MODIFIER_PROPERTY_ADDITIONAL_NEUTRAL_ITEM_DROPS +MODIFIER_PROPERTY_KILL_STREAK_BONUS_GOLD_PERCENTAGE = modifierfunction.MODIFIER_PROPERTY_KILL_STREAK_BONUS_GOLD_PERCENTAGE +MODIFIER_PROPERTY_HP_REGEN_MULTIPLIER_PRE_AMPLIFICATION = modifierfunction.MODIFIER_PROPERTY_HP_REGEN_MULTIPLIER_PRE_AMPLIFICATION +MODIFIER_PROPERTY_HEROFACET_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_HEROFACET_OVERRIDE +MODIFIER_EVENT_ON_TREE_CUT_DOWN = modifierfunction.MODIFIER_EVENT_ON_TREE_CUT_DOWN +MODIFIER_EVENT_ON_CLEAVE_ATTACK_LANDED = modifierfunction.MODIFIER_EVENT_ON_CLEAVE_ATTACK_LANDED +MODIFIER_PROPERTY_MIN_ATTRIBUTE_LEVEL = modifierfunction.MODIFIER_PROPERTY_MIN_ATTRIBUTE_LEVEL +MODIFIER_PROPERTY_TIER_TOKEN_REROLL = modifierfunction.MODIFIER_PROPERTY_TIER_TOKEN_REROLL +MODIFIER_PROPERTY_VISION_DEGREES_RESTRICTION = modifierfunction.MODIFIER_PROPERTY_VISION_DEGREES_RESTRICTION +MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_STACKING = modifierfunction.MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_STACKING +MODIFIER_PROPERTY_INVENTORY_SLOT_RESTRICTED = modifierfunction.MODIFIER_PROPERTY_INVENTORY_SLOT_RESTRICTED +MODIFIER_EVENT_ON_TIER_TOKEN_REROLLED = modifierfunction.MODIFIER_EVENT_ON_TIER_TOKEN_REROLLED +MODIFIER_PROPERTY_REDIRECT_SPELL = modifierfunction.MODIFIER_PROPERTY_REDIRECT_SPELL +MODIFIER_PROPERTY_BASEATTACK_POSTBONUS = modifierfunction.MODIFIER_PROPERTY_BASEATTACK_POSTBONUS +MODIFIER_EVENT_ON_FOW_TEAM_CHANGED = modifierfunction.MODIFIER_EVENT_ON_FOW_TEAM_CHANGED +MODIFIER_PROPERTY_SUPPRESS_ATTACK_PROCS = modifierfunction.MODIFIER_PROPERTY_SUPPRESS_ATTACK_PROCS +MODIFIER_EVENT_ON_ABILITY_TOGGLED = modifierfunction.MODIFIER_EVENT_ON_ABILITY_TOGGLED +MODIFIER_PROPERTY_AVOID_ATTACK_PROCS = modifierfunction.MODIFIER_PROPERTY_AVOID_ATTACK_PROCS +MODIFIER_EVENT_ON_RUNE_SPAWN = modifierfunction.MODIFIER_EVENT_ON_RUNE_SPAWN +MODIFIER_PROPERTY_PHYSICAL_LIFESTEAL = modifierfunction.MODIFIER_PROPERTY_PHYSICAL_LIFESTEAL +MODIFIER_PROPERTY_MAGICAL_LIFESTEAL = modifierfunction.MODIFIER_PROPERTY_MAGICAL_LIFESTEAL +MODIFIER_EVENT_ON_PURE_DAMAGE_CALCULATED = modifierfunction.MODIFIER_EVENT_ON_PURE_DAMAGE_CALCULATED +MODIFIER_EVENT_NEUTRAL_TRINKET_OPTIONS = modifierfunction.MODIFIER_EVENT_NEUTRAL_TRINKET_OPTIONS +MODIFIER_EVENT_NEUTRAL_ENHANCEMENT_OPTIONS = modifierfunction.MODIFIER_EVENT_NEUTRAL_ENHANCEMENT_OPTIONS +MODIFIER_PROPERTY_MOVESPEED_MAX_BONUS_CONSTANT = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_MAX_BONUS_CONSTANT +MODIFIER_PROPERTY_MOVESPEED_POST_MULTIPLIER_BONUS_CONSTANT = modifierfunction.MODIFIER_PROPERTY_MOVESPEED_POST_MULTIPLIER_BONUS_CONSTANT +MODIFIER_PROPERTY_FORBID_ILLUSIONS = modifierfunction.MODIFIER_PROPERTY_FORBID_ILLUSIONS +MODIFIER_PROPERTY_MANACOST_OVERRIDE = modifierfunction.MODIFIER_PROPERTY_MANACOST_OVERRIDE +MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION = modifierfunction.MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION +MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION_UNIQUE = modifierfunction.MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION_UNIQUE +MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE_UNIQUE = modifierfunction.MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE_UNIQUE +MODIFIER_PROPERTY_SUPPRESS_INCOMING_CRIT = modifierfunction.MODIFIER_PROPERTY_SUPPRESS_INCOMING_CRIT +MODIFIER_PROPERTY_UPGRADE_NEUTRAL_ARTIFACTS = modifierfunction.MODIFIER_PROPERTY_UPGRADE_NEUTRAL_ARTIFACTS +MODIFIER_PROPERTY_CONSUMABLE_USE_SPEED = modifierfunction.MODIFIER_PROPERTY_CONSUMABLE_USE_SPEED +MODIFIER_PROPERTY_FORCE_NETWORK_TRANSMIT = modifierfunction.MODIFIER_PROPERTY_FORCE_NETWORK_TRANSMIT +MODIFIER_FUNCTION_LAST = modifierfunction.MODIFIER_FUNCTION_LAST +MODIFIER_FUNCTION_INVALID = modifierfunction.MODIFIER_FUNCTION_INVALID --- (availability: server & client) ---- @alias modifierpriority ---- | `MODIFIER_PRIORITY_LOW` ---- | `MODIFIER_PRIORITY_NORMAL` ---- | `MODIFIER_PRIORITY_HIGH` ---- | `MODIFIER_PRIORITY_ULTRA` ---- | `MODIFIER_PRIORITY_SUPER_ULTRA` - ---- @type modifierpriority -MODIFIER_PRIORITY_LOW = 0 ---- @type modifierpriority -MODIFIER_PRIORITY_NORMAL = 1 ---- @type modifierpriority -MODIFIER_PRIORITY_HIGH = 2 ---- @type modifierpriority -MODIFIER_PRIORITY_ULTRA = 3 ---- @type modifierpriority -MODIFIER_PRIORITY_SUPER_ULTRA = 4 +--- @enum modifierpriority +--- @field MODIFIER_PRIORITY_LOW 0 +--- @field MODIFIER_PRIORITY_NORMAL 1 +--- @field MODIFIER_PRIORITY_HIGH 2 +--- @field MODIFIER_PRIORITY_ULTRA 3 +--- @field MODIFIER_PRIORITY_SUPER_ULTRA 4 +local modifierpriority = {} +MODIFIER_PRIORITY_LOW = modifierpriority.MODIFIER_PRIORITY_LOW +MODIFIER_PRIORITY_NORMAL = modifierpriority.MODIFIER_PRIORITY_NORMAL +MODIFIER_PRIORITY_HIGH = modifierpriority.MODIFIER_PRIORITY_HIGH +MODIFIER_PRIORITY_ULTRA = modifierpriority.MODIFIER_PRIORITY_ULTRA +MODIFIER_PRIORITY_SUPER_ULTRA = modifierpriority.MODIFIER_PRIORITY_SUPER_ULTRA --- (availability: server & client) ---- @alias modifierremove ---- | `DOTA_BUFF_REMOVE_ALL` ---- | `DOTA_BUFF_REMOVE_ENEMY` ---- | `DOTA_BUFF_REMOVE_ALLY` - ---- @type modifierremove -DOTA_BUFF_REMOVE_ALL = 0 ---- @type modifierremove -DOTA_BUFF_REMOVE_ENEMY = 1 ---- @type modifierremove -DOTA_BUFF_REMOVE_ALLY = 2 +--- @enum modifierremove +--- @field DOTA_BUFF_REMOVE_ALL 0 +--- @field DOTA_BUFF_REMOVE_ENEMY 1 +--- @field DOTA_BUFF_REMOVE_ALLY 2 +local modifierremove = {} +DOTA_BUFF_REMOVE_ALL = modifierremove.DOTA_BUFF_REMOVE_ALL +DOTA_BUFF_REMOVE_ENEMY = modifierremove.DOTA_BUFF_REMOVE_ENEMY +DOTA_BUFF_REMOVE_ALLY = modifierremove.DOTA_BUFF_REMOVE_ALLY --- (availability: server & client) ---- @alias modifierstate ---- | `MODIFIER_STATE_ROOTED` ---- | `MODIFIER_STATE_DISARMED` ---- | `MODIFIER_STATE_ATTACK_IMMUNE` ---- | `MODIFIER_STATE_SILENCED` ---- | `MODIFIER_STATE_MUTED` ---- | `MODIFIER_STATE_STUNNED` ---- | `MODIFIER_STATE_HEXED` ---- | `MODIFIER_STATE_INVISIBLE` ---- | `MODIFIER_STATE_INVULNERABLE` ---- | `MODIFIER_STATE_MAGIC_IMMUNE` ---- | `MODIFIER_STATE_PROVIDES_VISION` ---- | `MODIFIER_STATE_NIGHTMARED` ---- | `MODIFIER_STATE_BLOCK_DISABLED` ---- | `MODIFIER_STATE_EVADE_DISABLED` ---- | `MODIFIER_STATE_UNSELECTABLE` ---- | `MODIFIER_STATE_CANNOT_TARGET_ENEMIES` ---- | `MODIFIER_STATE_CANNOT_TARGET_BUILDINGS` ---- | `MODIFIER_STATE_CANNOT_MISS` ---- | `MODIFIER_STATE_SPECIALLY_DENIABLE` ---- | `MODIFIER_STATE_FROZEN` ---- | `MODIFIER_STATE_COMMAND_RESTRICTED` ---- | `MODIFIER_STATE_NOT_ON_MINIMAP` ---- | `MODIFIER_STATE_LOW_ATTACK_PRIORITY` ---- | `MODIFIER_STATE_NO_HEALTH_BAR` ---- | `MODIFIER_STATE_NO_HEALTH_BAR_FOR_ENEMIES` ---- | `MODIFIER_STATE_NO_HEALTH_BAR_FOR_OTHER_PLAYERS` ---- | `MODIFIER_STATE_FLYING` ---- | `MODIFIER_STATE_NO_UNIT_COLLISION` ---- | `MODIFIER_STATE_NO_TEAM_MOVE_TO` ---- | `MODIFIER_STATE_NO_TEAM_SELECT` ---- | `MODIFIER_STATE_PASSIVES_DISABLED` ---- | `MODIFIER_STATE_DOMINATED` ---- | `MODIFIER_STATE_BLIND` ---- | `MODIFIER_STATE_OUT_OF_GAME` ---- | `MODIFIER_STATE_FAKE_ALLY` ---- | `MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY` ---- | `MODIFIER_STATE_TRUESIGHT_IMMUNE` ---- | `MODIFIER_STATE_UNTARGETABLE` ---- | `MODIFIER_STATE_UNTARGETABLE_ALLIED` ---- | `MODIFIER_STATE_UNTARGETABLE_ENEMY` ---- | `MODIFIER_STATE_UNTARGETABLE_SELF` ---- | `MODIFIER_STATE_IGNORING_MOVE_AND_ATTACK_ORDERS` ---- | `MODIFIER_STATE_ALLOW_PATHING_THROUGH_TREES` ---- | `MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES` ---- | `MODIFIER_STATE_UNSLOWABLE` ---- | `MODIFIER_STATE_TETHERED` ---- | `MODIFIER_STATE_IGNORING_STOP_ORDERS` ---- | `MODIFIER_STATE_FEARED` ---- | `MODIFIER_STATE_TAUNTED` ---- | `MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED` ---- | `MODIFIER_STATE_FORCED_FLYING_VISION` ---- | `MODIFIER_STATE_ATTACK_ALLIES` ---- | `MODIFIER_STATE_ALLOW_PATHING_THROUGH_CLIFFS` ---- | `MODIFIER_STATE_ALLOW_PATHING_THROUGH_FISSURE` ---- | `MODIFIER_STATE_SPECIALLY_UNDENIABLE` ---- | `MODIFIER_STATE_ALLOW_PATHING_THROUGH_OBSTRUCTIONS` ---- | `MODIFIER_STATE_DEBUFF_IMMUNE` ---- | `MODIFIER_STATE_NO_INVISIBILITY_VISUALS` ---- | `MODIFIER_STATE_ALLOW_PATHING_THROUGH_BASE_BLOCKER` ---- | `MODIFIER_STATE_IGNORING_MOVE_ORDERS` ---- | `MODIFIER_STATE_LAST` - ---- @type modifierstate -MODIFIER_STATE_ROOTED = 0 ---- @type modifierstate -MODIFIER_STATE_DISARMED = 1 ---- @type modifierstate -MODIFIER_STATE_ATTACK_IMMUNE = 2 ---- @type modifierstate -MODIFIER_STATE_SILENCED = 3 ---- @type modifierstate -MODIFIER_STATE_MUTED = 4 ---- @type modifierstate -MODIFIER_STATE_STUNNED = 5 ---- @type modifierstate -MODIFIER_STATE_HEXED = 6 ---- @type modifierstate -MODIFIER_STATE_INVISIBLE = 7 ---- @type modifierstate -MODIFIER_STATE_INVULNERABLE = 8 ---- @type modifierstate -MODIFIER_STATE_MAGIC_IMMUNE = 9 ---- @type modifierstate -MODIFIER_STATE_PROVIDES_VISION = 10 ---- @type modifierstate -MODIFIER_STATE_NIGHTMARED = 11 ---- @type modifierstate -MODIFIER_STATE_BLOCK_DISABLED = 12 ---- @type modifierstate -MODIFIER_STATE_EVADE_DISABLED = 13 ---- @type modifierstate -MODIFIER_STATE_UNSELECTABLE = 14 ---- @type modifierstate -MODIFIER_STATE_CANNOT_TARGET_ENEMIES = 15 ---- @type modifierstate -MODIFIER_STATE_CANNOT_TARGET_BUILDINGS = 16 ---- @type modifierstate -MODIFIER_STATE_CANNOT_MISS = 17 ---- @type modifierstate -MODIFIER_STATE_SPECIALLY_DENIABLE = 18 ---- @type modifierstate -MODIFIER_STATE_FROZEN = 19 ---- @type modifierstate -MODIFIER_STATE_COMMAND_RESTRICTED = 20 ---- @type modifierstate -MODIFIER_STATE_NOT_ON_MINIMAP = 21 ---- @type modifierstate -MODIFIER_STATE_LOW_ATTACK_PRIORITY = 22 ---- @type modifierstate -MODIFIER_STATE_NO_HEALTH_BAR = 23 ---- @type modifierstate -MODIFIER_STATE_NO_HEALTH_BAR_FOR_ENEMIES = 24 ---- @type modifierstate -MODIFIER_STATE_NO_HEALTH_BAR_FOR_OTHER_PLAYERS = 25 ---- @type modifierstate -MODIFIER_STATE_FLYING = 26 ---- @type modifierstate -MODIFIER_STATE_NO_UNIT_COLLISION = 27 ---- @type modifierstate -MODIFIER_STATE_NO_TEAM_MOVE_TO = 28 ---- @type modifierstate -MODIFIER_STATE_NO_TEAM_SELECT = 29 ---- @type modifierstate -MODIFIER_STATE_PASSIVES_DISABLED = 30 ---- @type modifierstate -MODIFIER_STATE_DOMINATED = 31 ---- @type modifierstate -MODIFIER_STATE_BLIND = 32 ---- @type modifierstate -MODIFIER_STATE_OUT_OF_GAME = 33 ---- @type modifierstate -MODIFIER_STATE_FAKE_ALLY = 34 ---- @type modifierstate -MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY = 35 ---- @type modifierstate -MODIFIER_STATE_TRUESIGHT_IMMUNE = 36 ---- @type modifierstate -MODIFIER_STATE_UNTARGETABLE = 37 ---- @type modifierstate -MODIFIER_STATE_UNTARGETABLE_ALLIED = 38 ---- @type modifierstate -MODIFIER_STATE_UNTARGETABLE_ENEMY = 39 ---- @type modifierstate -MODIFIER_STATE_UNTARGETABLE_SELF = 40 ---- @type modifierstate -MODIFIER_STATE_IGNORING_MOVE_AND_ATTACK_ORDERS = 41 ---- @type modifierstate -MODIFIER_STATE_ALLOW_PATHING_THROUGH_TREES = 42 ---- @type modifierstate -MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES = 43 ---- @type modifierstate -MODIFIER_STATE_UNSLOWABLE = 44 ---- @type modifierstate -MODIFIER_STATE_TETHERED = 45 ---- @type modifierstate -MODIFIER_STATE_IGNORING_STOP_ORDERS = 46 ---- @type modifierstate -MODIFIER_STATE_FEARED = 47 ---- @type modifierstate -MODIFIER_STATE_TAUNTED = 48 ---- @type modifierstate -MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED = 49 ---- @type modifierstate -MODIFIER_STATE_FORCED_FLYING_VISION = 50 ---- @type modifierstate -MODIFIER_STATE_ATTACK_ALLIES = 51 ---- @type modifierstate -MODIFIER_STATE_ALLOW_PATHING_THROUGH_CLIFFS = 52 ---- @type modifierstate -MODIFIER_STATE_ALLOW_PATHING_THROUGH_FISSURE = 53 ---- @type modifierstate -MODIFIER_STATE_SPECIALLY_UNDENIABLE = 54 ---- @type modifierstate -MODIFIER_STATE_ALLOW_PATHING_THROUGH_OBSTRUCTIONS = 55 ---- @type modifierstate -MODIFIER_STATE_DEBUFF_IMMUNE = 56 ---- @type modifierstate -MODIFIER_STATE_NO_INVISIBILITY_VISUALS = 57 ---- @type modifierstate -MODIFIER_STATE_ALLOW_PATHING_THROUGH_BASE_BLOCKER = 58 ---- @type modifierstate -MODIFIER_STATE_IGNORING_MOVE_ORDERS = 59 ---- @type modifierstate -MODIFIER_STATE_LAST = 60 +--- @enum modifierstate +--- @field MODIFIER_STATE_ROOTED 0 +--- @field MODIFIER_STATE_DISARMED 1 +--- @field MODIFIER_STATE_ATTACK_IMMUNE 2 +--- @field MODIFIER_STATE_SILENCED 3 +--- @field MODIFIER_STATE_MUTED 4 +--- @field MODIFIER_STATE_STUNNED 5 +--- @field MODIFIER_STATE_HEXED 6 +--- @field MODIFIER_STATE_INVISIBLE 7 +--- @field MODIFIER_STATE_INVULNERABLE 8 +--- @field MODIFIER_STATE_MAGIC_IMMUNE 9 +--- @field MODIFIER_STATE_PROVIDES_VISION 10 +--- @field MODIFIER_STATE_NIGHTMARED 11 +--- @field MODIFIER_STATE_BLOCK_DISABLED 12 +--- @field MODIFIER_STATE_EVADE_DISABLED 13 +--- @field MODIFIER_STATE_UNSELECTABLE 14 +--- @field MODIFIER_STATE_CANNOT_TARGET_ENEMIES 15 +--- @field MODIFIER_STATE_CANNOT_TARGET_BUILDINGS 16 +--- @field MODIFIER_STATE_CANNOT_MISS 17 +--- @field MODIFIER_STATE_SPECIALLY_DENIABLE 18 +--- @field MODIFIER_STATE_FROZEN 19 +--- @field MODIFIER_STATE_COMMAND_RESTRICTED 20 +--- @field MODIFIER_STATE_NOT_ON_MINIMAP 21 +--- @field MODIFIER_STATE_LOW_ATTACK_PRIORITY 22 +--- @field MODIFIER_STATE_NO_HEALTH_BAR 23 +--- @field MODIFIER_STATE_NO_HEALTH_BAR_FOR_ENEMIES 24 +--- @field MODIFIER_STATE_NO_HEALTH_BAR_FOR_OTHER_PLAYERS 25 +--- @field MODIFIER_STATE_FLYING 26 +--- @field MODIFIER_STATE_NO_UNIT_COLLISION 27 +--- @field MODIFIER_STATE_NO_TEAM_MOVE_TO 28 +--- @field MODIFIER_STATE_NO_TEAM_SELECT 29 +--- @field MODIFIER_STATE_PASSIVES_DISABLED 30 +--- @field MODIFIER_STATE_DOMINATED 31 +--- @field MODIFIER_STATE_BLIND 32 +--- @field MODIFIER_STATE_OUT_OF_GAME 33 +--- @field MODIFIER_STATE_FAKE_ALLY 34 +--- @field MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY 35 +--- @field MODIFIER_STATE_TRUESIGHT_IMMUNE 36 +--- @field MODIFIER_STATE_UNTARGETABLE 37 +--- @field MODIFIER_STATE_UNTARGETABLE_ALLIED 38 +--- @field MODIFIER_STATE_UNTARGETABLE_ENEMY 39 +--- @field MODIFIER_STATE_UNTARGETABLE_SELF 40 +--- @field MODIFIER_STATE_IGNORING_MOVE_AND_ATTACK_ORDERS 41 +--- @field MODIFIER_STATE_ALLOW_PATHING_THROUGH_TREES 42 +--- @field MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES 43 +--- @field MODIFIER_STATE_UNSLOWABLE 44 +--- @field MODIFIER_STATE_TETHERED 45 +--- @field MODIFIER_STATE_IGNORING_STOP_ORDERS 46 +--- @field MODIFIER_STATE_FEARED 47 +--- @field MODIFIER_STATE_TAUNTED 48 +--- @field MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED 49 +--- @field MODIFIER_STATE_FORCED_FLYING_VISION 50 +--- @field MODIFIER_STATE_ATTACK_ALLIES 51 +--- @field MODIFIER_STATE_ALLOW_PATHING_THROUGH_CLIFFS 52 +--- @field MODIFIER_STATE_ALLOW_PATHING_THROUGH_FISSURE 53 +--- @field MODIFIER_STATE_SPECIALLY_UNDENIABLE 54 +--- @field MODIFIER_STATE_ALLOW_PATHING_THROUGH_OBSTRUCTIONS 55 +--- @field MODIFIER_STATE_DEBUFF_IMMUNE 56 +--- @field MODIFIER_STATE_ALLOW_PATHING_THROUGH_BASE_BLOCKER 57 +--- @field MODIFIER_STATE_IGNORING_MOVE_ORDERS 58 +--- @field MODIFIER_STATE_ATTACKS_ARE_MELEE 59 +--- @field MODIFIER_STATE_CAN_USE_BACKPACK_ITEMS 60 +--- @field MODIFIER_STATE_CASTS_IGNORE_CHANNELING 61 +--- @field MODIFIER_STATE_ATTACKS_DONT_REVEAL 62 +--- @field MODIFIER_STATE_NEUTRALS_DONT_ATTACK 63 +--- @field MODIFIER_STATE_LAST 64 +local modifierstate = {} +MODIFIER_STATE_ROOTED = modifierstate.MODIFIER_STATE_ROOTED +MODIFIER_STATE_DISARMED = modifierstate.MODIFIER_STATE_DISARMED +MODIFIER_STATE_ATTACK_IMMUNE = modifierstate.MODIFIER_STATE_ATTACK_IMMUNE +MODIFIER_STATE_SILENCED = modifierstate.MODIFIER_STATE_SILENCED +MODIFIER_STATE_MUTED = modifierstate.MODIFIER_STATE_MUTED +MODIFIER_STATE_STUNNED = modifierstate.MODIFIER_STATE_STUNNED +MODIFIER_STATE_HEXED = modifierstate.MODIFIER_STATE_HEXED +MODIFIER_STATE_INVISIBLE = modifierstate.MODIFIER_STATE_INVISIBLE +MODIFIER_STATE_INVULNERABLE = modifierstate.MODIFIER_STATE_INVULNERABLE +MODIFIER_STATE_MAGIC_IMMUNE = modifierstate.MODIFIER_STATE_MAGIC_IMMUNE +MODIFIER_STATE_PROVIDES_VISION = modifierstate.MODIFIER_STATE_PROVIDES_VISION +MODIFIER_STATE_NIGHTMARED = modifierstate.MODIFIER_STATE_NIGHTMARED +MODIFIER_STATE_BLOCK_DISABLED = modifierstate.MODIFIER_STATE_BLOCK_DISABLED +MODIFIER_STATE_EVADE_DISABLED = modifierstate.MODIFIER_STATE_EVADE_DISABLED +MODIFIER_STATE_UNSELECTABLE = modifierstate.MODIFIER_STATE_UNSELECTABLE +MODIFIER_STATE_CANNOT_TARGET_ENEMIES = modifierstate.MODIFIER_STATE_CANNOT_TARGET_ENEMIES +MODIFIER_STATE_CANNOT_TARGET_BUILDINGS = modifierstate.MODIFIER_STATE_CANNOT_TARGET_BUILDINGS +MODIFIER_STATE_CANNOT_MISS = modifierstate.MODIFIER_STATE_CANNOT_MISS +MODIFIER_STATE_SPECIALLY_DENIABLE = modifierstate.MODIFIER_STATE_SPECIALLY_DENIABLE +MODIFIER_STATE_FROZEN = modifierstate.MODIFIER_STATE_FROZEN +MODIFIER_STATE_COMMAND_RESTRICTED = modifierstate.MODIFIER_STATE_COMMAND_RESTRICTED +MODIFIER_STATE_NOT_ON_MINIMAP = modifierstate.MODIFIER_STATE_NOT_ON_MINIMAP +MODIFIER_STATE_LOW_ATTACK_PRIORITY = modifierstate.MODIFIER_STATE_LOW_ATTACK_PRIORITY +MODIFIER_STATE_NO_HEALTH_BAR = modifierstate.MODIFIER_STATE_NO_HEALTH_BAR +MODIFIER_STATE_NO_HEALTH_BAR_FOR_ENEMIES = modifierstate.MODIFIER_STATE_NO_HEALTH_BAR_FOR_ENEMIES +MODIFIER_STATE_NO_HEALTH_BAR_FOR_OTHER_PLAYERS = modifierstate.MODIFIER_STATE_NO_HEALTH_BAR_FOR_OTHER_PLAYERS +MODIFIER_STATE_FLYING = modifierstate.MODIFIER_STATE_FLYING +MODIFIER_STATE_NO_UNIT_COLLISION = modifierstate.MODIFIER_STATE_NO_UNIT_COLLISION +MODIFIER_STATE_NO_TEAM_MOVE_TO = modifierstate.MODIFIER_STATE_NO_TEAM_MOVE_TO +MODIFIER_STATE_NO_TEAM_SELECT = modifierstate.MODIFIER_STATE_NO_TEAM_SELECT +MODIFIER_STATE_PASSIVES_DISABLED = modifierstate.MODIFIER_STATE_PASSIVES_DISABLED +MODIFIER_STATE_DOMINATED = modifierstate.MODIFIER_STATE_DOMINATED +MODIFIER_STATE_BLIND = modifierstate.MODIFIER_STATE_BLIND +MODIFIER_STATE_OUT_OF_GAME = modifierstate.MODIFIER_STATE_OUT_OF_GAME +MODIFIER_STATE_FAKE_ALLY = modifierstate.MODIFIER_STATE_FAKE_ALLY +MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY = modifierstate.MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY +MODIFIER_STATE_TRUESIGHT_IMMUNE = modifierstate.MODIFIER_STATE_TRUESIGHT_IMMUNE +MODIFIER_STATE_UNTARGETABLE = modifierstate.MODIFIER_STATE_UNTARGETABLE +MODIFIER_STATE_UNTARGETABLE_ALLIED = modifierstate.MODIFIER_STATE_UNTARGETABLE_ALLIED +MODIFIER_STATE_UNTARGETABLE_ENEMY = modifierstate.MODIFIER_STATE_UNTARGETABLE_ENEMY +MODIFIER_STATE_UNTARGETABLE_SELF = modifierstate.MODIFIER_STATE_UNTARGETABLE_SELF +MODIFIER_STATE_IGNORING_MOVE_AND_ATTACK_ORDERS = modifierstate.MODIFIER_STATE_IGNORING_MOVE_AND_ATTACK_ORDERS +MODIFIER_STATE_ALLOW_PATHING_THROUGH_TREES = modifierstate.MODIFIER_STATE_ALLOW_PATHING_THROUGH_TREES +MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES = modifierstate.MODIFIER_STATE_NOT_ON_MINIMAP_FOR_ENEMIES +MODIFIER_STATE_UNSLOWABLE = modifierstate.MODIFIER_STATE_UNSLOWABLE +MODIFIER_STATE_TETHERED = modifierstate.MODIFIER_STATE_TETHERED +MODIFIER_STATE_IGNORING_STOP_ORDERS = modifierstate.MODIFIER_STATE_IGNORING_STOP_ORDERS +MODIFIER_STATE_FEARED = modifierstate.MODIFIER_STATE_FEARED +MODIFIER_STATE_TAUNTED = modifierstate.MODIFIER_STATE_TAUNTED +MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED = modifierstate.MODIFIER_STATE_CANNOT_BE_MOTION_CONTROLLED +MODIFIER_STATE_FORCED_FLYING_VISION = modifierstate.MODIFIER_STATE_FORCED_FLYING_VISION +MODIFIER_STATE_ATTACK_ALLIES = modifierstate.MODIFIER_STATE_ATTACK_ALLIES +MODIFIER_STATE_ALLOW_PATHING_THROUGH_CLIFFS = modifierstate.MODIFIER_STATE_ALLOW_PATHING_THROUGH_CLIFFS +MODIFIER_STATE_ALLOW_PATHING_THROUGH_FISSURE = modifierstate.MODIFIER_STATE_ALLOW_PATHING_THROUGH_FISSURE +MODIFIER_STATE_SPECIALLY_UNDENIABLE = modifierstate.MODIFIER_STATE_SPECIALLY_UNDENIABLE +MODIFIER_STATE_ALLOW_PATHING_THROUGH_OBSTRUCTIONS = modifierstate.MODIFIER_STATE_ALLOW_PATHING_THROUGH_OBSTRUCTIONS +MODIFIER_STATE_DEBUFF_IMMUNE = modifierstate.MODIFIER_STATE_DEBUFF_IMMUNE +MODIFIER_STATE_ALLOW_PATHING_THROUGH_BASE_BLOCKER = modifierstate.MODIFIER_STATE_ALLOW_PATHING_THROUGH_BASE_BLOCKER +MODIFIER_STATE_IGNORING_MOVE_ORDERS = modifierstate.MODIFIER_STATE_IGNORING_MOVE_ORDERS +MODIFIER_STATE_ATTACKS_ARE_MELEE = modifierstate.MODIFIER_STATE_ATTACKS_ARE_MELEE +MODIFIER_STATE_CAN_USE_BACKPACK_ITEMS = modifierstate.MODIFIER_STATE_CAN_USE_BACKPACK_ITEMS +MODIFIER_STATE_CASTS_IGNORE_CHANNELING = modifierstate.MODIFIER_STATE_CASTS_IGNORE_CHANNELING +MODIFIER_STATE_ATTACKS_DONT_REVEAL = modifierstate.MODIFIER_STATE_ATTACKS_DONT_REVEAL +MODIFIER_STATE_NEUTRALS_DONT_ATTACK = modifierstate.MODIFIER_STATE_NEUTRALS_DONT_ATTACK +MODIFIER_STATE_LAST = modifierstate.MODIFIER_STATE_LAST --- (availability: server & client) ---- @alias ParticleAttachment_t ---- | `PATTACH_INVALID` ---- | `PATTACH_ABSORIGIN` ---- | `PATTACH_ABSORIGIN_FOLLOW` ---- | `PATTACH_CUSTOMORIGIN` ---- | `PATTACH_CUSTOMORIGIN_FOLLOW` ---- | `PATTACH_POINT` ---- | `PATTACH_POINT_FOLLOW` ---- | `PATTACH_EYES_FOLLOW` ---- | `PATTACH_OVERHEAD_FOLLOW` ---- | `PATTACH_WORLDORIGIN` ---- | `PATTACH_ROOTBONE_FOLLOW` ---- | `PATTACH_RENDERORIGIN_FOLLOW` ---- | `PATTACH_MAIN_VIEW` ---- | `PATTACH_WATERWAKE` ---- | `PATTACH_CENTER_FOLLOW` ---- | `PATTACH_CUSTOM_GAME_STATE_1` ---- | `PATTACH_HEALTHBAR` ---- | `MAX_PATTACH_TYPES` - ---- @type ParticleAttachment_t -PATTACH_INVALID = -1 ---- @type ParticleAttachment_t -PATTACH_ABSORIGIN = 0 ---- @type ParticleAttachment_t -PATTACH_ABSORIGIN_FOLLOW = 1 ---- @type ParticleAttachment_t -PATTACH_CUSTOMORIGIN = 2 ---- @type ParticleAttachment_t -PATTACH_CUSTOMORIGIN_FOLLOW = 3 ---- @type ParticleAttachment_t -PATTACH_POINT = 4 ---- @type ParticleAttachment_t -PATTACH_POINT_FOLLOW = 5 ---- @type ParticleAttachment_t -PATTACH_EYES_FOLLOW = 6 ---- @type ParticleAttachment_t -PATTACH_OVERHEAD_FOLLOW = 7 ---- @type ParticleAttachment_t -PATTACH_WORLDORIGIN = 8 ---- @type ParticleAttachment_t -PATTACH_ROOTBONE_FOLLOW = 9 ---- @type ParticleAttachment_t -PATTACH_RENDERORIGIN_FOLLOW = 10 ---- @type ParticleAttachment_t -PATTACH_MAIN_VIEW = 11 ---- @type ParticleAttachment_t -PATTACH_WATERWAKE = 12 ---- @type ParticleAttachment_t -PATTACH_CENTER_FOLLOW = 13 ---- @type ParticleAttachment_t -PATTACH_CUSTOM_GAME_STATE_1 = 14 ---- @type ParticleAttachment_t -PATTACH_HEALTHBAR = 15 ---- @type ParticleAttachment_t -MAX_PATTACH_TYPES = 16 +--- @enum ParticleAttachment_t +--- @field PATTACH_INVALID -1 +--- @field PATTACH_ABSORIGIN 0 +--- @field PATTACH_ABSORIGIN_FOLLOW 1 +--- @field PATTACH_CUSTOMORIGIN 2 +--- @field PATTACH_CUSTOMORIGIN_FOLLOW 3 +--- @field PATTACH_POINT 4 +--- @field PATTACH_POINT_FOLLOW 5 +--- @field PATTACH_EYES_FOLLOW 6 +--- @field PATTACH_OVERHEAD_FOLLOW 7 +--- @field PATTACH_WORLDORIGIN 8 +--- @field PATTACH_ROOTBONE_FOLLOW 9 +--- @field PATTACH_RENDERORIGIN_FOLLOW 10 +--- @field PATTACH_MAIN_VIEW 11 +--- @field PATTACH_WATERWAKE 12 +--- @field PATTACH_CENTER_FOLLOW 13 +--- @field PATTACH_CUSTOM_GAME_STATE_1 14 +--- @field PATTACH_HEALTHBAR 15 +--- @field MAX_PATTACH_TYPES 16 +local ParticleAttachment_t = {} +PATTACH_INVALID = ParticleAttachment_t.PATTACH_INVALID +PATTACH_ABSORIGIN = ParticleAttachment_t.PATTACH_ABSORIGIN +PATTACH_ABSORIGIN_FOLLOW = ParticleAttachment_t.PATTACH_ABSORIGIN_FOLLOW +PATTACH_CUSTOMORIGIN = ParticleAttachment_t.PATTACH_CUSTOMORIGIN +PATTACH_CUSTOMORIGIN_FOLLOW = ParticleAttachment_t.PATTACH_CUSTOMORIGIN_FOLLOW +PATTACH_POINT = ParticleAttachment_t.PATTACH_POINT +PATTACH_POINT_FOLLOW = ParticleAttachment_t.PATTACH_POINT_FOLLOW +PATTACH_EYES_FOLLOW = ParticleAttachment_t.PATTACH_EYES_FOLLOW +PATTACH_OVERHEAD_FOLLOW = ParticleAttachment_t.PATTACH_OVERHEAD_FOLLOW +PATTACH_WORLDORIGIN = ParticleAttachment_t.PATTACH_WORLDORIGIN +PATTACH_ROOTBONE_FOLLOW = ParticleAttachment_t.PATTACH_ROOTBONE_FOLLOW +PATTACH_RENDERORIGIN_FOLLOW = ParticleAttachment_t.PATTACH_RENDERORIGIN_FOLLOW +PATTACH_MAIN_VIEW = ParticleAttachment_t.PATTACH_MAIN_VIEW +PATTACH_WATERWAKE = ParticleAttachment_t.PATTACH_WATERWAKE +PATTACH_CENTER_FOLLOW = ParticleAttachment_t.PATTACH_CENTER_FOLLOW +PATTACH_CUSTOM_GAME_STATE_1 = ParticleAttachment_t.PATTACH_CUSTOM_GAME_STATE_1 +PATTACH_HEALTHBAR = ParticleAttachment_t.PATTACH_HEALTHBAR +MAX_PATTACH_TYPES = ParticleAttachment_t.MAX_PATTACH_TYPES --- (availability: server & client) ---- @alias PseudoRandom ---- | `DOTA_PSEUDO_RANDOM_NONE` ---- | `DOTA_PSEUDO_RANDOM_MAGNUS_SHARD` ---- | `DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_CRIT` ---- | `DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_DAGGER` ---- | `DOTA_PSEUDO_RANDOM_PHANTOMLANCER_JUXTAPOSE` ---- | `DOTA_PSEUDO_RANDOM_TINY_CRAGGY` ---- | `DOTA_PSEUDO_RANDOM_COLD_REBUKE` ---- | `DOTA_PSEUDO_RANDOM_WOLF_CRIT` ---- | `DOTA_PSEUDO_RANDOM_AXE_HELIX` ---- | `DOTA_PSEUDO_RANDOM_AXE_HELIX_ATTACK` ---- | `DOTA_PSEUDO_RANDOM_LEGION_MOMENT` ---- | `DOTA_PSEUDO_RANDOM_SLARDAR_BASH` ---- | `DOTA_PSEUDO_RANDOM_OD_ESSENCE` ---- | `DOTA_PSEUDO_RANDOM_DROW_MARKSMANSHIP` ---- | `DOTA_PSEUDO_RANDOM_OGRE_MAGI_FIREBLAST` ---- | `DOTA_PSEUDO_RANDOM_OGRE_ITEM_MULTICAST` ---- | `DOTA_PSEUDO_RANDOM_SPIRITBREAKER_GREATERBASH` ---- | `DOTA_PSEUDO_RANDOM_LONE_DRUID_ENTANGLE` ---- | `DOTA_PSEUDO_RANDOM_FACELESS_BASH` ---- | `DOTA_PSEUDO_RANDOM_FACELESS_EVADE_SPELL` ---- | `DOTA_PSEUDO_RANDOM_FACELESS_EVADE_ATTACK` ---- | `DOTA_PSEUDO_RANDOM_FACELESS_VOID_BACKTRACK` ---- | `DOTA_PSEUDO_RANDOM_BREWMASTER_CRIT` ---- | `DOTA_PSEUDO_RANDOM_BREWMASTER_CINDER_BREW` ---- | `DOTA_PSEUDO_RANDOM_SNIPER_HEADSHOT` ---- | `DOTA_PSEUDO_RANDOM_ATOS` ---- | `DOTA_PSEUDO_RANDOM_JUGG_CRIT` ---- | `DOTA_PSEUDO_RANDOM_DAZZLE_SCEPTER` ---- | `DOTA_PSEUDO_RANDOM_CHAOS_CRIT` ---- | `DOTA_PSEUDO_RANDOM_LYCAN_CRIT` ---- | `DOTA_PSEUDO_RANDOM_TUSK_CRIT` ---- | `DOTA_PSEUDO_RANDOM_CM_FREEZING_FIELD` ---- | `DOTA_PSEUDO_RANDOM_GENERIC_BASHER` ---- | `DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT` ---- | `DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT_MORTAL` ---- | `DOTA_PSEUDO_RANDOM_ITEM_GREATERCRIT` ---- | `DOTA_PSEUDO_RANDOM_ITEM_LESSERCRIT` ---- | `DOTA_PSEUDO_RANDOM_ITEM_BASHER` ---- | `DOTA_PSEUDO_RANDOM_ITEM_SOLAR_CREST` ---- | `DOTA_PSEUDO_RANDOM_ITEM_JAVELIN_ACCURACY` ---- | `DOTA_PSEUDO_RANDOM_ITEM_TRIDENT` ---- | `DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL` ---- | `DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL_BLOCK` ---- | `DOTA_PSEUDO_RANDOM_ITEM_STOUT` ---- | `DOTA_PSEUDO_RANDOM_ITEM_VANGUARD` ---- | `DOTA_PSEUDO_RANDOM_ITEM_CRIMSON_GUARD` ---- | `DOTA_PSEUDO_RANDOM_ITEM_PMS` ---- | `DOTA_PSEUDO_RANDOM_ITEM_HALBRED_MAIM` ---- | `DOTA_PSEUDO_RANDOM_ITEM_SANGEYASHA_MAIM` ---- | `DOTA_PSEUDO_RANDOM_ITEM_SANGEKAYA_MAIM` ---- | `DOTA_PSEUDO_RANDOM_ITEM_SANGE_MAIM` ---- | `DOTA_PSEUDO_RANDOM_ITEM_BUTTERFLY` ---- | `DOTA_PSEUDO_RANDOM_ITEM_MAELSTROM` ---- | `DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR` ---- | `DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR_STATIC` ---- | `DOTA_PSEUDO_RANDOM_ITEM_MKB` ---- | `DOTA_PSEUDO_RANDOM_ITEM_SILVER_EDGE` ---- | `DOTA_PSEUDO_RANDOM_ITEM_NAGINATA` ---- | `DOTA_PSEUDO_RANDOM_TROLL_BASH` ---- | `DOTA_PSEUDO_RANDOM_RIKI_SMOKE_SCREEN` ---- | `DOTA_PSEUDO_RANDOM_CHAOS_DOUBLE_CRIT` ---- | `DOTA_PSEUDO_RANDOM_CHAOS_TRIPLE_CRIT` ---- | `DOTA_PSEUDO_RANDOM_GENERIC_EVASION` ---- | `DOTA_PSEUDO_RANDOM_GENERIC_HEIGHT_MISS` ---- | `DOTA_PSEUDO_RANDOM_GENERIC_MISS` ---- | `DOTA_PSEUDO_RANDOM_ARMADILLO_HEARTPIERCER` ---- | `DOTA_PSEUDO_RANDOM_MARS_SHIELD` ---- | `DOTA_PSEUDO_RANDOM_ANTIMAGE_SILENT` ---- | `DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER1` ---- | `DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER2` ---- | `DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER3` ---- | `DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER4` ---- | `DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER5` ---- | `DOTA_PSEUDO_RANDOM_MARS_BULWARK` ---- | `DOTA_PSEUDO_RANDOM_MUERTA_GUNSLINGER` ---- | `DOTA_PSEUDO_RANDOM_TROLL_FERVOR_SHARD` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GENERIC` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_1` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_2` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_3` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_4` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_5` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_6` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_7` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_8` ---- | `DOTA_PSEUDO_RANDOM_CUSTOM_GAME_9` - ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_NONE = 0 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_MAGNUS_SHARD = 1 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_CRIT = 2 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_DAGGER = 3 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_PHANTOMLANCER_JUXTAPOSE = 4 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_TINY_CRAGGY = 5 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_COLD_REBUKE = 6 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_WOLF_CRIT = 7 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_AXE_HELIX = 8 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_AXE_HELIX_ATTACK = 9 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_LEGION_MOMENT = 10 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_SLARDAR_BASH = 11 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_OD_ESSENCE = 12 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_DROW_MARKSMANSHIP = 13 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_OGRE_MAGI_FIREBLAST = 14 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_OGRE_ITEM_MULTICAST = 15 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_SPIRITBREAKER_GREATERBASH = 16 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_LONE_DRUID_ENTANGLE = 17 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_FACELESS_BASH = 18 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_FACELESS_EVADE_SPELL = 19 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_FACELESS_EVADE_ATTACK = 20 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_FACELESS_VOID_BACKTRACK = 21 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_BREWMASTER_CRIT = 22 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_BREWMASTER_CINDER_BREW = 23 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_SNIPER_HEADSHOT = 24 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ATOS = 25 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_JUGG_CRIT = 26 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_DAZZLE_SCEPTER = 27 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CHAOS_CRIT = 28 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_LYCAN_CRIT = 29 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_TUSK_CRIT = 30 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CM_FREEZING_FIELD = 31 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_GENERIC_BASHER = 32 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT = 33 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT_MORTAL = 34 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_GREATERCRIT = 35 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_LESSERCRIT = 36 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_BASHER = 37 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_SOLAR_CREST = 38 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_JAVELIN_ACCURACY = 39 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_TRIDENT = 40 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL = 41 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL_BLOCK = 42 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_STOUT = 43 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_VANGUARD = 44 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_CRIMSON_GUARD = 45 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_PMS = 46 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_HALBRED_MAIM = 47 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_SANGEYASHA_MAIM = 48 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_SANGEKAYA_MAIM = 49 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_SANGE_MAIM = 50 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_BUTTERFLY = 51 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_MAELSTROM = 52 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR = 53 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR_STATIC = 54 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_MKB = 55 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_SILVER_EDGE = 56 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ITEM_NAGINATA = 57 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_TROLL_BASH = 58 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_RIKI_SMOKE_SCREEN = 59 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CHAOS_DOUBLE_CRIT = 60 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CHAOS_TRIPLE_CRIT = 61 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_GENERIC_EVASION = 62 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_GENERIC_HEIGHT_MISS = 63 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_GENERIC_MISS = 64 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ARMADILLO_HEARTPIERCER = 65 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_MARS_SHIELD = 66 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_ANTIMAGE_SILENT = 67 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER1 = 68 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER2 = 69 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER3 = 70 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER4 = 71 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER5 = 72 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_MARS_BULWARK = 73 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_MUERTA_GUNSLINGER = 74 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_TROLL_FERVOR_SHARD = 75 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GENERIC = 76 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_1 = 77 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_2 = 78 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_3 = 79 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_4 = 80 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_5 = 81 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_6 = 82 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_7 = 83 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_8 = 84 ---- @type PseudoRandom -DOTA_PSEUDO_RANDOM_CUSTOM_GAME_9 = 85 +--- @enum PseudoRandom +--- @field DOTA_PSEUDO_RANDOM_NONE 0 +--- @field DOTA_PSEUDO_RANDOM_MAGNUS_SHARD 1 +--- @field DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_CRIT 2 +--- @field DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_DAGGER 3 +--- @field DOTA_PSEUDO_RANDOM_PHANTOMLANCER_JUXTAPOSE 4 +--- @field DOTA_PSEUDO_RANDOM_TINY_CRAGGY 5 +--- @field DOTA_PSEUDO_RANDOM_COLD_REBUKE 6 +--- @field DOTA_PSEUDO_RANDOM_WOLF_CRIT 7 +--- @field DOTA_PSEUDO_RANDOM_AXE_HELIX 8 +--- @field DOTA_PSEUDO_RANDOM_AXE_HELIX_ATTACK 9 +--- @field DOTA_PSEUDO_RANDOM_LEGION_MOMENT 10 +--- @field DOTA_PSEUDO_RANDOM_SLARDAR_BASH 11 +--- @field DOTA_PSEUDO_RANDOM_OD_ESSENCE 12 +--- @field DOTA_PSEUDO_RANDOM_DROW_MARKSMANSHIP 13 +--- @field DOTA_PSEUDO_RANDOM_OGRE_MAGI_FIREBLAST 14 +--- @field DOTA_PSEUDO_RANDOM_OGRE_ITEM_MULTICAST 15 +--- @field DOTA_PSEUDO_RANDOM_SPIRITBREAKER_GREATERBASH 16 +--- @field DOTA_PSEUDO_RANDOM_LONE_DRUID_ENTANGLE 17 +--- @field DOTA_PSEUDO_RANDOM_FACELESS_BASH 18 +--- @field DOTA_PSEUDO_RANDOM_FACELESS_EVADE_SPELL 19 +--- @field DOTA_PSEUDO_RANDOM_FACELESS_EVADE_ATTACK 20 +--- @field DOTA_PSEUDO_RANDOM_FACELESS_VOID_BACKTRACK 21 +--- @field DOTA_PSEUDO_RANDOM_BREWMASTER_CRIT 22 +--- @field DOTA_PSEUDO_RANDOM_BREWMASTER_CINDER_BREW 23 +--- @field DOTA_PSEUDO_RANDOM_SNIPER_HEADSHOT 24 +--- @field DOTA_PSEUDO_RANDOM_ATOS 25 +--- @field DOTA_PSEUDO_RANDOM_JUGG_CRIT 26 +--- @field DOTA_PSEUDO_RANDOM_DAZZLE_SCEPTER 27 +--- @field DOTA_PSEUDO_RANDOM_CHAOS_CRIT 28 +--- @field DOTA_PSEUDO_RANDOM_LYCAN_CRIT 29 +--- @field DOTA_PSEUDO_RANDOM_TUSK_CRIT 30 +--- @field DOTA_PSEUDO_RANDOM_CM_FREEZING_FIELD 31 +--- @field DOTA_PSEUDO_RANDOM_GENERIC_BASHER 32 +--- @field DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT 33 +--- @field DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT_MORTAL 34 +--- @field DOTA_PSEUDO_RANDOM_ITEM_GREATERCRIT 35 +--- @field DOTA_PSEUDO_RANDOM_ITEM_LESSERCRIT 36 +--- @field DOTA_PSEUDO_RANDOM_ITEM_BASHER 37 +--- @field DOTA_PSEUDO_RANDOM_ITEM_SOLAR_CREST 38 +--- @field DOTA_PSEUDO_RANDOM_ITEM_JAVELIN_ACCURACY 39 +--- @field DOTA_PSEUDO_RANDOM_ITEM_TRIDENT 40 +--- @field DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL 41 +--- @field DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL_BLOCK 42 +--- @field DOTA_PSEUDO_RANDOM_ITEM_STOUT 43 +--- @field DOTA_PSEUDO_RANDOM_ITEM_VANGUARD 44 +--- @field DOTA_PSEUDO_RANDOM_ITEM_CRIMSON_GUARD 45 +--- @field DOTA_PSEUDO_RANDOM_ITEM_PMS 46 +--- @field DOTA_PSEUDO_RANDOM_ITEM_HALBRED_MAIM 47 +--- @field DOTA_PSEUDO_RANDOM_ITEM_SANGEYASHA_MAIM 48 +--- @field DOTA_PSEUDO_RANDOM_ITEM_SANGEKAYA_MAIM 49 +--- @field DOTA_PSEUDO_RANDOM_ITEM_SANGE_MAIM 50 +--- @field DOTA_PSEUDO_RANDOM_ITEM_BUTTERFLY 51 +--- @field DOTA_PSEUDO_RANDOM_ITEM_MAELSTROM 52 +--- @field DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR 53 +--- @field DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR_STATIC 54 +--- @field DOTA_PSEUDO_RANDOM_ITEM_MKB 55 +--- @field DOTA_PSEUDO_RANDOM_ITEM_SILVER_EDGE 56 +--- @field DOTA_PSEUDO_RANDOM_ITEM_NAGINATA 57 +--- @field DOTA_PSEUDO_RANDOM_TROLL_BASH 58 +--- @field DOTA_PSEUDO_RANDOM_RIKI_SMOKE_SCREEN 59 +--- @field DOTA_PSEUDO_RANDOM_CHAOS_DOUBLE_CRIT 60 +--- @field DOTA_PSEUDO_RANDOM_CHAOS_TRIPLE_CRIT 61 +--- @field DOTA_PSEUDO_RANDOM_GENERIC_EVASION 62 +--- @field DOTA_PSEUDO_RANDOM_GENERIC_HEIGHT_MISS 63 +--- @field DOTA_PSEUDO_RANDOM_GENERIC_MISS 64 +--- @field DOTA_PSEUDO_RANDOM_ARMADILLO_HEARTPIERCER 65 +--- @field DOTA_PSEUDO_RANDOM_MARS_SHIELD 66 +--- @field DOTA_PSEUDO_RANDOM_CHAOS_KNIGHT_INNATE_REFUND 67 +--- @field DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER1 68 +--- @field DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER2 69 +--- @field DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER3 70 +--- @field DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER4 71 +--- @field DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER5 72 +--- @field DOTA_PSEUDO_RANDOM_MARS_BULWARK 73 +--- @field DOTA_PSEUDO_RANDOM_MUERTA_GUNSLINGER 74 +--- @field DOTA_PSEUDO_RANDOM_TROLL_FERVOR_SHARD 75 +--- @field DOTA_PSEUDO_RANDOM_SNAPFIRE_GLANCING 76 +--- @field DOTA_PSEUDO_RANDOM_PANGOLIER_PARRY 77 +--- @field DOTA_PSEUDO_RANDOM_HOODWINK_REDIRECT 78 +--- @field DOTA_PSEUDO_RANDOM_KEZ_SAI 79 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GENERIC 80 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_1 81 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_2 82 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_3 83 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_4 84 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_5 85 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_6 86 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_7 87 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_8 88 +--- @field DOTA_PSEUDO_RANDOM_CUSTOM_GAME_9 89 +local PseudoRandom = {} +DOTA_PSEUDO_RANDOM_NONE = PseudoRandom.DOTA_PSEUDO_RANDOM_NONE +DOTA_PSEUDO_RANDOM_MAGNUS_SHARD = PseudoRandom.DOTA_PSEUDO_RANDOM_MAGNUS_SHARD +DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_CRIT +DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_DAGGER = PseudoRandom.DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_DAGGER +DOTA_PSEUDO_RANDOM_PHANTOMLANCER_JUXTAPOSE = PseudoRandom.DOTA_PSEUDO_RANDOM_PHANTOMLANCER_JUXTAPOSE +DOTA_PSEUDO_RANDOM_TINY_CRAGGY = PseudoRandom.DOTA_PSEUDO_RANDOM_TINY_CRAGGY +DOTA_PSEUDO_RANDOM_COLD_REBUKE = PseudoRandom.DOTA_PSEUDO_RANDOM_COLD_REBUKE +DOTA_PSEUDO_RANDOM_WOLF_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_WOLF_CRIT +DOTA_PSEUDO_RANDOM_AXE_HELIX = PseudoRandom.DOTA_PSEUDO_RANDOM_AXE_HELIX +DOTA_PSEUDO_RANDOM_AXE_HELIX_ATTACK = PseudoRandom.DOTA_PSEUDO_RANDOM_AXE_HELIX_ATTACK +DOTA_PSEUDO_RANDOM_LEGION_MOMENT = PseudoRandom.DOTA_PSEUDO_RANDOM_LEGION_MOMENT +DOTA_PSEUDO_RANDOM_SLARDAR_BASH = PseudoRandom.DOTA_PSEUDO_RANDOM_SLARDAR_BASH +DOTA_PSEUDO_RANDOM_OD_ESSENCE = PseudoRandom.DOTA_PSEUDO_RANDOM_OD_ESSENCE +DOTA_PSEUDO_RANDOM_DROW_MARKSMANSHIP = PseudoRandom.DOTA_PSEUDO_RANDOM_DROW_MARKSMANSHIP +DOTA_PSEUDO_RANDOM_OGRE_MAGI_FIREBLAST = PseudoRandom.DOTA_PSEUDO_RANDOM_OGRE_MAGI_FIREBLAST +DOTA_PSEUDO_RANDOM_OGRE_ITEM_MULTICAST = PseudoRandom.DOTA_PSEUDO_RANDOM_OGRE_ITEM_MULTICAST +DOTA_PSEUDO_RANDOM_SPIRITBREAKER_GREATERBASH = PseudoRandom.DOTA_PSEUDO_RANDOM_SPIRITBREAKER_GREATERBASH +DOTA_PSEUDO_RANDOM_LONE_DRUID_ENTANGLE = PseudoRandom.DOTA_PSEUDO_RANDOM_LONE_DRUID_ENTANGLE +DOTA_PSEUDO_RANDOM_FACELESS_BASH = PseudoRandom.DOTA_PSEUDO_RANDOM_FACELESS_BASH +DOTA_PSEUDO_RANDOM_FACELESS_EVADE_SPELL = PseudoRandom.DOTA_PSEUDO_RANDOM_FACELESS_EVADE_SPELL +DOTA_PSEUDO_RANDOM_FACELESS_EVADE_ATTACK = PseudoRandom.DOTA_PSEUDO_RANDOM_FACELESS_EVADE_ATTACK +DOTA_PSEUDO_RANDOM_FACELESS_VOID_BACKTRACK = PseudoRandom.DOTA_PSEUDO_RANDOM_FACELESS_VOID_BACKTRACK +DOTA_PSEUDO_RANDOM_BREWMASTER_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_BREWMASTER_CRIT +DOTA_PSEUDO_RANDOM_BREWMASTER_CINDER_BREW = PseudoRandom.DOTA_PSEUDO_RANDOM_BREWMASTER_CINDER_BREW +DOTA_PSEUDO_RANDOM_SNIPER_HEADSHOT = PseudoRandom.DOTA_PSEUDO_RANDOM_SNIPER_HEADSHOT +DOTA_PSEUDO_RANDOM_ATOS = PseudoRandom.DOTA_PSEUDO_RANDOM_ATOS +DOTA_PSEUDO_RANDOM_JUGG_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_JUGG_CRIT +DOTA_PSEUDO_RANDOM_DAZZLE_SCEPTER = PseudoRandom.DOTA_PSEUDO_RANDOM_DAZZLE_SCEPTER +DOTA_PSEUDO_RANDOM_CHAOS_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_CHAOS_CRIT +DOTA_PSEUDO_RANDOM_LYCAN_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_LYCAN_CRIT +DOTA_PSEUDO_RANDOM_TUSK_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_TUSK_CRIT +DOTA_PSEUDO_RANDOM_CM_FREEZING_FIELD = PseudoRandom.DOTA_PSEUDO_RANDOM_CM_FREEZING_FIELD +DOTA_PSEUDO_RANDOM_GENERIC_BASHER = PseudoRandom.DOTA_PSEUDO_RANDOM_GENERIC_BASHER +DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT +DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT_MORTAL = PseudoRandom.DOTA_PSEUDO_RANDOM_SKELETONKING_CRIT_MORTAL +DOTA_PSEUDO_RANDOM_ITEM_GREATERCRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_GREATERCRIT +DOTA_PSEUDO_RANDOM_ITEM_LESSERCRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_LESSERCRIT +DOTA_PSEUDO_RANDOM_ITEM_BASHER = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_BASHER +DOTA_PSEUDO_RANDOM_ITEM_SOLAR_CREST = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_SOLAR_CREST +DOTA_PSEUDO_RANDOM_ITEM_JAVELIN_ACCURACY = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_JAVELIN_ACCURACY +DOTA_PSEUDO_RANDOM_ITEM_TRIDENT = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_TRIDENT +DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL +DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL_BLOCK = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL_BLOCK +DOTA_PSEUDO_RANDOM_ITEM_STOUT = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_STOUT +DOTA_PSEUDO_RANDOM_ITEM_VANGUARD = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_VANGUARD +DOTA_PSEUDO_RANDOM_ITEM_CRIMSON_GUARD = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_CRIMSON_GUARD +DOTA_PSEUDO_RANDOM_ITEM_PMS = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_PMS +DOTA_PSEUDO_RANDOM_ITEM_HALBRED_MAIM = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_HALBRED_MAIM +DOTA_PSEUDO_RANDOM_ITEM_SANGEYASHA_MAIM = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_SANGEYASHA_MAIM +DOTA_PSEUDO_RANDOM_ITEM_SANGEKAYA_MAIM = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_SANGEKAYA_MAIM +DOTA_PSEUDO_RANDOM_ITEM_SANGE_MAIM = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_SANGE_MAIM +DOTA_PSEUDO_RANDOM_ITEM_BUTTERFLY = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_BUTTERFLY +DOTA_PSEUDO_RANDOM_ITEM_MAELSTROM = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_MAELSTROM +DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR +DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR_STATIC = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_MJOLLNIR_STATIC +DOTA_PSEUDO_RANDOM_ITEM_MKB = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_MKB +DOTA_PSEUDO_RANDOM_ITEM_SILVER_EDGE = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_SILVER_EDGE +DOTA_PSEUDO_RANDOM_ITEM_NAGINATA = PseudoRandom.DOTA_PSEUDO_RANDOM_ITEM_NAGINATA +DOTA_PSEUDO_RANDOM_TROLL_BASH = PseudoRandom.DOTA_PSEUDO_RANDOM_TROLL_BASH +DOTA_PSEUDO_RANDOM_RIKI_SMOKE_SCREEN = PseudoRandom.DOTA_PSEUDO_RANDOM_RIKI_SMOKE_SCREEN +DOTA_PSEUDO_RANDOM_CHAOS_DOUBLE_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_CHAOS_DOUBLE_CRIT +DOTA_PSEUDO_RANDOM_CHAOS_TRIPLE_CRIT = PseudoRandom.DOTA_PSEUDO_RANDOM_CHAOS_TRIPLE_CRIT +DOTA_PSEUDO_RANDOM_GENERIC_EVASION = PseudoRandom.DOTA_PSEUDO_RANDOM_GENERIC_EVASION +DOTA_PSEUDO_RANDOM_GENERIC_HEIGHT_MISS = PseudoRandom.DOTA_PSEUDO_RANDOM_GENERIC_HEIGHT_MISS +DOTA_PSEUDO_RANDOM_GENERIC_MISS = PseudoRandom.DOTA_PSEUDO_RANDOM_GENERIC_MISS +DOTA_PSEUDO_RANDOM_ARMADILLO_HEARTPIERCER = PseudoRandom.DOTA_PSEUDO_RANDOM_ARMADILLO_HEARTPIERCER +DOTA_PSEUDO_RANDOM_MARS_SHIELD = PseudoRandom.DOTA_PSEUDO_RANDOM_MARS_SHIELD +DOTA_PSEUDO_RANDOM_CHAOS_KNIGHT_INNATE_REFUND = PseudoRandom.DOTA_PSEUDO_RANDOM_CHAOS_KNIGHT_INNATE_REFUND +DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER1 = PseudoRandom.DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER1 +DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER2 = PseudoRandom.DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER2 +DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER3 = PseudoRandom.DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER3 +DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER4 = PseudoRandom.DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER4 +DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER5 = PseudoRandom.DOTA_PSEUDO_RANDOM_NEUTRAL_DROP_TIER5 +DOTA_PSEUDO_RANDOM_MARS_BULWARK = PseudoRandom.DOTA_PSEUDO_RANDOM_MARS_BULWARK +DOTA_PSEUDO_RANDOM_MUERTA_GUNSLINGER = PseudoRandom.DOTA_PSEUDO_RANDOM_MUERTA_GUNSLINGER +DOTA_PSEUDO_RANDOM_TROLL_FERVOR_SHARD = PseudoRandom.DOTA_PSEUDO_RANDOM_TROLL_FERVOR_SHARD +DOTA_PSEUDO_RANDOM_SNAPFIRE_GLANCING = PseudoRandom.DOTA_PSEUDO_RANDOM_SNAPFIRE_GLANCING +DOTA_PSEUDO_RANDOM_PANGOLIER_PARRY = PseudoRandom.DOTA_PSEUDO_RANDOM_PANGOLIER_PARRY +DOTA_PSEUDO_RANDOM_HOODWINK_REDIRECT = PseudoRandom.DOTA_PSEUDO_RANDOM_HOODWINK_REDIRECT +DOTA_PSEUDO_RANDOM_KEZ_SAI = PseudoRandom.DOTA_PSEUDO_RANDOM_KEZ_SAI +DOTA_PSEUDO_RANDOM_CUSTOM_GENERIC = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GENERIC +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_1 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_1 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_2 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_2 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_3 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_3 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_4 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_4 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_5 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_5 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_6 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_6 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_7 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_7 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_8 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_8 +DOTA_PSEUDO_RANDOM_CUSTOM_GAME_9 = PseudoRandom.DOTA_PSEUDO_RANDOM_CUSTOM_GAME_9 --- (availability: server) ---- @alias quest_text_replace_values_t ---- | `QUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE` ---- | `QUEST_TEXT_REPLACE_VALUE_TARGET_VALUE` ---- | `QUEST_TEXT_REPLACE_VALUE_ROUND` ---- | `QUEST_TEXT_REPLACE_VALUE_REWARD` ---- | `QUEST_NUM_TEXT_REPLACE_VALUES` - ---- @type quest_text_replace_values_t -QUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE = 0 ---- @type quest_text_replace_values_t -QUEST_TEXT_REPLACE_VALUE_TARGET_VALUE = 1 ---- @type quest_text_replace_values_t -QUEST_TEXT_REPLACE_VALUE_ROUND = 2 ---- @type quest_text_replace_values_t -QUEST_TEXT_REPLACE_VALUE_REWARD = 3 ---- @type quest_text_replace_values_t -QUEST_NUM_TEXT_REPLACE_VALUES = 4 +--- @enum quest_text_replace_values_t +--- @field QUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE 0 +--- @field QUEST_TEXT_REPLACE_VALUE_TARGET_VALUE 1 +--- @field QUEST_TEXT_REPLACE_VALUE_ROUND 2 +--- @field QUEST_TEXT_REPLACE_VALUE_REWARD 3 +--- @field QUEST_NUM_TEXT_REPLACE_VALUES 4 +local quest_text_replace_values_t = {} +QUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE = quest_text_replace_values_t.QUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE +QUEST_TEXT_REPLACE_VALUE_TARGET_VALUE = quest_text_replace_values_t.QUEST_TEXT_REPLACE_VALUE_TARGET_VALUE +QUEST_TEXT_REPLACE_VALUE_ROUND = quest_text_replace_values_t.QUEST_TEXT_REPLACE_VALUE_ROUND +QUEST_TEXT_REPLACE_VALUE_REWARD = quest_text_replace_values_t.QUEST_TEXT_REPLACE_VALUE_REWARD +QUEST_NUM_TEXT_REPLACE_VALUES = quest_text_replace_values_t.QUEST_NUM_TEXT_REPLACE_VALUES --- (availability: server) ---- @alias ShowGenericPopupType ---- | `DOTA_SHOWGENERICPOPUP_TINT_SCREEN` ---- | `DOTA_SHOWGENERICPOPUP_SHOW_NO_OTHER_DIALOGS` - ---- @type ShowGenericPopupType -DOTA_SHOWGENERICPOPUP_TINT_SCREEN = 1 ---- @type ShowGenericPopupType -DOTA_SHOWGENERICPOPUP_SHOW_NO_OTHER_DIALOGS = 2 +--- @enum ShowGenericPopupType +--- @field DOTA_SHOWGENERICPOPUP_TINT_SCREEN 1 +--- @field DOTA_SHOWGENERICPOPUP_SHOW_NO_OTHER_DIALOGS 2 +local ShowGenericPopupType = {} +DOTA_SHOWGENERICPOPUP_TINT_SCREEN = ShowGenericPopupType.DOTA_SHOWGENERICPOPUP_TINT_SCREEN +DOTA_SHOWGENERICPOPUP_SHOW_NO_OTHER_DIALOGS = ShowGenericPopupType.DOTA_SHOWGENERICPOPUP_SHOW_NO_OTHER_DIALOGS --- https://developer.valvesoftware.com/wiki/Animation_Events#Server_events --- --- (availability: server & client) ---- @alias SourceEngineAnimationEvent ---- | `AE_EMPTY` ---- | `AE_CL_PLAYSOUND` ---- | `AE_CL_PLAYSOUND_ATTACHMENT` ---- | `AE_CL_PLAYSOUND_POSITION` ---- | `AE_SV_PLAYSOUND` ---- | `AE_CL_STOPSOUND` ---- | `AE_CL_PLAYSOUND_LOOPING` ---- | `AE_CL_CREATE_PARTICLE_EFFECT` ---- | `AE_CL_STOP_PARTICLE_EFFECT` ---- | `AE_CL_CREATE_PARTICLE_EFFECT_CFG` ---- | `AE_SV_CREATE_PARTICLE_EFFECT_CFG` ---- | `AE_SV_STOP_PARTICLE_EFFECT` ---- | `AE_FOOTSTEP` ---- | `AE_RAGDOLL` ---- | `AE_CL_STOP_RAGDOLL_CONTROL` ---- | `AE_CL_ENABLE_BODYGROUP` ---- | `AE_CL_DISABLE_BODYGROUP` ---- | `AE_CL_BODYGROUP_SET_VALUE` ---- | `AE_SV_BODYGROUP_SET_VALUE` ---- | `AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN` ---- | `AE_WPN_PRIMARYATTACK` ---- | `AE_WPN_SECONDARYATTACK` ---- | `AE_FIRE_INPUT` ---- | `AE_CL_CLOTH_ATTR` ---- | `AE_CL_CLOTH_GROUND_OFFSET` ---- | `AE_CL_CLOTH_STIFFEN` ---- | `AE_CL_CLOTH_EFFECT` ---- | `AE_CL_CREATE_ANIM_SCOPE_PROP` ---- | `AE_CL_SUPPRESS_EVENTS_WITH_TAG` ---- | `AE_CL_HIDE_PARTICLE_EFFECT` ---- | `AE_CL_SHOW_PARTICLE_EFFECT` ---- | `AE_CL_ADD_PARTICLE_EFFECT_CP` ---- | `AE_CL_SPEECH` ---- | `AE_CL_PANORAMA_EVENT` ---- | `AE_CL_DOTA_PLAY_STATUS_EFFECT` ---- | `AE_CL_DOTA_STOP_STATUS_EFFECT` ---- | `AE_CL_DOTA_NPC_CREATE_PARTICLE_EFFECT` ---- | `AE_CL_DOTA_RUBICK_ARCANA_CREATE_PARTICLE_EFFECT` ---- | `AE_DOTA_PET_ITEM_PICKUP` ---- | `AE_DOTA_PET_ITEM_DROP` ---- | `AE_DOTA_SUPPRESS_CONSTANT_LAYER` ---- | `AE_DOTA_PLAY_SOUND_ATTACK_SPECIAL` ---- | `AE_DOTA_CREATE_CLINKZ_ATTACK` ---- | `AE_DOTA_PLAY_SOUND_ATTACK_BACKSTAB` ---- | `AE_DOTA_DIE_PHANTOM_DEATH_PARTICLES` ---- | `AE_DOTA_SWITCH_ATTACK_COMBO` ---- | `AE_EF_NODRAW` ---- | `AE_EF_DRAW` ---- | `AE_DOTA_PLAY_SOUND_ATTACK` - ---- @type SourceEngineAnimationEvent -AE_EMPTY = 0 ---- @type SourceEngineAnimationEvent -AE_CL_PLAYSOUND = 1 ---- @type SourceEngineAnimationEvent -AE_CL_PLAYSOUND_ATTACHMENT = 2 ---- @type SourceEngineAnimationEvent -AE_CL_PLAYSOUND_POSITION = 3 ---- @type SourceEngineAnimationEvent -AE_SV_PLAYSOUND = 4 ---- @type SourceEngineAnimationEvent -AE_CL_STOPSOUND = 5 ---- @type SourceEngineAnimationEvent -AE_CL_PLAYSOUND_LOOPING = 6 ---- @type SourceEngineAnimationEvent -AE_CL_CREATE_PARTICLE_EFFECT = 7 ---- @type SourceEngineAnimationEvent -AE_CL_STOP_PARTICLE_EFFECT = 8 ---- @type SourceEngineAnimationEvent -AE_CL_CREATE_PARTICLE_EFFECT_CFG = 9 ---- @type SourceEngineAnimationEvent -AE_SV_CREATE_PARTICLE_EFFECT_CFG = 10 ---- @type SourceEngineAnimationEvent -AE_SV_STOP_PARTICLE_EFFECT = 11 ---- @type SourceEngineAnimationEvent -AE_FOOTSTEP = 12 ---- @type SourceEngineAnimationEvent -AE_RAGDOLL = 13 ---- @type SourceEngineAnimationEvent -AE_CL_STOP_RAGDOLL_CONTROL = 14 ---- @type SourceEngineAnimationEvent -AE_CL_ENABLE_BODYGROUP = 15 ---- @type SourceEngineAnimationEvent -AE_CL_DISABLE_BODYGROUP = 16 ---- @type SourceEngineAnimationEvent -AE_CL_BODYGROUP_SET_VALUE = 17 ---- @type SourceEngineAnimationEvent -AE_SV_BODYGROUP_SET_VALUE = 18 ---- @type SourceEngineAnimationEvent -AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN = 19 ---- @type SourceEngineAnimationEvent -AE_WPN_PRIMARYATTACK = 20 ---- @type SourceEngineAnimationEvent -AE_WPN_SECONDARYATTACK = 21 ---- @type SourceEngineAnimationEvent -AE_FIRE_INPUT = 22 ---- @type SourceEngineAnimationEvent -AE_CL_CLOTH_ATTR = 23 ---- @type SourceEngineAnimationEvent -AE_CL_CLOTH_GROUND_OFFSET = 24 ---- @type SourceEngineAnimationEvent -AE_CL_CLOTH_STIFFEN = 25 ---- @type SourceEngineAnimationEvent -AE_CL_CLOTH_EFFECT = 26 ---- @type SourceEngineAnimationEvent -AE_CL_CREATE_ANIM_SCOPE_PROP = 27 ---- @type SourceEngineAnimationEvent -AE_CL_SUPPRESS_EVENTS_WITH_TAG = 28 ---- @type SourceEngineAnimationEvent -AE_CL_HIDE_PARTICLE_EFFECT = 29 ---- @type SourceEngineAnimationEvent -AE_CL_SHOW_PARTICLE_EFFECT = 30 ---- @type SourceEngineAnimationEvent -AE_CL_ADD_PARTICLE_EFFECT_CP = 31 ---- @type SourceEngineAnimationEvent -AE_CL_SPEECH = 32 ---- @type SourceEngineAnimationEvent -AE_CL_PANORAMA_EVENT = 33 ---- @type SourceEngineAnimationEvent -AE_CL_DOTA_PLAY_STATUS_EFFECT = 34 ---- @type SourceEngineAnimationEvent -AE_CL_DOTA_STOP_STATUS_EFFECT = 35 ---- @type SourceEngineAnimationEvent -AE_CL_DOTA_NPC_CREATE_PARTICLE_EFFECT = 36 ---- @type SourceEngineAnimationEvent -AE_CL_DOTA_RUBICK_ARCANA_CREATE_PARTICLE_EFFECT = 37 ---- @type SourceEngineAnimationEvent -AE_DOTA_PET_ITEM_PICKUP = 38 ---- @type SourceEngineAnimationEvent -AE_DOTA_PET_ITEM_DROP = 39 ---- @type SourceEngineAnimationEvent -AE_DOTA_SUPPRESS_CONSTANT_LAYER = 40 ---- @type SourceEngineAnimationEvent -AE_DOTA_PLAY_SOUND_ATTACK_SPECIAL = 41 ---- @type SourceEngineAnimationEvent -AE_DOTA_CREATE_CLINKZ_ATTACK = 42 ---- @type SourceEngineAnimationEvent -AE_DOTA_PLAY_SOUND_ATTACK_BACKSTAB = 43 ---- @type SourceEngineAnimationEvent -AE_DOTA_DIE_PHANTOM_DEATH_PARTICLES = 44 ---- @type SourceEngineAnimationEvent -AE_DOTA_SWITCH_ATTACK_COMBO = 45 ---- @type SourceEngineAnimationEvent -AE_EF_NODRAW = 47 ---- @type SourceEngineAnimationEvent -AE_EF_DRAW = 48 ---- @type SourceEngineAnimationEvent -AE_DOTA_PLAY_SOUND_ATTACK = 49 +--- @enum SourceEngineAnimationEvent +--- @field AE_EMPTY 0 +--- @field AE_CL_PLAYSOUND 1 +--- @field AE_CL_PLAYSOUND_ATTACHMENT 2 +--- @field AE_CL_PLAYSOUND_POSITION 3 +--- @field AE_SV_PLAYSOUND 4 +--- @field AE_CL_STOPSOUND 5 +--- @field AE_CL_PLAYSOUND_LOOPING 6 +--- @field AE_CL_CREATE_PARTICLE_EFFECT 7 +--- @field AE_CL_STOP_PARTICLE_EFFECT 8 +--- @field AE_CL_CREATE_PARTICLE_EFFECT_CFG 9 +--- @field AE_SV_CREATE_PARTICLE_EFFECT_CFG 10 +--- @field AE_SV_STOP_PARTICLE_EFFECT 11 +--- @field AE_FOOTSTEP 12 +--- @field AE_CL_STOP_RAGDOLL_CONTROL 13 +--- @field AE_CL_ENABLE_BODYGROUP 14 +--- @field AE_CL_DISABLE_BODYGROUP 15 +--- @field AE_BODYGROUP_SET_VALUE 16 +--- @field AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN 17 +--- @field AE_WEAPON_PERFORM_ATTACK 18 +--- @field AE_FIRE_INPUT 19 +--- @field AE_CL_CLOTH_ATTR 20 +--- @field AE_CL_CLOTH_GROUND_OFFSET 21 +--- @field AE_CL_CLOTH_STIFFEN 22 +--- @field AE_CL_CLOTH_EFFECT 23 +--- @field AE_CL_CREATE_ANIM_SCOPE_PROP 24 +--- @field AE_SV_IKLOCK 25 +--- @field AE_PULSE_GRAPH 26 +--- @field AE_PULSE_GRAPH_LOOKAT 27 +--- @field AE_PULSE_GRAPH_AIMAT 28 +--- @field AE_PULSE_GRAPH_IKLOCKLEFTARM 29 +--- @field AE_PULSE_GRAPH_IKLOCKRIGHTARM 30 +--- @field AE_DISABLE_PLATFORM 31 +--- @field AE_ENABLE_PLATFORM_PLAYER_FOLLOWS_YAW 32 +--- @field AE_ENABLE_PLATFORM_PLAYER_IGNORES_YAW 33 +--- @field AE_DESTRUCTIBLE_PART_DESTROY 34 +--- @field AE_CL_SUPPRESS_EVENTS_WITH_TAG 35 +--- @field AE_CL_HIDE_PARTICLE_EFFECT 36 +--- @field AE_CL_SHOW_PARTICLE_EFFECT 37 +--- @field AE_CL_ADD_PARTICLE_EFFECT_CP 38 +--- @field AE_CL_SPEECH 39 +--- @field AE_CL_PANORAMA_EVENT 40 +--- @field AE_CL_DOTA_PLAY_STATUS_EFFECT 41 +--- @field AE_CL_DOTA_STOP_STATUS_EFFECT 42 +--- @field AE_CL_DOTA_NPC_CREATE_PARTICLE_EFFECT 43 +--- @field AE_CL_DOTA_RUBICK_ARCANA_CREATE_PARTICLE_EFFECT 44 +--- @field AE_DOTA_PET_ITEM_PICKUP 45 +--- @field AE_DOTA_PET_ITEM_DROP 46 +--- @field AE_DOTA_SUPPRESS_CONSTANT_LAYER 47 +--- @field AE_DOTA_PLAY_SOUND_ATTACK_SPECIAL 48 +--- @field AE_DOTA_CREATE_CLINKZ_ATTACK 49 +--- @field AE_DOTA_PLAY_SOUND_ATTACK_BACKSTAB 50 +--- @field AE_DOTA_DIE_PHANTOM_DEATH_PARTICLES 51 +--- @field AE_DOTA_SWITCH_ATTACK_COMBO 52 +--- @field AE_EF_NODRAW 53 +--- @field AE_EF_DRAW 54 +--- @field AE_DOTA_PLAY_SOUND_ATTACK 55 +local SourceEngineAnimationEvent = {} +AE_EMPTY = SourceEngineAnimationEvent.AE_EMPTY +AE_CL_PLAYSOUND = SourceEngineAnimationEvent.AE_CL_PLAYSOUND +AE_CL_PLAYSOUND_ATTACHMENT = SourceEngineAnimationEvent.AE_CL_PLAYSOUND_ATTACHMENT +AE_CL_PLAYSOUND_POSITION = SourceEngineAnimationEvent.AE_CL_PLAYSOUND_POSITION +AE_SV_PLAYSOUND = SourceEngineAnimationEvent.AE_SV_PLAYSOUND +AE_CL_STOPSOUND = SourceEngineAnimationEvent.AE_CL_STOPSOUND +AE_CL_PLAYSOUND_LOOPING = SourceEngineAnimationEvent.AE_CL_PLAYSOUND_LOOPING +AE_CL_CREATE_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_CL_CREATE_PARTICLE_EFFECT +AE_CL_STOP_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_CL_STOP_PARTICLE_EFFECT +AE_CL_CREATE_PARTICLE_EFFECT_CFG = SourceEngineAnimationEvent.AE_CL_CREATE_PARTICLE_EFFECT_CFG +AE_SV_CREATE_PARTICLE_EFFECT_CFG = SourceEngineAnimationEvent.AE_SV_CREATE_PARTICLE_EFFECT_CFG +AE_SV_STOP_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_SV_STOP_PARTICLE_EFFECT +AE_FOOTSTEP = SourceEngineAnimationEvent.AE_FOOTSTEP +AE_CL_STOP_RAGDOLL_CONTROL = SourceEngineAnimationEvent.AE_CL_STOP_RAGDOLL_CONTROL +AE_CL_ENABLE_BODYGROUP = SourceEngineAnimationEvent.AE_CL_ENABLE_BODYGROUP +AE_CL_DISABLE_BODYGROUP = SourceEngineAnimationEvent.AE_CL_DISABLE_BODYGROUP +AE_BODYGROUP_SET_VALUE = SourceEngineAnimationEvent.AE_BODYGROUP_SET_VALUE +AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN = SourceEngineAnimationEvent.AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN +AE_WEAPON_PERFORM_ATTACK = SourceEngineAnimationEvent.AE_WEAPON_PERFORM_ATTACK +AE_FIRE_INPUT = SourceEngineAnimationEvent.AE_FIRE_INPUT +AE_CL_CLOTH_ATTR = SourceEngineAnimationEvent.AE_CL_CLOTH_ATTR +AE_CL_CLOTH_GROUND_OFFSET = SourceEngineAnimationEvent.AE_CL_CLOTH_GROUND_OFFSET +AE_CL_CLOTH_STIFFEN = SourceEngineAnimationEvent.AE_CL_CLOTH_STIFFEN +AE_CL_CLOTH_EFFECT = SourceEngineAnimationEvent.AE_CL_CLOTH_EFFECT +AE_CL_CREATE_ANIM_SCOPE_PROP = SourceEngineAnimationEvent.AE_CL_CREATE_ANIM_SCOPE_PROP +AE_SV_IKLOCK = SourceEngineAnimationEvent.AE_SV_IKLOCK +AE_PULSE_GRAPH = SourceEngineAnimationEvent.AE_PULSE_GRAPH +AE_PULSE_GRAPH_LOOKAT = SourceEngineAnimationEvent.AE_PULSE_GRAPH_LOOKAT +AE_PULSE_GRAPH_AIMAT = SourceEngineAnimationEvent.AE_PULSE_GRAPH_AIMAT +AE_PULSE_GRAPH_IKLOCKLEFTARM = SourceEngineAnimationEvent.AE_PULSE_GRAPH_IKLOCKLEFTARM +AE_PULSE_GRAPH_IKLOCKRIGHTARM = SourceEngineAnimationEvent.AE_PULSE_GRAPH_IKLOCKRIGHTARM +AE_DISABLE_PLATFORM = SourceEngineAnimationEvent.AE_DISABLE_PLATFORM +AE_ENABLE_PLATFORM_PLAYER_FOLLOWS_YAW = SourceEngineAnimationEvent.AE_ENABLE_PLATFORM_PLAYER_FOLLOWS_YAW +AE_ENABLE_PLATFORM_PLAYER_IGNORES_YAW = SourceEngineAnimationEvent.AE_ENABLE_PLATFORM_PLAYER_IGNORES_YAW +AE_DESTRUCTIBLE_PART_DESTROY = SourceEngineAnimationEvent.AE_DESTRUCTIBLE_PART_DESTROY +AE_CL_SUPPRESS_EVENTS_WITH_TAG = SourceEngineAnimationEvent.AE_CL_SUPPRESS_EVENTS_WITH_TAG +AE_CL_HIDE_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_CL_HIDE_PARTICLE_EFFECT +AE_CL_SHOW_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_CL_SHOW_PARTICLE_EFFECT +AE_CL_ADD_PARTICLE_EFFECT_CP = SourceEngineAnimationEvent.AE_CL_ADD_PARTICLE_EFFECT_CP +AE_CL_SPEECH = SourceEngineAnimationEvent.AE_CL_SPEECH +AE_CL_PANORAMA_EVENT = SourceEngineAnimationEvent.AE_CL_PANORAMA_EVENT +AE_CL_DOTA_PLAY_STATUS_EFFECT = SourceEngineAnimationEvent.AE_CL_DOTA_PLAY_STATUS_EFFECT +AE_CL_DOTA_STOP_STATUS_EFFECT = SourceEngineAnimationEvent.AE_CL_DOTA_STOP_STATUS_EFFECT +AE_CL_DOTA_NPC_CREATE_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_CL_DOTA_NPC_CREATE_PARTICLE_EFFECT +AE_CL_DOTA_RUBICK_ARCANA_CREATE_PARTICLE_EFFECT = SourceEngineAnimationEvent.AE_CL_DOTA_RUBICK_ARCANA_CREATE_PARTICLE_EFFECT +AE_DOTA_PET_ITEM_PICKUP = SourceEngineAnimationEvent.AE_DOTA_PET_ITEM_PICKUP +AE_DOTA_PET_ITEM_DROP = SourceEngineAnimationEvent.AE_DOTA_PET_ITEM_DROP +AE_DOTA_SUPPRESS_CONSTANT_LAYER = SourceEngineAnimationEvent.AE_DOTA_SUPPRESS_CONSTANT_LAYER +AE_DOTA_PLAY_SOUND_ATTACK_SPECIAL = SourceEngineAnimationEvent.AE_DOTA_PLAY_SOUND_ATTACK_SPECIAL +AE_DOTA_CREATE_CLINKZ_ATTACK = SourceEngineAnimationEvent.AE_DOTA_CREATE_CLINKZ_ATTACK +AE_DOTA_PLAY_SOUND_ATTACK_BACKSTAB = SourceEngineAnimationEvent.AE_DOTA_PLAY_SOUND_ATTACK_BACKSTAB +AE_DOTA_DIE_PHANTOM_DEATH_PARTICLES = SourceEngineAnimationEvent.AE_DOTA_DIE_PHANTOM_DEATH_PARTICLES +AE_DOTA_SWITCH_ATTACK_COMBO = SourceEngineAnimationEvent.AE_DOTA_SWITCH_ATTACK_COMBO +AE_EF_NODRAW = SourceEngineAnimationEvent.AE_EF_NODRAW +AE_EF_DRAW = SourceEngineAnimationEvent.AE_EF_DRAW +AE_DOTA_PLAY_SOUND_ATTACK = SourceEngineAnimationEvent.AE_DOTA_PLAY_SOUND_ATTACK --- https://developer.valvesoftware.com/wiki/Damage_types --- --- (availability: server & client) ---- @alias SourceEngineDamageTypes ---- | `DMG_GENERIC` # Generic damage. ---- | `DMG_CRUSH` # Caused by physics interaction. Ignored by airboat drivers. ---- | `DMG_BULLET` # Bullet damage. ---- | `DMG_SLASH` # Sharp objects, such as Manhacks or other NPCs attacks. ---- | `DMG_BURN` # Damage from fire. ---- | `DMG_VEHICLE` # Hit by a vehicle. This will need to be set for passengers of some vehicle to receive damage. ---- | `DMG_FALL` # Fall damage. ---- | `DMG_BLAST` # Explosion damage. Will be ignored by most vehicle passengers. ---- | `DMG_CLUB` # Crowbar damage. ---- | `DMG_SHOCK` # Electrical damage, shows smoke at the damage position. ---- | `DMG_SONIC` # Sonic damage,used by the Gargantua and Houndeye NPCs. ---- | `DMG_ENERGYBEAM` # Laser. ---- | `DMG_PREVENT_PHYSICS_FORCE` # Prevent a physics force. ---- | `DMG_NEVERGIB` # Never creates gibs. Used by the crossbow. ---- | `DMG_ALWAYSGIB` # Always create gibs. ---- | `DMG_DROWN` # Drown damage. ---- | `DMG_PARALYZE` # Same as DMG_POISON. ---- | `DMG_NERVEGAS` # Neurotoxin damage. ---- | `DMG_POISON` # Poison damage. ---- | `DMG_RADIATION` # Radiation. Will be ignored by most vehicle passengers. ---- | `DMG_DROWNRECOVER` # Damage applied to the player to restore health after drowning. ---- | `DMG_ACID` # Toxic chemicals or acid burns. ---- | `DMG_SLOWBURN` # In an oven. ---- | `DMG_REMOVENORAGDOLL` # Don't create a ragdoll on death. ---- | `DMG_PHYSGUN` # Damage done by the gravity gun. ---- | `DMG_PLASMA` # Plasma. - ---- @type SourceEngineDamageTypes -DMG_GENERIC = 0 ---- @type SourceEngineDamageTypes -DMG_CRUSH = 1 ---- @type SourceEngineDamageTypes -DMG_BULLET = 2 ---- @type SourceEngineDamageTypes -DMG_SLASH = 4 ---- @type SourceEngineDamageTypes -DMG_BURN = 8 ---- @type SourceEngineDamageTypes -DMG_VEHICLE = 16 ---- @type SourceEngineDamageTypes -DMG_FALL = 32 ---- @type SourceEngineDamageTypes -DMG_BLAST = 64 ---- @type SourceEngineDamageTypes -DMG_CLUB = 128 ---- @type SourceEngineDamageTypes -DMG_SHOCK = 256 ---- @type SourceEngineDamageTypes -DMG_SONIC = 512 ---- @type SourceEngineDamageTypes -DMG_ENERGYBEAM = 1024 ---- @type SourceEngineDamageTypes -DMG_PREVENT_PHYSICS_FORCE = 2048 ---- @type SourceEngineDamageTypes -DMG_NEVERGIB = 4096 ---- @type SourceEngineDamageTypes -DMG_ALWAYSGIB = 8192 ---- @type SourceEngineDamageTypes -DMG_DROWN = 16384 ---- @type SourceEngineDamageTypes -DMG_PARALYZE = 32768 ---- @type SourceEngineDamageTypes -DMG_NERVEGAS = 65536 ---- @type SourceEngineDamageTypes -DMG_POISON = 131072 ---- @type SourceEngineDamageTypes -DMG_RADIATION = 262144 ---- @type SourceEngineDamageTypes -DMG_DROWNRECOVER = 524288 ---- @type SourceEngineDamageTypes -DMG_ACID = 1048576 ---- @type SourceEngineDamageTypes -DMG_SLOWBURN = 2097152 ---- @type SourceEngineDamageTypes -DMG_REMOVENORAGDOLL = 4194304 ---- @type SourceEngineDamageTypes -DMG_PHYSGUN = 8388608 ---- @type SourceEngineDamageTypes -DMG_PLASMA = 16777216 +--- @enum SourceEngineDamageTypes +--- @field DMG_GENERIC 0 Generic damage. +--- @field DMG_CRUSH 1 Caused by physics interaction. Ignored by airboat drivers. +--- @field DMG_BULLET 2 Bullet damage. +--- @field DMG_SLASH 4 Sharp objects, such as Manhacks or other NPCs attacks. +--- @field DMG_BURN 8 Damage from fire. +--- @field DMG_VEHICLE 16 Hit by a vehicle. This will need to be set for passengers of some vehicle to receive damage. +--- @field DMG_FALL 32 Fall damage. +--- @field DMG_BLAST 64 Explosion damage. Will be ignored by most vehicle passengers. +--- @field DMG_CLUB 128 Crowbar damage. +--- @field DMG_SHOCK 256 Electrical damage, shows smoke at the damage position. +--- @field DMG_SONIC 512 Sonic damage,used by the Gargantua and Houndeye NPCs. +--- @field DMG_ENERGYBEAM 1024 Laser. +--- @field DMG_PREVENT_PHYSICS_FORCE 2048 Prevent a physics force. +--- @field DMG_NEVERGIB 4096 Never creates gibs. Used by the crossbow. +--- @field DMG_ALWAYSGIB 8192 Always create gibs. +--- @field DMG_DROWN 16384 Drown damage. +--- @field DMG_PARALYZE 32768 Same as DMG_POISON. +--- @field DMG_NERVEGAS 65536 Neurotoxin damage. +--- @field DMG_POISON 131072 Poison damage. +--- @field DMG_RADIATION 262144 Radiation. Will be ignored by most vehicle passengers. +--- @field DMG_DROWNRECOVER 524288 Damage applied to the player to restore health after drowning. +--- @field DMG_ACID 1048576 Toxic chemicals or acid burns. +--- @field DMG_SLOWBURN 2097152 In an oven. +--- @field DMG_REMOVENORAGDOLL 4194304 Don't create a ragdoll on death. +local SourceEngineDamageTypes = {} +DMG_GENERIC = SourceEngineDamageTypes.DMG_GENERIC +DMG_CRUSH = SourceEngineDamageTypes.DMG_CRUSH +DMG_BULLET = SourceEngineDamageTypes.DMG_BULLET +DMG_SLASH = SourceEngineDamageTypes.DMG_SLASH +DMG_BURN = SourceEngineDamageTypes.DMG_BURN +DMG_VEHICLE = SourceEngineDamageTypes.DMG_VEHICLE +DMG_FALL = SourceEngineDamageTypes.DMG_FALL +DMG_BLAST = SourceEngineDamageTypes.DMG_BLAST +DMG_CLUB = SourceEngineDamageTypes.DMG_CLUB +DMG_SHOCK = SourceEngineDamageTypes.DMG_SHOCK +DMG_SONIC = SourceEngineDamageTypes.DMG_SONIC +DMG_ENERGYBEAM = SourceEngineDamageTypes.DMG_ENERGYBEAM +DMG_PREVENT_PHYSICS_FORCE = SourceEngineDamageTypes.DMG_PREVENT_PHYSICS_FORCE +DMG_NEVERGIB = SourceEngineDamageTypes.DMG_NEVERGIB +DMG_ALWAYSGIB = SourceEngineDamageTypes.DMG_ALWAYSGIB +DMG_DROWN = SourceEngineDamageTypes.DMG_DROWN +DMG_PARALYZE = SourceEngineDamageTypes.DMG_PARALYZE +DMG_NERVEGAS = SourceEngineDamageTypes.DMG_NERVEGAS +DMG_POISON = SourceEngineDamageTypes.DMG_POISON +DMG_RADIATION = SourceEngineDamageTypes.DMG_RADIATION +DMG_DROWNRECOVER = SourceEngineDamageTypes.DMG_DROWNRECOVER +DMG_ACID = SourceEngineDamageTypes.DMG_ACID +DMG_SLOWBURN = SourceEngineDamageTypes.DMG_SLOWBURN +DMG_REMOVENORAGDOLL = SourceEngineDamageTypes.DMG_REMOVENORAGDOLL --- https://developer.valvesoftware.com/wiki/Weapon_script#SoundData --- --- (availability: server & client) ---- @alias SourceEngineSoundData ---- | `EMPTY` ---- | `SINGLE_SHOT` ---- | `DOUBLE_SHOT` ---- | `RELOAD` ---- | `MELEE_MISS` ---- | `MELEE_HIT` ---- | `MELEE_HIT_WORLD` ---- | `SPECIAL1` ---- | `SPECIAL2` ---- | `SPECIAL3` - ---- @type SourceEngineSoundData -EMPTY = 0 ---- @type SourceEngineSoundData -SINGLE_SHOT = 2 ---- @type SourceEngineSoundData -DOUBLE_SHOT = 3 ---- @type SourceEngineSoundData -RELOAD = 4 ---- @type SourceEngineSoundData -MELEE_MISS = 5 ---- @type SourceEngineSoundData -MELEE_HIT = 6 ---- @type SourceEngineSoundData -MELEE_HIT_WORLD = 7 ---- @type SourceEngineSoundData -SPECIAL1 = 10 ---- @type SourceEngineSoundData -SPECIAL2 = 11 ---- @type SourceEngineSoundData -SPECIAL3 = 12 +--- @enum SourceEngineSoundData +--- @field EMPTY 0 +--- @field SINGLE_SHOT 2 +--- @field DOUBLE_SHOT 3 +--- @field MELEE_MISS 4 +--- @field MELEE_HIT 5 +--- @field MELEE_HIT_WORLD 6 +--- @field SPECIAL1 9 +--- @field SPECIAL2 10 +--- @field SPECIAL3 11 +local SourceEngineSoundData = {} +EMPTY = SourceEngineSoundData.EMPTY +SINGLE_SHOT = SourceEngineSoundData.SINGLE_SHOT +DOUBLE_SHOT = SourceEngineSoundData.DOUBLE_SHOT +MELEE_MISS = SourceEngineSoundData.MELEE_MISS +MELEE_HIT = SourceEngineSoundData.MELEE_HIT +MELEE_HIT_WORLD = SourceEngineSoundData.MELEE_HIT_WORLD +SPECIAL1 = SourceEngineSoundData.SPECIAL1 +SPECIAL2 = SourceEngineSoundData.SPECIAL2 +SPECIAL3 = SourceEngineSoundData.SPECIAL3 --- (availability: server) ---- @alias subquest_text_replace_values_t ---- | `SUBQUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE` ---- | `SUBQUEST_TEXT_REPLACE_VALUE_TARGET_VALUE` ---- | `SUBQUEST_NUM_TEXT_REPLACE_VALUES` - ---- @type subquest_text_replace_values_t -SUBQUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE = 0 ---- @type subquest_text_replace_values_t -SUBQUEST_TEXT_REPLACE_VALUE_TARGET_VALUE = 1 ---- @type subquest_text_replace_values_t -SUBQUEST_NUM_TEXT_REPLACE_VALUES = 2 +--- @enum subquest_text_replace_values_t +--- @field SUBQUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE 0 +--- @field SUBQUEST_TEXT_REPLACE_VALUE_TARGET_VALUE 1 +--- @field SUBQUEST_NUM_TEXT_REPLACE_VALUES 2 +local subquest_text_replace_values_t = {} +SUBQUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE = subquest_text_replace_values_t.SUBQUEST_TEXT_REPLACE_VALUE_CURRENT_VALUE +SUBQUEST_TEXT_REPLACE_VALUE_TARGET_VALUE = subquest_text_replace_values_t.SUBQUEST_TEXT_REPLACE_VALUE_TARGET_VALUE +SUBQUEST_NUM_TEXT_REPLACE_VALUES = subquest_text_replace_values_t.SUBQUEST_NUM_TEXT_REPLACE_VALUES --- (availability: server & client) ---- @alias UnitFilterResult ---- | `UF_SUCCESS` ---- | `UF_FAIL_FRIENDLY` ---- | `UF_FAIL_ENEMY` ---- | `UF_FAIL_HERO` ---- | `UF_FAIL_CONSIDERED_HERO` ---- | `UF_FAIL_CREEP` ---- | `UF_FAIL_BUILDING` ---- | `UF_FAIL_COURIER` ---- | `UF_FAIL_OTHER` ---- | `UF_FAIL_ANCIENT` ---- | `UF_FAIL_ILLUSION` ---- | `UF_FAIL_SUMMONED` ---- | `UF_FAIL_DOMINATED` ---- | `UF_FAIL_MELEE` ---- | `UF_FAIL_RANGED` ---- | `UF_FAIL_DEAD` ---- | `UF_FAIL_MAGIC_IMMUNE_ALLY` ---- | `UF_FAIL_MAGIC_IMMUNE_ENEMY` ---- | `UF_FAIL_INVULNERABLE` ---- | `UF_FAIL_IN_FOW` ---- | `UF_FAIL_INVISIBLE` ---- | `UF_FAIL_NOT_PLAYER_CONTROLLED` ---- | `UF_FAIL_ATTACK_IMMUNE` ---- | `UF_FAIL_CUSTOM` ---- | `UF_FAIL_INVALID_LOCATION` ---- | `UF_FAIL_DISABLE_HELP` ---- | `UF_FAIL_OUT_OF_WORLD` ---- | `UF_FAIL_NIGHTMARED` ---- | `UF_FAIL_OBSTRUCTED` - ---- @type UnitFilterResult -UF_SUCCESS = 0 ---- @type UnitFilterResult -UF_FAIL_FRIENDLY = 1 ---- @type UnitFilterResult -UF_FAIL_ENEMY = 2 ---- @type UnitFilterResult -UF_FAIL_HERO = 3 ---- @type UnitFilterResult -UF_FAIL_CONSIDERED_HERO = 4 ---- @type UnitFilterResult -UF_FAIL_CREEP = 5 ---- @type UnitFilterResult -UF_FAIL_BUILDING = 6 ---- @type UnitFilterResult -UF_FAIL_COURIER = 7 ---- @type UnitFilterResult -UF_FAIL_OTHER = 8 ---- @type UnitFilterResult -UF_FAIL_ANCIENT = 9 ---- @type UnitFilterResult -UF_FAIL_ILLUSION = 10 ---- @type UnitFilterResult -UF_FAIL_SUMMONED = 11 ---- @type UnitFilterResult -UF_FAIL_DOMINATED = 12 ---- @type UnitFilterResult -UF_FAIL_MELEE = 13 ---- @type UnitFilterResult -UF_FAIL_RANGED = 14 ---- @type UnitFilterResult -UF_FAIL_DEAD = 15 ---- @type UnitFilterResult -UF_FAIL_MAGIC_IMMUNE_ALLY = 16 ---- @type UnitFilterResult -UF_FAIL_MAGIC_IMMUNE_ENEMY = 17 ---- @type UnitFilterResult -UF_FAIL_INVULNERABLE = 18 ---- @type UnitFilterResult -UF_FAIL_IN_FOW = 19 ---- @type UnitFilterResult -UF_FAIL_INVISIBLE = 20 ---- @type UnitFilterResult -UF_FAIL_NOT_PLAYER_CONTROLLED = 21 ---- @type UnitFilterResult -UF_FAIL_ATTACK_IMMUNE = 22 ---- @type UnitFilterResult -UF_FAIL_CUSTOM = 23 ---- @type UnitFilterResult -UF_FAIL_INVALID_LOCATION = 24 ---- @type UnitFilterResult -UF_FAIL_DISABLE_HELP = 25 ---- @type UnitFilterResult -UF_FAIL_OUT_OF_WORLD = 26 ---- @type UnitFilterResult -UF_FAIL_NIGHTMARED = 27 ---- @type UnitFilterResult -UF_FAIL_OBSTRUCTED = 28 +--- @enum UnitFilterResult +--- @field UF_SUCCESS 0 +--- @field UF_FAIL_FRIENDLY 1 +--- @field UF_FAIL_ENEMY 2 +--- @field UF_FAIL_HERO 3 +--- @field UF_FAIL_CONSIDERED_HERO 4 +--- @field UF_FAIL_CREEP 5 +--- @field UF_FAIL_BUILDING 6 +--- @field UF_FAIL_COURIER 7 +--- @field UF_FAIL_OTHER 8 +--- @field UF_FAIL_ANCIENT 9 +--- @field UF_FAIL_ILLUSION 10 +--- @field UF_FAIL_SUMMONED 11 +--- @field UF_FAIL_DOMINATED 12 +--- @field UF_FAIL_MELEE 13 +--- @field UF_FAIL_RANGED 14 +--- @field UF_FAIL_DEAD 15 +--- @field UF_FAIL_MAGIC_IMMUNE_ALLY 16 +--- @field UF_FAIL_MAGIC_IMMUNE_ENEMY 17 +--- @field UF_FAIL_INVULNERABLE 18 +--- @field UF_FAIL_IN_FOW 19 +--- @field UF_FAIL_INVISIBLE 20 +--- @field UF_FAIL_NOT_PLAYER_CONTROLLED 21 +--- @field UF_FAIL_ATTACK_IMMUNE 22 +--- @field UF_FAIL_CUSTOM 23 +--- @field UF_FAIL_INVALID_LOCATION 24 +--- @field UF_FAIL_DISABLE_HELP 25 +--- @field UF_FAIL_OUT_OF_WORLD 26 +--- @field UF_FAIL_NIGHTMARED 27 +--- @field UF_FAIL_OBSTRUCTED 28 +local UnitFilterResult = {} +UF_SUCCESS = UnitFilterResult.UF_SUCCESS +UF_FAIL_FRIENDLY = UnitFilterResult.UF_FAIL_FRIENDLY +UF_FAIL_ENEMY = UnitFilterResult.UF_FAIL_ENEMY +UF_FAIL_HERO = UnitFilterResult.UF_FAIL_HERO +UF_FAIL_CONSIDERED_HERO = UnitFilterResult.UF_FAIL_CONSIDERED_HERO +UF_FAIL_CREEP = UnitFilterResult.UF_FAIL_CREEP +UF_FAIL_BUILDING = UnitFilterResult.UF_FAIL_BUILDING +UF_FAIL_COURIER = UnitFilterResult.UF_FAIL_COURIER +UF_FAIL_OTHER = UnitFilterResult.UF_FAIL_OTHER +UF_FAIL_ANCIENT = UnitFilterResult.UF_FAIL_ANCIENT +UF_FAIL_ILLUSION = UnitFilterResult.UF_FAIL_ILLUSION +UF_FAIL_SUMMONED = UnitFilterResult.UF_FAIL_SUMMONED +UF_FAIL_DOMINATED = UnitFilterResult.UF_FAIL_DOMINATED +UF_FAIL_MELEE = UnitFilterResult.UF_FAIL_MELEE +UF_FAIL_RANGED = UnitFilterResult.UF_FAIL_RANGED +UF_FAIL_DEAD = UnitFilterResult.UF_FAIL_DEAD +UF_FAIL_MAGIC_IMMUNE_ALLY = UnitFilterResult.UF_FAIL_MAGIC_IMMUNE_ALLY +UF_FAIL_MAGIC_IMMUNE_ENEMY = UnitFilterResult.UF_FAIL_MAGIC_IMMUNE_ENEMY +UF_FAIL_INVULNERABLE = UnitFilterResult.UF_FAIL_INVULNERABLE +UF_FAIL_IN_FOW = UnitFilterResult.UF_FAIL_IN_FOW +UF_FAIL_INVISIBLE = UnitFilterResult.UF_FAIL_INVISIBLE +UF_FAIL_NOT_PLAYER_CONTROLLED = UnitFilterResult.UF_FAIL_NOT_PLAYER_CONTROLLED +UF_FAIL_ATTACK_IMMUNE = UnitFilterResult.UF_FAIL_ATTACK_IMMUNE +UF_FAIL_CUSTOM = UnitFilterResult.UF_FAIL_CUSTOM +UF_FAIL_INVALID_LOCATION = UnitFilterResult.UF_FAIL_INVALID_LOCATION +UF_FAIL_DISABLE_HELP = UnitFilterResult.UF_FAIL_DISABLE_HELP +UF_FAIL_OUT_OF_WORLD = UnitFilterResult.UF_FAIL_OUT_OF_WORLD +UF_FAIL_NIGHTMARED = UnitFilterResult.UF_FAIL_NIGHTMARED +UF_FAIL_OBSTRUCTED = UnitFilterResult.UF_FAIL_OBSTRUCTED diff --git a/.luacats/dota2/events.lua b/.luacats/dota2/events.lua index cc45aae..510a851 100644 --- a/.luacats/dota2/events.lua +++ b/.luacats/dota2/events.lua @@ -2,6 +2,7 @@ -- Generated by dota2-pos5 -- +--# selene: allow(incorrect_standard_library_use) --# selene: allow(unscoped_variables) --# selene: allow(unused_variable) @@ -58,8 +59,7 @@ --- @field name string Player name. --- @field userid EntityIndex User ID on server (unique on server). --- @field networkid string Player network (i.e steam) id. ---- @field xuid integer Steam id. ---- @field address string Ip:port. +--- @field xuid Uint64 Steam id. --- @field bot boolean --- @field index integer Player slot (entity index-1). @@ -69,14 +69,14 @@ --- @field reason integer See networkdisconnect enum protobuf. --- @field name string Player name. --- @field networkid string Player network (i.e steam) id. ---- @field xuid integer Steam id. +--- @field xuid Uint64 Steam id. --- @field PlayerID PlayerID --- A player changed his name. --- @class dota2.events.player_info --- @field name string Player name. --- @field userid EntityIndex User ID on server (unique on server). ---- @field steamid integer Player network (i.e steam) id. +--- @field steamid Uint64 Player network (i.e steam) id. --- @field bot boolean True if player is a AI bot. --- Player spawned in game. @@ -103,7 +103,7 @@ --- @class dota2.events.player_hurt --- @field userid EntityIndex Player who was hurt. ---- @field attacker player_controller_and_pawn Player who attacked. +--- @field attacker EntityIndex Player who attacked. --- @field health integer Remaining health points. --- A public player chat. @@ -148,8 +148,8 @@ --- Shot of a single entity. --- @class dota2.events.hltv_chase ---- @field target1 player_controller Primary traget index. ---- @field target2 player_controller Secondary traget index or 0. +--- @field target1 EntityIndex Primary traget index. +--- @field target2 EntityIndex Secondary traget index or 0. --- @field distance integer Camera distance. --- @field theta integer View angle horizontal. --- @field phi integer View angle vertical. @@ -160,13 +160,13 @@ --- @class dota2.events.hltv_rank_camera --- @field index integer Fixed camera index. --- @field rank number Ranking, how interesting is this camera view. ---- @field target player_controller Best/closest target entity. +--- @field target EntityIndex Best/closest target entity. --- An entity ranking. --- @class dota2.events.hltv_rank_entity --- @field userid EntityIndex Player slot. --- @field rank number Ranking, how interesting is this entity to view. ---- @field target player_controller Best/closest target entity. +--- @field target EntityIndex Best/closest target entity. --- Show from fixed view. --- @class dota2.events.hltv_fixed @@ -177,7 +177,7 @@ --- @field phi integer --- @field offset integer --- @field fov number ---- @field target player_controller Follow this player. +--- @field target EntityIndex Follow this player. --- A HLTV message send by moderators. --- @class dota2.events.hltv_message @@ -196,7 +196,7 @@ --- A HLTV chat msg sent by spectators. --- @class dota2.events.hltv_chat --- @field text string ---- @field steamID integer Steam id. +--- @field steamID Uint64 Steam id. --- @field name string --- @class dota2.events.hltv_versioninfo @@ -209,19 +209,8 @@ --- @class dota2.events.hltv_replay_status --- @field reason integer Reason for hltv replay status change (). ---- @class dota2.events.demo_start ---- @field dota_combatlog_list local CSVCMsgList_GameEvents that are combat log events. ---- @field dota_hero_chase_list local CSVCMsgList_GameEvents. ---- @field dota_pick_hero_list local CSVCMsgList_GameEvents. - --- @class dota2.events.demo_stop ---- @class dota2.events.demo_skip ---- @field playback_tick integer Current playback tick. ---- @field skipto_tick integer Tick we're going to. ---- @field user_message_list local CSVCMsgList_UserMessages. ---- @field dota_hero_chase_list local CSVCMsgList_GameEvents. - --- @class dota2.events.map_shutdown --- @class dota2.events.map_transition @@ -268,7 +257,7 @@ --- A game event, name may be 32 charaters long. --- @class dota2.events.player_death --- @field userid EntityIndex User ID who died. ---- @field attacker player_controller_and_pawn User ID who killed. +--- @field attacker EntityIndex User ID who killed. --- @class dota2.events.player_footstep --- @field userid EntityIndex @@ -309,17 +298,17 @@ --- @field votedata string --- @field team integer --- @field initiator integer Entity id of the player who initiated the vote. ---- @field reliable 1 This event is reliable. +--- @field reliable integer This event is reliable. --- @class dota2.events.vote_failed --- @field team integer ---- @field reliable 1 This event is reliable. +--- @field reliable integer This event is reliable. --- @class dota2.events.vote_passed --- @field details string --- @field param1 string --- @field team integer ---- @field reliable 1 This event is reliable. +--- @field reliable integer This event is reliable. --- @class dota2.events.vote_changed --- @field yesVotes integer @@ -340,7 +329,7 @@ --- @field max_val integer Total # of steps in achievement. --- @class dota2.events.achievement_earned ---- @field player player_controller Entindex of the player. +--- @field player EntityIndex Entindex of the player. --- @field achievement integer Achievement ID. --- @class dota2.events.achievement_write_failed @@ -446,6 +435,13 @@ --- @class dota2.events.dynamic_shadow_light_changed +--- @class dota2.events.bot_takeover +--- @field userid EntityIndex +--- @field botid EntityIndex +--- @field p number +--- @field y number +--- @field r number + --- Shot of a single entity. --- @class dota2.events.dota_chase_hero --- @field target1 integer Primary traget index. @@ -515,17 +511,32 @@ --- @class dota2.events.dota_barracks_kill --- @field barracks_id integer ---- @field killer_playerid PlayerID +--- @field barracks_type integer +--- @field teamnumber integer +--- @field killer_userid EntityIndex --- @field killer_team integer ---- @field bounty_amount integer +--- @field gold integer +--- @field pos_x number +--- @field pos_y number +--- @field pos_z number --- @class dota2.events.dota_tower_kill --- @field killer_userid EntityIndex --- @field teamnumber integer --- @field gold integer +--- @field tier integer +--- @field pos_x number +--- @field pos_y number +--- @field pos_z number --- @class dota2.events.dota_tower_deny --- @field killer_userid EntityIndex +--- @field teamnumber integer +--- @field gold integer +--- @field tier integer +--- @field pos_x number +--- @field pos_y number +--- @field pos_z number --- @class dota2.events.dota_effigy_kill --- @field owner_userid EntityIndex @@ -673,8 +684,6 @@ --- @class dota2.events.dota_action_success ---- @class dota2.events.dota_starting_position_changed - --- @class dota2.events.dota_team_neutral_stash_items_changed --- @field teamnumber integer @@ -694,10 +703,6 @@ --- @class dota2.events.dota_inventory_changed ---- @class dota2.events.dota_item_suggestions_changed - ---- @class dota2.events.dota_estimated_match_duration_changed - --- @class dota2.events.dota_hero_ability_points_changed --- @class dota2.events.dota_item_picked_up @@ -798,10 +803,10 @@ --- @class dota2.events.game_rules_state_change --- @class dota2.events.match_history_updated ---- @field SteamID integer +--- @field SteamID Uint64 --- @class dota2.events.match_details_updated ---- @field matchID integer +--- @field matchID Uint64 --- @class dota2.events.team_details_updated --- @field teamID integer @@ -814,7 +819,7 @@ --- @class dota2.events.news_updated --- @class dota2.events.persona_updated ---- @field SteamID integer +--- @field SteamID Uint64 --- @class dota2.events.tournament_state_updated @@ -897,6 +902,7 @@ --- @class dota2.events.dota_assist_earned --- @field entindex_hero EntityIndex +--- @field playerid_victim PlayerID --- @class dota2.events.bindpanel_open @@ -1074,8 +1080,6 @@ --- @class dota2.events.dota_tutorial_shop_toggled --- @field shop_opened boolean ---- @class dota2.events.map_location_updated - --- @class dota2.events.richpresence_custom_updated --- @class dota2.events.game_end_visible @@ -1135,27 +1139,27 @@ --- @field tree_y number --- @class dota2.events.ugc_details_arrived ---- @field published_file_id integer +--- @field published_file_id Uint64 --- @class dota2.events.ugc_subscribed ---- @field published_file_id integer +--- @field published_file_id Uint64 --- @class dota2.events.ugc_unsubscribed ---- @field published_file_id integer +--- @field published_file_id Uint64 --- @class dota2.events.ugc_download_requested ---- @field published_file_id integer +--- @field published_file_id Uint64 --- @class dota2.events.ugc_installed ---- @field published_file_id integer +--- @field published_file_id Uint64 --- @class dota2.events.prizepool_received --- @field success boolean ---- @field prizepool integer ---- @field leagueid integer +--- @field prizepool Uint64 +--- @field leagueid Uint64 --- @class dota2.events.microtransaction_success ---- @field txnid integer +--- @field txnid Uint64 --- @class dota2.events.dota_rubick_ability_steal --- @field abilityIndex integer @@ -1174,11 +1178,11 @@ --- @field reclaim_time number --- @class dota2.events.account_all_hero_challenge_changed ---- @field account_id integer +--- @field account_id Uint64 --- @class dota2.events.team_showcase_ui_update --- @field show boolean ---- @field account_id integer +--- @field account_id Uint64 --- @field hero_entindex EntityIndex --- @field display_ui_on_left boolean @@ -1190,7 +1194,7 @@ --- @class dota2.events.dota_year_beast_killed --- @field killer_player_id PlayerID --- @field message integer ---- @field beast_id integer +--- @field beast_id Uint64 --- @class dota2.events.dota_player_spawned --- @field PlayerID PlayerID @@ -1219,10 +1223,10 @@ --- @class dota2.events.dota_player_details_changed --- @class dota2.events.custom_game_player_count_updated ---- @field custom_game_id integer +--- @field custom_game_id Uint64 --- @class dota2.events.custom_game_friends_played_updated ---- @field custom_game_id integer +--- @field custom_game_id Uint64 --- @class dota2.events.custom_games_friends_play_updated @@ -1244,7 +1248,7 @@ --- @class dota2.events.dota_coin_wager --- @field userid EntityIndex --- @field message integer ---- @field coins integer +--- @field coins Uint64 --- @class dota2.events.dota_wager_token --- @field userid EntityIndex @@ -1267,6 +1271,28 @@ --- @field userid EntityIndex --- @field item_ability_id integer +--- @class dota2.events.dota_custom_camera_updated +--- @field flags integer DOTACustomCameraEventFlags_t. +--- @field zoom number +--- @field x number +--- @field y number +--- @field extra_yaw number +--- @field pitch number +--- @field duration number +--- @field player_id integer Only used if associated flag is set. + +--- @class dota2.events.dota_event_game_camera_zoom_updated +--- @field zoom integer +--- @field duration number 0 - instantaneous camera update. + +--- @class dota2.events.dota_event_game_camera_position_updated +--- @field x number +--- @field y number +--- @field duration number 0 - instantaneous camera update. + +--- @class dota2.events.dota_custom_camera_pitch_updated +--- @field pitch number + --- @class dota2.events.colorblind_mode_changed --- @class dota2.events.dota_report_submitted @@ -1362,6 +1388,21 @@ --- @field teamnumber integer --- @field herokills integer +--- @class dota2.events.dota_alchemist_granted_scepter +--- @field alchemist_userid EntityIndex +--- @field grantee_userid EntityIndex + +--- @class dota2.events.dota_protector_spawned +--- @field player_id integer + +--- @class dota2.events.dota_crafting_xp +--- @field userid EntityIndex +--- @field type integer +--- @field xp integer + +--- @class dota2.events.dota_roshan_roar +--- @field teamnumber integer + --- @class dota2.events.npc_spawned --- @field entindex EntityIndex --- @field is_respawn integer @@ -1388,4 +1429,9 @@ --- @class dota2.events.chat_members_changed --- @field channel integer +--- An NPC has gained aggro (is attacking) a hero. +--- @class dota2.events.dota_hero_on_gain_aggro +--- @field entindex_attacker EntityIndex +--- @field entindex_hero EntityIndex + diff --git a/.luacats/dota2/init.lua b/.luacats/dota2/init.lua index f366f15..dbbdb37 100644 --- a/.luacats/dota2/init.lua +++ b/.luacats/dota2/init.lua @@ -2,6 +2,7 @@ -- Generated by dota2-pos5 -- +--# selene: allow(incorrect_standard_library_use) --# selene: allow(unscoped_variables) --# selene: allow(unused_variable) @@ -529,14 +530,6 @@ function CBaseEntity:Kill() end --- @return CBaseEntity function CBaseEntity:NextMovePeer() end ---- Takes duration, value for a temporary override. ---- ---- (availability: server) ---- @param duration number ---- @param friction number ---- @return nil -function CBaseEntity:OverrideFriction(duration, friction) end - --- Precache a sound for later playing. --- --- (availability: server) @@ -617,7 +610,7 @@ function CBaseEntity:SetContextNum(name, value, duration) end --- --- (availability: server & client) --- @param contextName string ---- @param thinkFunc fun(entity: CBaseEntity): number | nil | nil +--- @param thinkFunc (fun(entity: CBaseEntity): number | nil) | nil --- @param interval number --- @return nil function CBaseEntity:SetContextThink(contextName, thinkFunc, interval) end @@ -721,7 +714,7 @@ function CBaseEntity:SetTeam(teamNum) end --- Note: optional parameters can be given in any order. --- --- (availability: server & client) ---- @param functionName fun(entity: CBaseEntity): number | nil | string If `context` is provided, think function would perform a dynamic lookup on `context` table. Otherwise searches for that function name in caller scope. +--- @param functionName (fun(entity: CBaseEntity): number | nil) | string If `context` is provided, think function would perform a dynamic lookup on `context` table. Otherwise searches for that function name in caller scope. --- @param context table | nil --- @param contextName string | nil Defaults to `functionName` if it's a string. --- @param initialDelay number | nil Defaults to 0 (next game frame). @@ -871,10 +864,10 @@ function CBaseModelEntity:ScriptLookupAttachment(attachmentName) end --- Sets a bodygroup. --- --- (availability: server) ---- @param group integer ---- @param value integer +--- @param bodyGroup integer +--- @param choice integer --- @return nil -function CBaseModelEntity:SetBodygroup(group, value) end +function CBaseModelEntity:SetBodygroup(bodyGroup, choice) end --- Sets a bodygroup by name. --- @@ -884,13 +877,6 @@ function CBaseModelEntity:SetBodygroup(group, value) end --- @return nil function CBaseModelEntity:SetBodygroupByName(name, value) end ---- Sets the light group of the entity. ---- ---- (availability: server) ---- @param lightGroup string ---- @return nil -function CBaseModelEntity:SetLightGroup(lightGroup) end - --- Set the material group of this entity. --- --- (availability: server) @@ -2103,17 +2089,6 @@ CDOTA_Ability_Nian_Roar = {} function CDOTA_Ability_Nian_Roar:GetCastCount() end ---- @class CDOTA_AghsFort_Ability_ArcWardenBoss_TempestDouble : CDOTABaseAbility -CDOTA_AghsFort_Ability_ArcWardenBoss_TempestDouble = {} - ---- Sets the number of doubles to spawn. ---- ---- (availability: server & client) ---- @param doubles integer ---- @return nil -function CDOTA_AghsFort_Ability_ArcWardenBoss_TempestDouble:SetNumDoubles(doubles) end - - --- @class CDOTA_BaseNPC : CBaseFlex CDOTA_BaseNPC = {} @@ -2270,6 +2245,13 @@ function CDOTA_BaseNPC:ChangeTeam(teamNum) end --- @return nil function CDOTA_BaseNPC:ClearActivityModifiers() end +--- Consume the item, deleting it from the inventory and granting the hero the specified bonuses. +--- +--- (availability: server) +--- @param item userdata +--- @return nil +function CDOTA_BaseNPC:ConsumeItem(item) end + --- (availability: server) --- @return nil function CDOTA_BaseNPC:DestroyAllSpeechBubbles() end @@ -4069,8 +4051,10 @@ function CDOTA_BaseNPC:TakeItem(item) end function CDOTA_BaseNPC:TimeUntilNextAttack() end --- (availability: server) +--- @param ability userdata +--- @param buff userdata --- @return boolean -function CDOTA_BaseNPC:TriggerModifierDodge() end +function CDOTA_BaseNPC:TriggerModifierDodge(ability, buff) end --- (availability: server) --- @param ability CDOTABaseAbility @@ -4223,6 +4207,13 @@ function CDOTA_BaseNPC_Creature:SetDisableResistance(disableResistance) end --- @return nil function CDOTA_BaseNPC_Creature:SetDisableResistanceGain(disableResistanceGain) end +--- Switches visible econ item group. +--- +--- (availability: server) +--- @param group integer +--- @return nil +function CDOTA_BaseNPC_Creature:SetEconItemGroup(group) end + --- Set the hit points gained per level on this creature. --- --- (availability: server) @@ -4407,9 +4398,8 @@ function CDOTA_BaseNPC_Hero:GetBuybackCooldownTime() end --- Return integer value for the gold cost of a buyback. --- --- (availability: server) ---- @param returnOldValues boolean --- @return integer -function CDOTA_BaseNPC_Hero:GetBuybackCost(returnOldValues) end +function CDOTA_BaseNPC_Hero:GetBuybackCost() end --- Returns the amount of time gold gain is limited after buying back. --- @@ -4449,6 +4439,10 @@ function CDOTA_BaseNPC_Hero:GetGold() end --- @return integer function CDOTA_BaseNPC_Hero:GetGoldBounty() end +--- (availability: server & client) +--- @return integer +function CDOTA_BaseNPC_Hero:GetHeroFacetID() end + --- (availability: server) --- @return integer function CDOTA_BaseNPC_Hero:GetHeroID() end @@ -4461,8 +4455,9 @@ function CDOTA_BaseNPC_Hero:GetHeroID() end function CDOTA_BaseNPC_Hero:GetIncreasedAttackSpeed(ignoreTempAttackSpeed) end --- (availability: server & client) +--- @param skipNoConsume boolean --- @return number -function CDOTA_BaseNPC_Hero:GetIntellect() end +function CDOTA_BaseNPC_Hero:GetIntellect(skipNoConsume) end --- (availability: server) --- @return number @@ -4834,8 +4829,8 @@ function CDOTA_BaseNPC_Hero:UpgradeAbility(ability) end function CDOTA_BaseNPC_Hero:WillReincarnate() end ---- @class CDOTA_BaseNPC_MangoTree : CDOTA_BaseNPC_Building -CDOTA_BaseNPC_MangoTree = {} +--- @class CDOTA_BaseNPC_LotusPool : CDOTA_BaseNPC_Building +CDOTA_BaseNPC_LotusPool = {} --- @class CDOTA_BaseNPC_NeutralItemStash : CDOTA_BaseNPC_Building CDOTA_BaseNPC_NeutralItemStash = {} @@ -5020,6 +5015,12 @@ function CDOTA_Buff:IsDebuff() end --- @return boolean function CDOTA_Buff:IsHexDebuff() end +--- Has underlying C++ entity object been deleted? +--- +--- (availability: server & client) +--- @return boolean +function CDOTA_Buff:IsNull() end + --- (availability: server & client) --- @return boolean function CDOTA_Buff:IsStunDebuff() end @@ -5169,6 +5170,10 @@ function CDOTA_Item:GetShareability() end --- @return integer function CDOTA_Item:GetValuelessCharges() end +--- (availability: server) +--- @return boolean +function CDOTA_Item:IsActiveNeutral() end + --- (availability: server & client) --- @return boolean function CDOTA_Item:IsAlertableItem() end @@ -5209,10 +5214,6 @@ function CDOTA_Item:IsKillable() end --- @return boolean function CDOTA_Item:IsMuted() end ---- (availability: server) ---- @return boolean -function CDOTA_Item:IsNeutralDrop() end - --- Is this a permanent item? --- --- (availability: server & client) @@ -5361,8 +5362,9 @@ function CDOTA_Item:SetShareability(shareability) end function CDOTA_Item:SetStacksWithOtherOwners(stacksWithOtherOwners) end --- (availability: server) +--- @param delayRemove number --- @return nil -function CDOTA_Item:SpendCharge() end +function CDOTA_Item:SpendCharge(delayRemove) end --- (availability: server) --- @return boolean @@ -5802,6 +5804,12 @@ function CDOTA_Item_Physical:GetContainedItem() end --- @return number function CDOTA_Item_Physical:GetCreationTime() end +--- Is this drop flagged as a loot drop? +--- +--- (availability: server) +--- @return boolean +function CDOTA_Item_Physical:IsLoot() end + --- Set the contained item. --- --- (availability: server) @@ -5809,6 +5817,13 @@ function CDOTA_Item_Physical:GetCreationTime() end --- @return nil function CDOTA_Item_Physical:SetContainedItem(item) end +--- Set if this drop is flagged as a loot drop. +--- +--- (availability: server) +--- @param isLoot boolean +--- @return nil +function CDOTA_Item_Physical:SetIsLoot(isLoot) end + --- @class CDOTA_ItemSpawner : CBaseEntity CDOTA_ItemSpawner = {} @@ -5892,7 +5907,7 @@ function CDOTA_Modifier_Lua:GetAuraEntityReject(entity) end --- Return the range around the parent this aura tries to apply its buff. --- --- (availability: server & client) ---- @return integer +--- @return number function CDOTA_Modifier_Lua:GetAuraRadius() end --- Return the unit flags this aura respects when placing buffs. @@ -6132,6 +6147,10 @@ function CDOTA_Modifier_Lua:GetAlwaysAutoAttackWhileHoldPosition() end --- @return string function CDOTA_Modifier_Lua:GetAttackSound() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetBaseAttackPostBonus() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetBonusDayVision() end @@ -6152,6 +6171,14 @@ function CDOTA_Modifier_Lua:GetBonusNightVisionUnique() end --- @return number function CDOTA_Modifier_Lua:GetBonusVisionPercentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetConvertAttackPhysicalToPure() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetCriticalStrikeBonus() end + --- (availability: server & client) --- @return 0 | 1 function CDOTA_Modifier_Lua:GetDisableAutoAttack() end @@ -6160,6 +6187,10 @@ function CDOTA_Modifier_Lua:GetDisableAutoAttack() end --- @return 0 | 1 function CDOTA_Modifier_Lua:GetDisableHealing() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetDisableManaGain() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetFixedDayVision() end @@ -6176,22 +6207,46 @@ function CDOTA_Modifier_Lua:GetForceDrawOnMinimap() end --- @return 0 | 1 function CDOTA_Modifier_Lua:GetIsIllusion() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetMagicalArmorPiercingPercentageTarget() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetMinHealth() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetMinMana() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierAbilityLayout() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierAbilityPoints() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierAdditionalNutralItemDrops() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierAoEBonusConstant() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierAoEBonusConstantStacking() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierAoEBonusPercentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierAttackHeightBonus() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierAttackPointConstant() end @@ -6216,6 +6271,10 @@ function CDOTA_Modifier_Lua:GetModifierAttackRangeOverride() end --- @return nil function CDOTA_Modifier_Lua:GetModifierAttackSpeed_Limit() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierAttackSpeedAbsoluteMax() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierAttackSpeedBaseOverride() end @@ -6232,6 +6291,10 @@ function CDOTA_Modifier_Lua:GetModifierAttackSpeedPercentage() end --- @return number function CDOTA_Modifier_Lua:GetModifierAttackSpeedReductionPercentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierAvoidAttackProcs() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return number @@ -6277,6 +6340,18 @@ function CDOTA_Modifier_Lua:GetModifierBaseDamageOutgoing_PercentageUnique(event --- @return number function CDOTA_Modifier_Lua:GetModifierBaseRegen() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBecomeAgility() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBecomeIntelligence() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBecomeStrength() end + --- (availability: server & client) --- @return 0 | 1 function CDOTA_Modifier_Lua:GetModifierBecomeUniversal() end @@ -6285,6 +6360,26 @@ function CDOTA_Modifier_Lua:GetModifierBecomeUniversal() end --- @return nil function CDOTA_Modifier_Lua:GetModifierBonusDamageOutgoing_Percentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBonusLotusHeal() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBonusLotusHeal() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBonusLotusHeal() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBonusLotusHeal() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBonusLotusHeal() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierBonusStats_Agility() end @@ -6309,6 +6404,14 @@ function CDOTA_Modifier_Lua:GetModifierBonusStats_Strength() end --- @return number function CDOTA_Modifier_Lua:GetModifierBonusStats_Strength_Percentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBonusUphillMissChance() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierBuybackPenaltyPercent() end + --- (availability: server & client) --- @return 0 | 1 function CDOTA_Modifier_Lua:GetModifierCanAttackTrees() end @@ -6357,11 +6460,27 @@ function CDOTA_Modifier_Lua:GetModifierConstantManaRegenUnique() end --- @return number function CDOTA_Modifier_Lua:GetModifierConstantRespawnTime() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierConvertManaCostToHealthCost() end + --- (availability: server & client) --- @param event ModifierAbilityEvent --- @return number function CDOTA_Modifier_Lua:GetModifierCooldownReduction_Constant(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierCreateBonusIllusionChance() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierCreateBonusIllusionCount() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierCreepDenyPercent() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return number @@ -6385,12 +6504,12 @@ function CDOTA_Modifier_Lua:GetModifierDamageOutgoing_PercentageMultiplicative() function CDOTA_Modifier_Lua:GetModifierDisableTurning() end --- (availability: server & client) ---- @return 0 | 1 -function CDOTA_Modifier_Lua:GetModifierDodgeProjectile() end +--- @return nil +function CDOTA_Modifier_Lua:GetModifierDisassembleAnything() end --- (availability: server & client) ---- @return nil -function CDOTA_Modifier_Lua:GetModifierDoNotSinkAfterDeath() end +--- @return 0 | 1 +function CDOTA_Modifier_Lua:GetModifierDodgeProjectile() end --- (availability: server & client) --- @param event ModifierAttackEvent @@ -6425,10 +6544,26 @@ function CDOTA_Modifier_Lua:GetModifierExtraStrengthBonus() end --- @return number function CDOTA_Modifier_Lua:GetModifierFixedAttackRate() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierFixedManaRegen() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierForceMaxHealth() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierForceMaxMana() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierFoWTeam() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierHasBonusNeutralItemChoice() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierHealAmplify_PercentageSource() end @@ -6460,6 +6595,10 @@ function CDOTA_Modifier_Lua:GetModifierHealthRegenPercentage() end --- @return number function CDOTA_Modifier_Lua:GetModifierHealthRegenPercentageUnique() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierHeroFacetOverride() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierHPRegen_CanBeNegative() end @@ -6468,6 +6607,10 @@ function CDOTA_Modifier_Lua:GetModifierHPRegen_CanBeNegative() end --- @return number function CDOTA_Modifier_Lua:GetModifierHPRegenAmplify_Percentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierHPRegenMultiplierPreAmplification() end + --- (availability: server & client) --- @return 0 | 1 function CDOTA_Modifier_Lua:GetModifierIgnoreCastAngle() end @@ -6520,6 +6663,14 @@ function CDOTA_Modifier_Lua:GetModifierIncomingPhysicalDamageConstant(event) end --- @return number function CDOTA_Modifier_Lua:GetModifierIncomingSpellDamageConstant(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierInnateDamageBlockPctOverride() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierInventorySlotRestricted() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierInvisibilityAttackBehaviorException() end @@ -6530,7 +6681,15 @@ function CDOTA_Modifier_Lua:GetModifierInvisibilityLevel() end --- (availability: server & client) --- @return nil -function CDOTA_Modifier_Lua:GetModifierIsRatPack() end +function CDOTA_Modifier_Lua:GetModifierIsPackRat() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierItemSellbackCost() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierKillStreakBonusGoldPercentage() end --- (availability: server & client) --- @return nil @@ -6601,6 +6760,10 @@ function CDOTA_Modifier_Lua:GetModifierMinPhysicalArmor() end --- @return number function CDOTA_Modifier_Lua:GetModifierMiss_Percentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierMiss_Percentage_Target() end + --- (availability: server & client) --- @return string function CDOTA_Modifier_Lua:GetModifierModelChange() end @@ -6637,6 +6800,14 @@ function CDOTA_Modifier_Lua:GetModifierMoveSpeed_AbsoluteMin() end --- @return number function CDOTA_Modifier_Lua:GetModifierMoveSpeed_Limit() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierMoveSpeed_MaxOverride() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierMoveSpeed_MinOverride() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierMoveSpeedBonus_Constant() end @@ -6665,10 +6836,18 @@ function CDOTA_Modifier_Lua:GetModifierMoveSpeedBonus_Special_Boots() end --- @return number function CDOTA_Modifier_Lua:GetModifierMoveSpeedBonus_Special_Boots_2() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierMoveSpeedMax_BonusConstant() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierMoveSpeedOverride() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierMoveSpeedPostMultiplierBonus_Constant () end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierMoveSpeedReductionPercentage() end @@ -6677,6 +6856,10 @@ function CDOTA_Modifier_Lua:GetModifierMoveSpeedReductionPercentage() end --- @return number function CDOTA_Modifier_Lua:GetModifierMPRegenAmplify_Percentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierMPRegenAmplify_Percentage_Unique() end + --- Total amplify value is clamped to 0. --- --- (availability: server & client) @@ -6687,6 +6870,18 @@ function CDOTA_Modifier_Lua:GetModifierMPRestoreAmplify_Percentage() end --- @return number function CDOTA_Modifier_Lua:GetModifierNegativeEvasion_Constant() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierNeutralEnhancementOptions() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierNeutralTrinketOptions() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierNoFreeTPScrollOnDeath() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierNoVisionOfAttacker() end @@ -6729,6 +6924,10 @@ function CDOTA_Modifier_Lua:GetModifierPercentageCooldownOngoing(event) end --- @return number function CDOTA_Modifier_Lua:GetModifierPercentageCooldownStacking(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPercentageDeathGoldCost() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierPercentageExpRateBoost() end @@ -6850,6 +7049,10 @@ function CDOTA_Modifier_Lua:GetModifierPreAttack_Target_CriticalStrike() end --- @return nil function CDOTA_Modifier_Lua:GetModifierPrereduceIncomingDamage_Mult() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPreserveNeutralItemPassives() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return number @@ -6894,6 +7097,46 @@ function CDOTA_Modifier_Lua:GetModifierProjectileSpeedBonus() end --- @return number function CDOTA_Modifier_Lua:GetModifierProjectileSpeedBonusPercentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierProjectileSpeedTarget() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierProperty_MagicalLifesteal() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierProperty_PhysicalLifesteal() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyConsumableUseSpeed() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyForbidIllusions() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyHealingAmplificationUnique() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyManacostOverride() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyRestorationAmplification() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyRestorationAmplificationUnique() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierPropertyUpgradeNeutralArtifacts() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierPropetyFailAttack() end @@ -6919,8 +7162,20 @@ function CDOTA_Modifier_Lua:GetModifierScepter() end function CDOTA_Modifier_Lua:GetModifierShard() end --- (availability: server & client) ---- @return number -function CDOTA_Modifier_Lua:GetModifierSlowResistance() end +--- @return nil +function CDOTA_Modifier_Lua:GetModifierShareXPRune() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierSlowResistance_Stacking() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GEtModifierSlowResistance_Unique() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierSlowResistanceAppliesToAttacks() end --- (availability: server & client) --- @param event ModifierAttackEvent @@ -6931,6 +7186,10 @@ function CDOTA_Modifier_Lua:GetModifierSpellAmplify_Percentage(event) end --- @return nil function CDOTA_Modifier_Lua:GetModifierSpellAmplify_PercentageCreep() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierSpellAmplify_PercentageTarget() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetModifierSpellAmplify_PercentageUnique() end @@ -6939,6 +7198,10 @@ function CDOTA_Modifier_Lua:GetModifierSpellAmplify_PercentageUnique() end --- @return nil function CDOTA_Modifier_Lua:GetModifierSpellLifestealRegenAmplify_Percentage() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierSpellLifestealRegenAmplify_Percentage_Unique() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetModifierSpellRedirectTarget() end @@ -6993,6 +7256,10 @@ function CDOTA_Modifier_Lua:GetModifierTickGold_Multiplier() end --- @return number function CDOTA_Modifier_Lua:GetModifierTotal_ConstantBlock(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierTotal_ConstantBlockStacking() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return number @@ -7026,6 +7293,14 @@ function CDOTA_Modifier_Lua:GetModifierUnitStatsNeedsRefresh() end --- @return nil function CDOTA_Modifier_Lua:GetModifierXPDuringDeath() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModifierXPFountainCountdownTimeOverride() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetModofierPropertyPseudoRandomBonus() end + --- (availability: server & client) --- @return GameActivity_t function CDOTA_Modifier_Lua:GetOverrideAnimation() end @@ -7034,32 +7309,56 @@ function CDOTA_Modifier_Lua:GetOverrideAnimation() end --- @return number function CDOTA_Modifier_Lua:GetOverrideAnimationRate() end ---- (availability: server & client) ---- @return number -function CDOTA_Modifier_Lua:GetOverrideAnimationWeight() end - --- (availability: server & client) --- @return 0 | 1 function CDOTA_Modifier_Lua:GetOverrideAttackMagical() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetPhysicalArmorPiercingPercentageTarget() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetPrimaryStatDamageMultiplier() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetRedirectSpell() end + --- (availability: server & client) --- @param event ModifierAbilityEvent --- @return 0 | 1 function CDOTA_Modifier_Lua:GetReflectSpell(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetSkipAttackRegulator() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetSuppressAttackProcs() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return 0 | 1 function CDOTA_Modifier_Lua:GetSuppressCleave(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetSuppressCrit() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetSuppressIncomingCrit() end + --- (availability: server & client) --- @return 0 | 1 function CDOTA_Modifier_Lua:GetSuppressTeleport() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetTierTokenReroll() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:GetTriggerCosmeticAndEndAttack() end @@ -7068,6 +7367,10 @@ function CDOTA_Modifier_Lua:GetTriggerCosmeticAndEndAttack() end --- @return number function CDOTA_Modifier_Lua:GetUnitLifetimeFraction() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:GetVisionDegreeRestriction() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:GetVisualZDelta() end @@ -7076,6 +7379,10 @@ function CDOTA_Modifier_Lua:GetVisualZDelta() end --- @return nil function CDOTA_Modifier_Lua:GetVisualZSpeedBaseOverride() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:MinAttributeLevel() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT_POST() end @@ -7100,6 +7407,10 @@ function CDOTA_Modifier_Lua:OnAbilityFullyCast(event) end --- @return nil function CDOTA_Modifier_Lua:OnAbilityStart(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnAbilityToggled() end + --- (availability: server & client) --- @return nil function CDOTA_Modifier_Lua:OnAssist() end @@ -7169,6 +7480,10 @@ function CDOTA_Modifier_Lua:OnBreakInvisibility() end --- @return nil function CDOTA_Modifier_Lua:OnBuildingKilled(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnCleaveAttackLanded() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return nil @@ -7182,6 +7497,10 @@ function CDOTA_Modifier_Lua:OnDamageHPLoss() end --- @return nil function CDOTA_Modifier_Lua:OnDamagePrevented() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnDayStarted() end + --- (availability: server & client) --- @param event ModifierInstanceEvent --- @return nil @@ -7201,6 +7520,10 @@ function CDOTA_Modifier_Lua:OnDominated(event) end --- @return nil function CDOTA_Modifier_Lua:OnForceProcMagicStick() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnFoWTeamChanged() end + --- (availability: server & client) --- @param event ModifierHealEvent --- @return nil @@ -7211,6 +7534,10 @@ function CDOTA_Modifier_Lua:OnHealReceived(event) end --- @return nil function CDOTA_Modifier_Lua:OnHealthGained(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnHeroBeginDying() end + --- (availability: server & client) --- @param event ModifierAttackEvent --- @return nil @@ -7239,6 +7566,18 @@ function CDOTA_Modifier_Lua:OnModelChanged(event) end --- @return nil function CDOTA_Modifier_Lua:OnModifierAdded(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnModifierRemoved() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnMuteDamageAbilities() end + +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnNightStarted() end + --- (availability: server & client) --- @param event ModifierUnitEvent --- @return nil @@ -7261,11 +7600,19 @@ function CDOTA_Modifier_Lua:OnProjectileDodge(event) end --- @return nil function CDOTA_Modifier_Lua:OnProjectileObstructionHit() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnPureDamageCalculated() end + --- (availability: server & client) --- @param event ModifierUnitEvent --- @return nil function CDOTA_Modifier_Lua:OnRespawn(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnRuneSpawn() end + --- (availability: server & client) --- @param event ModifierUnitEvent --- @return nil @@ -7305,6 +7652,10 @@ function CDOTA_Modifier_Lua:OnTakeDamage(event) end --- @return nil function CDOTA_Modifier_Lua:OnTakeDamageKillCredit(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnTakeDamagePostUnavoidableBlock() end + --- (availability: server & client) --- @param event ModifierUnitEvent --- @return nil @@ -7315,6 +7666,10 @@ function CDOTA_Modifier_Lua:OnTeleported(event) end --- @return nil function CDOTA_Modifier_Lua:OnTeleporting(event) end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnTierTokenRerolled() end + --- (availability: server & client) --- @return number function CDOTA_Modifier_Lua:OnTooltip() end @@ -7323,6 +7678,10 @@ function CDOTA_Modifier_Lua:OnTooltip() end --- @return number function CDOTA_Modifier_Lua:OnTooltip2() end +--- (availability: server & client) +--- @return nil +function CDOTA_Modifier_Lua:OnTreeCutDown() end + --- (availability: server & client) --- @param event ModifierUnitEvent --- @return nil @@ -8381,6 +8740,12 @@ function CDOTA_SimpleObstruction:SetEnabled(enabled, force) end --- @class CDOTA_Unit_Courier : CDOTA_BaseNPC CDOTA_Unit_Courier = {} +--- Respawn the courier. +--- +--- (availability: server) +--- @return nil +function CDOTA_Unit_Courier:RespawnCourier() end + --- Upgrade the courier ( int param ) times. --- --- (availability: server) @@ -8418,33 +8783,6 @@ function CDOTA_Unit_CustomGameAnnouncerAghanim:SetAnimation(animation) end function CDOTA_Unit_CustomGameAnnouncerAghanim:SetServerAuthoritative(isServerAuthoritative) end ---- @class CDOTA_Unit_Diretide_Portal : CDOTA_BaseNPC_Building -CDOTA_Unit_Diretide_Portal = {} - ---- (availability: server) ---- @return userdata -function CDOTA_Unit_Diretide_Portal:GetPartnerPortal() end - ---- (availability: server) ---- @return nil -function CDOTA_Unit_Diretide_Portal:ResetPortal() end - ---- (availability: server) ---- @param runeType integer ---- @return nil -function CDOTA_Unit_Diretide_Portal:SetInvasionRuneType(runeType) end - ---- (availability: server) ---- @param portal userdata ---- @return nil -function CDOTA_Unit_Diretide_Portal:SetPartnerPortal(portal) end - ---- (availability: server) ---- @param active boolean ---- @return nil -function CDOTA_Unit_Diretide_Portal:SetPortalActive(active) end - - --- @class CDOTA_Unit_Nian : CDOTA_BaseNPC_Creature CDOTA_Unit_Nian = {} @@ -8574,7 +8912,7 @@ function CDOTABaseAbility:GetAbilityType() end function CDOTABaseAbility:GetAnimationIgnoresModelScale() end --- (availability: server) ---- @return integer +--- @return number function CDOTABaseAbility:GetAOERadius() end --- (availability: server) @@ -9964,6 +10302,11 @@ function CDOTABaseGameMode:SetKillingSpreeAnnouncerDisabled(disabled) end --- @return nil function CDOTABaseGameMode:SetLoseGoldOnDeath(enabled) end +--- (availability: server) +--- @param script userdata +--- @return nil +function CDOTABaseGameMode:SetLuaGameMode(script) end + --- Set the maximum attack speed for units. --- --- (availability: server) @@ -12205,7 +12548,7 @@ CMarkupVolumeTagged = {} --- Does this volume have the given tag. --- --- (availability: server) ---- @param tagName string +--- @param tagName any --- @return boolean function CMarkupVolumeTagged:HasTag(tagName) end @@ -12343,13 +12686,6 @@ function CPhysicsProp:DisableMotion() end --- @return nil function CPhysicsProp:EnableMotion() end ---- Enable/disable dynamic vs dynamic continuous collision traces. ---- ---- (availability: server) ---- @param isDynamicVsDynamicContinuousEnabled boolean ---- @return nil -function CPhysicsProp:SetDynamicVsDynamicContinuous(isDynamicVsDynamicContinuousEnabled) end - --- @class CPointClientUIWorldPanel : CBaseModelEntity CPointClientUIWorldPanel = {} @@ -12518,8 +12854,6 @@ function HeroList:GetHero(nth) end function HeroList:GetHeroCount() end ---- Note: Actual `CScriptHTTPRequest` global exists only after CreateHTTPRequest is called. ---- --- Note: Actual `CScriptHTTPRequest` global exists only after CreateHTTPRequest is called. --- @class CScriptHTTPRequest CScriptHTTPRequest = {} @@ -12783,9 +13117,9 @@ CTakeDamageInfo = {} function CTakeDamageInfo:AddDamage(addAmount) end --- (availability: server) ---- @param bitsDamageType integer +--- @param damageType integer --- @return nil -function CTakeDamageInfo:AddDamageType(bitsDamageType) end +function CTakeDamageInfo:AddDamageType(damageType) end --- (availability: server) --- @return integer @@ -12812,7 +13146,7 @@ function CTakeDamageInfo:GetDamageForce() end function CTakeDamageInfo:GetDamagePosition() end --- (availability: server) ---- @return integer +--- @return any function CTakeDamageInfo:GetDamageType() end --- (availability: server) @@ -12828,9 +13162,13 @@ function CTakeDamageInfo:GetOriginalDamage() end function CTakeDamageInfo:GetReportedPosition() end --- (availability: server) ---- @param bitsToTest integer +--- @return number +function CTakeDamageInfo:GetTotalledDamage() end + +--- (availability: server) +--- @param damageType integer --- @return boolean -function CTakeDamageInfo:HasDamageType(bitsToTest) end +function CTakeDamageInfo:HasDamageType(damageType) end --- (availability: server) --- @param scaleAmount number @@ -12868,9 +13206,9 @@ function CTakeDamageInfo:SetDamageForce(damageForce) end function CTakeDamageInfo:SetDamagePosition(damagePosition) end --- (availability: server) ---- @param bitsDamageType integer +--- @param damageType integer --- @return nil -function CTakeDamageInfo:SetDamageType(bitsDamageType) end +function CTakeDamageInfo:SetDamageType(damageType) end --- (availability: server) --- @param originalDamage number @@ -13104,8 +13442,6 @@ function ProjectileManager:ProjectileDodge(unit) end function ProjectileManager:UpdateLinearProjectileDirection(projectile, direction, speed) end ---- QAngle class. ---- --- QAngle class. --- @class QAngle --- @field x number Pitch angle @@ -13163,8 +13499,6 @@ SteamInfo = {} function SteamInfo:IsPublicUniverse() end ---- Integer with binary operations. ---- --- Integer with binary operations. --- @class Uint64 Uint64 = {} @@ -13242,8 +13576,6 @@ function Uint64:ToggleBit(bitvalue) end function Uint64:ToHexString() end ---- 3D Vector class. ---- --- 3D Vector class. --- @class Vector --- @field x number X-axis @@ -13500,7 +13832,7 @@ function CreateIllusions(owner, heroToCopy, modifierKeys, numIllusions, padding, --- (availability: server) --- @param itemName string --- @param owner CDOTAPlayerController | nil ---- @param purchaser CDOTAPlayerController | nil +--- @param purchaser CDOTA_BaseNPC_Hero | nil --- @return CDOTA_Item | nil function CreateItem(itemName, owner, purchaser) end @@ -13654,6 +13986,18 @@ function cvar_setf(arg1, arg2) end --- @return nil function DebugBreak() end +--- Creates a unit with a specified hero variant, controllable by the specified player. +--- +--- (availability: server) +--- @param arg1 userdata +--- @param arg2 string +--- @param arg3 integer +--- @param arg4 integer +--- @param arg5 boolean +--- @param arg6 userdata +--- @return integer +function DebugCreateHeroWithVariant(arg1, arg2, arg3, arg4, arg5, arg6) end + --- Creates a test unit controllable by the specified player. --- --- (availability: server) diff --git a/.luacats/dota2/types.lua b/.luacats/dota2/types.lua index 856a21a..8e29a50 100644 --- a/.luacats/dota2/types.lua +++ b/.luacats/dota2/types.lua @@ -2,6 +2,7 @@ -- Generated by dota2-pos5 -- +--# selene: allow(incorrect_standard_library_use) --# selene: allow(unscoped_variables) --# selene: allow(unused_variable) diff --git a/.luacats/luassert.lua b/.luacats/luassert.lua index 864298f..40e86ee 100644 --- a/.luacats/luassert.lua +++ b/.luacats/luassert.lua @@ -1,4 +1,4 @@ ----@meta +--- @meta ---@class luassert.internal local internal = {} diff --git a/.luacats/middleclass.lua b/.luacats/middleclass.lua new file mode 100644 index 0000000..b88fe77 --- /dev/null +++ b/.luacats/middleclass.lua @@ -0,0 +1,27 @@ +--# selene: allow(unused_variable) +--- @meta + +--- @class middleclass +--- @overload fun(classname: string, super?: middleclass.Class): middleclass.Class +local M = {} + +--- @class middleclass.Class +--- @field static table +local Class = {} + +--- @param ... any +--- @return self +function Class:new(...) end + +--- @param mixin table +function Class:include(mixin) end + +--- @param class middleclass.Class +--- @return boolean +function Class:isInstanceOf(class) end + +--- @param super middleclass.Class +--- @return boolean +function Class:isSubclassOf(super) end + +return M diff --git a/.luacats/pl/Date.lua b/.luacats/pl/Date.lua deleted file mode 100644 index 87461e8..0000000 --- a/.luacats/pl/Date.lua +++ /dev/null @@ -1,294 +0,0 @@ ----@meta - -local class = require("pl.class") - ----# Class [`pl.Date`](https://lunarmodules.github.io/Penlight/classes/pl.Date.html) ---- ----Date and Date Format classes. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/05-dates.md.html#). ---- ----NOTE: the date module is deprecated! see https://github.com/lunarmodules/Penlight/issues/285 ---- ----Dependencies: ---- [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html#) ---- [`pl.stringx`](https://lunarmodules.github.io/Penlight/libraries/pl.stringx.html#) ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#) ----@class pl.Date : pl.Class ----@operator sub(pl.Date): pl.Date.Interval ----@overload fun(t?: number|pl.Date|osdate, is_utc?: boolean): pl.Date ----@overload fun(year: integer, month: integer, day: integer, hour?: integer, min?: integer, sec?: integer): pl.Date -local Date = class() - ----Date constructor. ----@param self pl.Date ----@param t? number|pl.Date|osdate -- this can be either ---- ---- * `nil` or empty - use current date and time ---- * `number` - seconds since epoch (as returned by os.time). Resulting time is UTC ---- * `Date` - make a copy of this date ---- * `table` - table containing year, month, etc as for os.time. You may leave out year, month or day, in which case current values will be used. ---- * year (will be followed by month, day etc) ---- ----@param is_utc? boolean -- `true` if Universal Coordinated Time -function Date:_init(t, is_utc) end - ----@param self pl.Date ----@param year integer ----@param month integer ----@param day integer ----@param hour? integer ----@param min? integer ----@param sec? integer -function Date:_init(year, month, day, hour, min, sec) end - ----set the current time of this Date object. ----@param self pl.Date ----@param t integer -- seconds since epoch -function Date:set(t) end - ----get the time zone offset from UTC. ----@param ts integer -- seconds ahead of UTC ----@return integer ----@nodiscard -function Date.tzone(ts) end - ----convert this date to UTC. ----@param self pl.Date ----@return pl.Date ----@nodiscard -function Date:toUTC() end - ----convert this UTC date to local. ----@param self pl.Date ----@return pl.Date ----@nodiscard -function Date:toLocal() end - ----set the year. ----@param self pl.Date ----@param y integer -- Four-digit year ----@return pl.Date self -function Date:year(y) end - ----set the month. ----@param self pl.Date ----@param m integer -- month ----@return pl.Date self -function Date:month(m) end - ----set the day. ----@param self pl.Date ----@param d integer -- day ----@return pl.Date self -function Date:day(d) end - ----set the hour. ----@param h integer -- hour ----@return pl.Date self -function Date:hour(h) end - ----set the minutes. ----@param self pl.Date ----@param min integer -- minutes ----@return pl.Date self -function Date:min(min) end - ----set the seconds. ----@param self pl.Date ----@param sec integer -- seconds ----@return pl.Date self -function Date:sec(sec) end - ----set the day of year. ----@param self pl.Date ----@param yday integer -- day of year ----@return pl.Date self -function Date:yday(yday) end - ----get the year. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:year() end - ----get the month. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:month() end - ----get the day. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:day() end - ----get the hour. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:hour() end - ----get the minutes. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:min() end - ----get the seconds. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:sec() end - ----get the day of year. ----@param self pl.Date ----@return integer ----@nodiscard -function Date:yday() end - ----name of day of week. ----@param self pl.Date ----@param full boolean -- abbreviated if true, full otherwise. ----@return string -- name ----@nodiscard -function Date:weekday_name(full) end - ----name of month. ----@param self pl.Date ----@param full boolean -- abbreviated if true, full otherwise. ----@return string -- name ----@nodiscard -function Date:month_name(full) end - ----is this day on a weekend? ----@param self pl.Date ----@return boolean ----@nodiscard -function Date:is_weekend() end - ----add to a date object. ----@param self pl.Date ----@param t osdate -- a table containing one of the following keys and a value: one of `year`, `month`, `day`, `hour`, `min`, `sec` ----@return pl.Date self -- this date -function Date:add(t) end - ----last day of the month. ----@param self pl.Date ----@return integer -- day ----@nodiscard -function Date:last_day() end - ----difference between two `Date` objects. ----@param self pl.Date ----@param other pl.Date -- Date object ----@return pl.Date.Interval -- object ----@nodiscard -function Date:diff(other) end - ----long numerical ISO data format version of this date. ----@param self pl.Date ----@return string ----@nodiscard -function Date:__tostring() end - ----equality between Date objects. ----@param self pl.Date ----@param other pl.Date ----@return boolean ----@nodiscard -function Date:__eq(other) end - ----ordering between Date objects. ----@param self pl.Date ----@param other pl.Date ----@return boolean ----@nodiscard -function Date:__lt(other) end - ----difference between Date objects. ----@param self pl.Date ----@param other pl.Date ----@return pl.Date.Interval ----@nodiscard -function Date:__sub(other) end - ----add a date and an interval. ----@param self pl.Date ----@param other pl.Date.Interval|osdate -- either a `pl.Date.Interval` object or a table such as passed to `Date:add` ----@return pl.Date ----@nodiscard -function Date:__add(other) end - ----@class pl.Date.Interval : pl.Class ----@overload fun(t: integer): pl.Date.Interval -local DateInterval = class() - ----Date.Interval constructor ----@param self pl.Date.Interval ----@param t integer - an interval in seconds -function DateInterval:_init(t) end - ----If it's an interval then the format is '2 hours 29 sec' etc. ----@param self pl.Date.Interval ----@return string ----@nodiscard -function DateInterval:__tostring() end - -Date.Interval = DateInterval - ----@class pl.Date.Format : pl.Class ----@overload fun(fmt: string): pl.Date.Format -local DateFormat = class() - ----Date.Format constructor ----@param self pl.Date.Format ----@param fmt string -- a string where the following fields are significant: ---- ---- * `d`: day (either d or dd) ---- * `y`: year (either yy or yyy) ---- * `m`: month (either m or mm) ---- * `H`: hour (either H or HH) ---- * `M`: minute (either M or MM) ---- * `S`: second (either S or SS) ---- ----Alternatively, if `fmt` is nil then this returns a flexible date parser that ----tries various date/time schemes in turn: ---- ---- * ISO 8601, like `2010-05-10 12:35:23Z` or `2008-10-03T14:30+02` ---- * times like 15:30 or 8.05pm (assumed to be today's date) ---- * dates like 28/10/02 (European order!) or 5 Feb 2012 ---- * month name like march or Mar (case-insensitive, first 3 letters); here the day will be 1 and the year this current year ---- ----A date in format 3 can be optionally followed by a time in format 2. Please see test-date.lua in the tests folder for more examples. ---- ----Usage: ---- ----```lua ----df = Date.Format("yyyy-mm-dd HH:MM:SS") ----``` -function DateFormat:_init(fmt) end - ----parse a string into a Date object. ----@param self pl.Date.Format ----@param str string -- a date string ----@return pl.Date -- date object ----@nodiscard -function DateFormat:parse(str) end - ----convert a Date object into a string. ----@param self pl.Date.Format ----@param d pl.Date|integer -- a date object, or a time value as returned by os.time ----@return string ----@nodiscard -function DateFormat:tostring(d) end - ----force US order in dates like 9/11/2001 ----@param self pl.Date.Format ----@param yesno boolean -- whether US order in dates are forced -function DateFormat:US_order(yesno) end - -Date.Format = DateFormat - -return Date diff --git a/.luacats/pl/List.lua b/.luacats/pl/List.lua deleted file mode 100644 index 018d7dd..0000000 --- a/.luacats/pl/List.lua +++ /dev/null @@ -1,421 +0,0 @@ ----@meta - -local class = require("pl.class") - ----# Class [`pl.List`](https://lunarmodules.github.io/Penlight/classes/pl.List.html) ---- ----Python-style list class. ---- ----**Please Note:** methods that change the list will return the list. This is ----to allow for method chaining, but please note that `ls = ls:sort()` does not ----mean that a new copy of the list is made. In-place (mutable) methods are ----marked as returning 'the list' in this documentation. ---- ----See the Guide for further [discussion](https://lunarmodules.github.io/Penlight/manual/02-arrays.md.html#Python_style_Lists) ---- ----See http://www.python.org/doc/current/tut/tut.html, section 5.1 ---- ----**Note**: The comments before some of the functions are from the Python docs ----and contain Python code. ---- ----Written for Lua version Nick Trout 4.0; Redone for Lua 5.1, Steve Donovan. ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#), ---- [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html#) ----@class pl.List: pl.Class ----@field [integer] any ----@operator concat(pl.List): pl.List ----@overload fun(t?: any[]|pl.List): pl.List -local List = class() - ----Create a new list. Can optionally pass a table; passing another instance of ----`List` will cause a copy to be created; this will return a plain table with ----an appropriate metatable. we pass anything which isn't a simple table to ----`iterate()` to work out an appropriate iterator ----@param self pl.List ----@param t? any[]|pl.List -- An optional list-like table -function List:_init(t) end - ----Create a new list. Can optionally pass a table; passing another instance of ----`List` will cause a copy to be created; this will return a plain table with ----an appropriate metatable. we pass anything which isn't a simple table to ----`iterate()` to work out an appropriate iterator ----@param t? any[]|pl.List -- An optional list-like table ----@return pl.List -- a new List ----@nodiscard -function List.new(t) end - ----Make a copy of an existing list. The difference from a plain 'copy ----constructor' is that this returns the actual `List` subtype. ----@param self pl.List ----@return pl.List ----@nodiscard -function List:clone() end - ----Add an item to the end of the list. ----@param self pl.List ----@param i any -- An item ----@return pl.List self -- the list -function List:append(i) end - ----Extend the list by appending all the items in the given list. ----@param self pl.List ----@param L pl.List -- Another List ----@return pl.List self -- the list -function List:extend(L) end - ----Insert an item at a given position. `i` is the index of the element before which to insert. ----@param self pl.List ----@param i integer -- index of element before which to insert ----@param x any -- A data item ----@return pl.List self -- the list -function List:insert(i, x) end - ----Insert an item at the beginning of the list. ----@param self pl.List ----@param x any -- a data item ----@return pl.List self -- the list -function List:put(x) end - ----Remove an element given its index. (equivalent of Python's del s[i]) ----@param self pl.List ----@param i integer -- the index ----@return pl.List self -- the list -function List:remove(i) end - ----Remove the first item from the list whose value is given. (This is called ----`remove` in Python; renamed to avoid confusion with `table.remove`) Return ----`nil` if there is no such item. ----@param self pl.List ----@param x any -- A data value ----@return pl.List? self -- the list -function List:remove_value(x) end - ----Remove the item at the given position in the list, and return it. If no ----index is specified, `a:pop()` returns the last item in the list. The item is ----also removed from the list. ----@param self pl.List ----@param i? integer -- An index ----@return any -- the item -function List:pop(i) end - ----Return the index in the list of the first item whose value is given. Return ----`nil` if there is no such item. ----@param self pl.List ----@param x any -- A data value ----@param idx? integer -- where to start search (default `1`) ----@return integer? -- the index, or nil if not found. ----@nodiscard -function List:index(x, idx) end - ----Does this list contain the value? ----@param self pl.List ----@param x any -- A data value ----@return boolean -- true or false ----@nodiscard -function List:contains(x) end - ----Return the number of times value appears in the list. ----@param self pl.List ----@param x any -- A data value ----@return integer -- number of times `x` appears ----@nodiscard -function List:count(x) end - ----@param self pl.List ----@param cmp? fun(a: any, b: any): boolean ----@return pl.List self -function List:sort(cmp) end - ----Sort the items of the list, in place. ----@param self pl.List ----@param cmp? pl.BoolBinOpString -- an optional comparison function (default `'<'`) ----@return pl.List self -- the list -function List:sort(cmp) end - ----@param self pl.List ----@param cmp? fun(a: any, b: any): boolean ----@return pl.List ----@nodiscard -function List:sorted(cmp) end - ----Return a sorted copy of this list. ----@param self pl.List ----@param cmp? pl.BoolBinOpString -- an optional comparison function (default `'<'`) ----@return pl.List -- a new list ----@nodiscard -function List:sorted(cmp) end - ----Reverse the elements of the list, in place. ----@param self pl.List ----@return pl.List self -- the list -function List:reverse() end - ----Return the minimum and the maximum value of the list. ----@param self pl.List ----@return any min -- minimum value ----@return any max -- maximum value ----@nodiscard -function List:minmax() end - ----Emulate list slicing, like `list[first:last]` in Python. If `first` or ----`last` are negative then they are relative to the end of the list eg. ----`slice(-2)` gives last 2 entries in a list, and `slice(-4,-2)` gives from -----4th to -2nd ----@param self pl.List ----@param first integer -- An index ----@param last integer -- An index ----@return pl.List -- a new List ----@nodiscard -function List:slice(first, last) end - ----Empty the list. ----@param self pl.List ----@return pl.List self -- the list -function List:clear() end - ----Emulate Python's `range(x)` function. Included in List table for tidiness ----@param start integer -- A number ----@param finish? integer -- A number greater than start; if absent, then start is 1 and finish is start ----@param incr? integer -- an increment (may be less than 1) (default `1`) ----@return pl.List -- a List from start .. finish ----@nodiscard ---- ----Usage: ---- ----```lua ----List.range(0, 3) == List{0, 1, 2, 3} ---- ----List.range(4) = List{1, 2, 3, 4} ---- ----List.range(5, 1, -1) == List{5, 4, 3, 2, 1} ----``` -function List.range(start, finish, incr) end - ----`list:len()` is the same as `#list`. ----@param self pl.List ----@return integer ----@nodiscard -function List:len() end - ----Remove a subrange of elements. equivalent to `del s[i1:i2]` in Python. ----@param self pl.List ----@param i1 integer -- start of range ----@param i2 integer -- end of range ----@return pl.List self -- the list -function List:chop(i1, i2) end - ----Insert a sublist into a list. equivalent to `s[idx:idx] = list` in Python ----@param self pl.List ----@param idx integer -- index ----@param list pl.List -- list to insert ----@return pl.List self -- the list ---- ----Usage: ---- ----```lua ----l = List{10, 20} ----l:splice(2, {21, 22}) ----assert(l == List{10, 21, 22, 20}) ----``` -function List:splice(idx, list) end - ----General slice assignment `s[i1:i2] = seq`. ----@param self pl.List ----@param i1 integer -- start index ----@param i2 integer -- end index ----@param seq pl.List -- a list ----@return pl.List self -- the list -function List:slice_assign(i1, i2, seq) end - ----Join the elements of a list using a delimiter. This method uses `tostring` ----on all elements. ----@param self pl.List ----@param delim? string -- a delimiter string, can be empty (default `""`) ----@return string -- a string ----@nodiscard -function List:join(delim) end - ----Join a list of strings. ---- ----Uses `table.concat` directly. ----@param self pl.List ----@param delim? string -- a delimiter (default `""`) ----@return string -- a string ----@nodiscard -function List:concat(delim) end - ----@param self pl.List ----@param fun fun(value: any) ----@param ... any -function List:foreach(fun, ...) end - ----Call the function on each element of the list. ----@param self pl.List ----@param fun pl.OpString -- a function or callable object ----@param ... any -- optional values to pass to function -function List:foreach(fun, ...) end - ----Call the named method on each element of the list. ----@param self pl.List ----@param name string -- the method name ----@param ... any -- optional values to pass to function -function List:foreachm(name, ...) end - ----@param self pl.List ----@param fun fun(value: any, arg?: any): boolean ----@param arg? any ----@return pl.List ----@nodiscard -function List:filter(fun, arg) end - ----Create a list of all elements which match a function. ----@param self pl.List ----@param fun pl.BoolBinOpString -- a boolean function ----@param arg? any -- optional argument to be passed as second argument of the predicate ----@return pl.List -- a new filtered list. ----@nodiscard -function List:filter(fun, arg) end - ----Split a string using a delimiter. ----@param s string -- the string ----@param delim? string -- the delimiter (default spaces) ----@return pl.List -- a List of strings ----@nodiscard -function List.split(s, delim) end - ----@param self pl.List ----@param fun fun(value: any, ...: any): any ----@param ... any ----@return pl.List ----@nodiscard -function List:map(fun, ...) end - ----Apply a function to all elements. Any extra arguments will be passed to the ----function. ----@param self pl.List ----@param fun pl.OpString -- a function of at least one argument ----@param ... any -- arbitrary extra arguments. ----@return pl.List -- a new list: {f(x) for x in self} ----@nodiscard ---- ----Usage: ---- ----```lua ----List{'one', 'two'}:map(string.upper) == {'ONE', 'TWO'} ----``` -function List:map(fun, ...) end - ----@param self pl.List ----@param fun fun(value: any, ...: any): any ----@param ... any ----@return pl.List self -function List:transform(fun, ...) end - ----Apply a function to all elements, in-place. Any extra arguments are passed ----to the function. ----@param self pl.List ----@param fun pl.OpString -- A function that takes at least one argument ----@param ... any -- arbitrary extra arguments. ----@return pl.List self -- the list. -function List:transform(fun, ...) end - ----@param self pl.List ----@param fun fun(x: any, y: any, ...: any): any ----@param ls pl.List ----@param ... any ----@return pl.List ----@nodiscard -function List:map2(fun, ls, ...) end - ----Apply a function to elements of two lists. Any extra arguments will be ----passed to the function ----@param self pl.List ----@param fun pl.BinOpString -- a function of at least two arguments ----@param ls pl.List -- another list ----@param ... any -- arbitrary extra arguments. ----@return pl.List -- a new list: `{fun(x, y) for x, y in zip(self, ls)}` ----@nodiscard -function List:map2(fun, ls, ...) end - ----apply a named method to all elements. Any extra arguments will be passed to the method. ----@param self pl.List ----@param name string -- name of method ----@param ... any -- extra arguments ----@return pl.List -- a new list of the results ----@nodiscard -function List:mapm(name, ...) end - ----@param self pl.List ----@param fun fun(memo: any, val: any): any ----@return any ----@nodiscard -function List:reduce(fun) end - ----'reduce' a list using a binary function. ----@param self pl.List ----@param fun pl.BinOpString -- a function of two arguments ----@return any -- result of the function ----@nodiscard -function List:reduce(fun) end - ----@param self pl.List ----@param fun fun(val: any, ...: any): any ----@param ... any ----@return pl.MultiMap ----@nodiscard -function List:partition(fun, ...) end - ----Partition a list using a classifier function. The function may return nil, ----but this will be converted to the string key `""`. ----@param self pl.List ----@param fun pl.OpString -- a function of at least one argument ----@param ... any -- will also be passed to the function ----@return pl.MultiMap -- a table where the keys are the returned values, and the values are Lists of values where the function returned that key. ----@nodiscard -function List:partition(fun, ...) end - ----return an iterator over all values. ----@param self pl.List ----@return fun(): any ----@nodiscard -function List:iter() end - ----Create an iterator over a seqence. This captures the Python concept of ----'sequence'. For tables, iterates over all values with integer indices. ----@param seq pl.Sequence|string|table|file*|(fun(): any) -- a sequence; a string (over characters), a table, a file object (over lines) or an iterator function ----@return fun(): any ----@nodiscard ---- ----Usage: ---- ----```lua ----for x in iterate {1,10,22,55} do io.write(x,',') end --> 1,10,22,55 ---- ----for ch in iterate 'help' do io.write(ch,' ') end --> h e l p ----``` -function List.iterate(seq) end - ----Concatenation operator. ----@param self pl.List ----@param L pl.List -- another List ----@return pl.List -- a new list consisting of the list with the elements of the new list appended ----@nodiscard -function List:__concat(L) end - ----Equality operator `==`. True iff all elements of two lists are equal. ----@param self pl.List ----@param L pl.List -- another List ----@return boolean ----@nodiscard -function List:__eq(L) end - ----How our list should be rendered as a string. Uses `List:join()`. ----@param self pl.List ----@return string ----@nodiscard -function List:__tostring() end - -return List diff --git a/.luacats/pl/Map.lua b/.luacats/pl/Map.lua deleted file mode 100644 index cb1042d..0000000 --- a/.luacats/pl/Map.lua +++ /dev/null @@ -1,100 +0,0 @@ -local class = require("pl.class") - ----@meta ----# Class [`pl.Map`](https://lunarmodules.github.io/Penlight/classes/pl.Map.html) ---- ----A Map class. ---- ----```lua ----> Map = require 'pl.Map' ----> m = Map{one=1,two=2} ----> m:update {three=3,four=4,two=20} ----> = m == M{one=1,two=20,three=3,four=4} ----true ----``` ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#), ---- [`pl.pretty`](https://lunarmodules.github.io/Penlight/libraries/pl.pretty.html#) ----@class pl.Map : pl.Class ----@overload fun(t?: pl.Map|pl.Set): pl.Map -local Map = class() - ----list of keys. ----@param self pl.Map ----@return any[] ----@nodiscard -function Map:keys() end - ----list of values. ----@param self pl.Map ----@return any[] ----@nodiscard -function Map:values() end - ----return an iterator over all key-value pairs. ----@param self pl.Map ----@return fun(): (any, any) ----@nodiscard -function Map:iter() end - ----return a List of all key-value pairs, sorted by the keys. ----@param self pl.Map ----@return pl.List ----@nodiscard -function Map:items() end - ----set a value in the map if it doesn't exist yet. ----@param self pl.Map ----@param key any -- the key ----@param default any -- value to set ----@return any -- the value stored in the map (existing value, or the new value) -function Map:setdefault(key, default) end - ----size of map. note: this is a relatively expensive operation! ----@param self pl.Map ----@return integer ----@nodiscard -function Map:len() end - ----put a value into the map. This will remove the key if the value is nil ----@param self pl.Map ----@param key any -- the key ----@param val any -- the value -function Map:set(key, val) end - ----get a value from the map. ----@param self pl.Map ----@param key any -- the key ----@return any val -- the value, or `nil` if not found. ----@nodiscard -function Map:get(key) end - ----get a list of values indexed by a list of keys. ----@param self pl.Map ----@param keys pl.List -- a list-like table of keys ----@return pl.List values -- a new list ----@nodiscard -function Map:getvalues(keys) end - ----update the map using key/value pairs from another table. ----@param self pl.Map ----@param table pl.Map|table -function Map:update(table) end - ----equality between maps. ----@param self pl.Map ----@param m pl.Map -- another map. ----@return boolean ----@nodiscard -function Map:__eq(m) end - ----string representation of a map. ----@param self pl.Map ----@return string ----@nodiscard -function Map:__tostring() end - -return Map diff --git a/.luacats/pl/MultiMap.lua b/.luacats/pl/MultiMap.lua deleted file mode 100644 index 23c7202..0000000 --- a/.luacats/pl/MultiMap.lua +++ /dev/null @@ -1,31 +0,0 @@ -local class = require("pl.class") - ----@meta ----# Class [`pl.MultiMap`](https://lunarmodules.github.io/Penlight/classes/pl.MultiMap.html) ---- ----`MultiMap`, a `Map` which has multiple values per key. ---- ----Derived from [`pl.Map`](https://lunarmodules.github.io/Penlight/classes/pl.Map.html#). ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html#), ---- [`pl.List`](https://lunarmodules.github.io/Penlight/classes/pl.List.html#), ---- [`pl.Map`](https://lunarmodules.github.io/Penlight/classes/pl.Map.html#) ----@class pl.MultiMap : pl.Map ----@field [any] any[] ----@overload fun(t?: pl.MultiMap): pl.MultiMap -local MultiMap = class() - ----update a MultiMap using a table. ----@param self pl.MultiMap ----@param t pl.MultiMap|pl.Map|{ [any]: any[] } -- either a Multimap or a map-like table. -function MultiMap:update(t) end - ----add a new value to a key. Setting a `nil` value removes the key. ----@param self pl.MultiMap ----@param key any -- the key ----@param val any -- the value -function MultiMap:set(key, val) end - -return MultiMap diff --git a/.luacats/pl/OrderedMap.lua b/.luacats/pl/OrderedMap.lua deleted file mode 100644 index b30a81f..0000000 --- a/.luacats/pl/OrderedMap.lua +++ /dev/null @@ -1,90 +0,0 @@ ----@meta - -local class = require("pl.class") - ----# Class [`pl.OrderedMap`](https://lunarmodules.github.io/Penlight/classes/pl.OrderedMap.html) ---- ----`OrderedMap`, a `Map` which preserves ordering. ---- ----Derived from [`pl.Map`](https://lunarmodules.github.io/Penlight/classes/pl.Map.html#). ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#), ---- [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html#), ---- [`pl.List`](https://lunarmodules.github.io/Penlight/classes/pl.List.html#), ---- [`pl.Map`](https://lunarmodules.github.io/Penlight/classes/pl.Map.html#) ----@class pl.OrderedMap : pl.Map ----@overload fun(t?: {[any]: any}|{[any]: any}[]|pl.OrderedMap): pl.OrderedMap -local OrderedMap = class() - ----construct an `OrderedMap`. Will throw an error if the argument is bad. ----@param self pl.OrderedMap ----@param t? {[any]: any}|{[any]: any}[]|pl.OrderedMap -- optional initialization table, same as for `OrderedMap:update` -function OrderedMap:_init(t) end - ----update an `OrderedMap` using a table. If the table is itself an ----`OrderedMap`, then its entries will be appended. if it is a table of the ----form `{{key1 = val1}, {key2 = val2}, ...}` these will be appended. ----@param self pl.OrderedMap ----@param t {[any]: any}|{[any]: any}[]|pl.OrderedMap ----@return pl.OrderedMap? self -- the map, or `nil` in case of error ----@return string? error_message -- the error message -function OrderedMap:update(t) end - ----set the key's value. This key will be appended at the end of the map. ---- ----If the value is nil, then the key is removed. ----@param self pl.OrderedMap ----@param key any -- the key ----@param val any -- the value ----@return pl.OrderedMap self -- the map -function OrderedMap:set(key, val) end - -OrderedMap.__newindex = OrderedMap.set - ----insert a key/value pair before a given position. Note: if the map already ----contains the key, then this effectively moves the item to the new position ----by first removing at the old position. Has no effect if the key does not ----exist and val is `nil` ----@param self pl.OrderedMap ----@param pos integer -- a position starting at 1 ----@param key any -- the key ----@param val any -- the value; if `nil` use the old value ----@return pl.OrderedMap self -function OrderedMap:insert(pos, key, val) end - ----return the keys in order. (Not a copy!) ----@param self pl.OrderedMap ----@return pl.List ----@nodiscard -function OrderedMap:keys() end - ----return the values in order. this is relatively expensive. ----@param self pl.OrderedMap ----@return pl.List ----@nodiscard -function OrderedMap:values() end - ----sort the keys. ----@param self pl.OrderedMap ----@param cmp? fun(key1: any, key2: any): boolean -- a comparison function as for `table.sort` ----@return pl.OrderedMap self -function OrderedMap:sort(cmp) end - ----iterate over key-value pairs in order. ----@param self pl.OrderedMap ----@return fun(): (any, any) ----@nodiscard -function OrderedMap:iter() end - ----iterate over an ordered map (5.2). -OrderedMap.__pairs = OrderedMap.iter - ----string representation of an ordered map. ----@param self pl.OrderedMap ----@return string ----@nodiscard -function OrderedMap:__tostring() end - -return OrderedMap diff --git a/.luacats/pl/Set.lua b/.luacats/pl/Set.lua deleted file mode 100644 index c18b834..0000000 --- a/.luacats/pl/Set.lua +++ /dev/null @@ -1,194 +0,0 @@ -local class = require("pl.class") - ----@meta ----# Class [`pl.Set`](https://lunarmodules.github.io/Penlight/classes/pl.Set.html) ---- ----A Set class. ---- ----```lua ----> Set = require 'pl.Set' ----> = Set{'one','two'} == Set{'two','one'} ----true ----> fruit = Set{'apple','banana','orange'} ----> = fruit['banana'] ----true ----> = fruit['hazelnut'] ----nil ----> colours = Set{'red','orange','green','blue'} ----> = fruit,colours ----[apple,orange,banana] [blue,green,orange,red] ----> = fruit+colours ----[blue,green,apple,red,orange,banana] ----[orange] ----> more_fruits = fruit + 'apricot' ----> = fruit*colours ---- = more_fruits, fruit ----banana,apricot,apple,orange] [banana,apple,orange] ----``` ---- ----Dependencies: ---- ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#), ---- [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html#), ---- [`pl.Map`](https://lunarmodules.github.io/Penlight/classes/pl.Map.html#), ---- ([`pl.List`](https://lunarmodules.github.io/Penlight/classes/pl.List.html#) if `__tostring` is used) ----@class pl.Set.Class : pl.Map ----@overload fun(t?: any[]|pl.List|pl.Set|pl.Map): pl.Set -local Set = class() - ----@class pl.Set ----@operator add(any): pl.Set ----@operator mul(pl.Set): pl.Set ----@operator sub(any): pl.Set ----@operator pow(pl.Set): pl.Set ----@operator len: integer - ----create a set. ----@param self pl.Set ----@param t? any[]|pl.List|pl.Set|pl.Map -- may be a Set, Map or list-like table. -function Set:_init(t) end - ----get a list of the values in a set. ----@param self pl.Set ----@return pl.List -- a list ----@nodiscard -function Set.values(self) end - ----@param self pl.Set ----@param fn fun(val: any, ...: any): any ----@param ... any ----@return pl.Set ----@nodiscard -function Set.map(self, fn, ...) end - ----map a function over the values of a set. ----@param self pl.Set ----@param fn pl.OpString -- a function ----@param ... any -- extra arguments to pass to the function. ----@return pl.Set -- a new set ----@nodiscard -function Set.map(self, fn, ...) end - ----union of two sets (also `+`). ----@param self pl.Set ----@param set pl.Set -- another set ----@return pl.Set -- a new set ----@nodiscard -function Set.union(self, set) end - ----intersection of two sets (also `*`). ----@param self pl.Set ----@param set pl.Set -- another set ----@return pl.Set -- a new set ----@nodiscard ---- ----Usage: ---- ----```lua ----> s = Set{10, 20, 30} ----> t = Set{20, 30, 40} ----> = t ----[20,30,40] ----> = Set.intersection(s, t) ----[30,20] ----> = s*t ----[30,20] ----``` -function Set.intersection(self, set) end - ----a new set with elements in *either* one set *or* other but not both (also `^`). ----@param self pl.Set ----@param set pl.Set -- another set ----@return pl.Set -- a new set -function Set.symmetric_difference(self, set) end - ----new set with elements in the set that are not in the other (also `-`). ----@param self pl.Set ----@param set pl.Set -- another set ----@return pl.Set -- a new set ----@nodiscard -function Set.difference(self, set) end - ----is the first set a subset of the second (also `<`)? ----@param self pl.Set ----@param set pl.Set -- another set ----@return boolean ----@nodiscard -function Set.issubset(self, set) end - ----is the set empty? ----@param self pl.Set ----@return boolean ----@nodiscard -function Set.isempty(self) end - ----are the sets disjoint (no elements in common)? Uses naive definition, i.e. ----that intersection is empty ----@param self pl.Set ----@param set pl.Set -- another set ----@return boolean ----@nodiscard -function Set.isdisjoint(self, set) end - ----size of this set (also `#` for 5.2). ----@param self pl.Set ----@return integer size ----@nodiscard -function Set.len(self) end - ----string representation of a set. ----@param self pl.Set ----@return string ----@nodiscard -function Set.__tostring(self) end - ----union of sets. ----@param self pl.Set ----@param set pl.Set ----@return pl.Set ----@nodiscard -function Set.__add(self, set) end - ----intersection of sets. ----@param self pl.Set ----@param set pl.Set ----@return pl.Set ----@nodiscard -function Set.__mul(self, set) end - ----difference of sets. ----@param self pl.Set ----@param set pl.Set ----@return pl.Set ----@nodiscard -function Set.__sub(self, set) end - ----symmetric difference of sets. ----@param self pl.Set ----@param set pl.Set ----@return pl.Set ----@nodiscard -function Set.__pow(self, set) end - ----first set subset of second? ----@param self pl.Set ----@param set pl.Set ----@return boolean ----@nodiscard -function Set.__lt(self, set) end - ----cardinality of set (5.2). ----@param self pl.Set ----@return integer ----@nodiscard -function Set.__len(self, set) end - ----equality between sets. ----@param self pl.Set ----@param set pl.Set ----@return boolean ----@nodiscard -function Set.__eq(self, set) end - -return Set diff --git a/.luacats/pl/app.lua b/.luacats/pl/app.lua deleted file mode 100644 index ed9927f..0000000 --- a/.luacats/pl/app.lua +++ /dev/null @@ -1,128 +0,0 @@ ----@meta ----# Module [`pl.app`](https://lunarmodules.github.io/Penlight/libraries/pl.app.html) ---- ----Application support functions. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/01-introduction.md.html#Application_Support). ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html), ---- [`pl.path`](https://lunarmodules.github.io/Penlight/libraries/pl.path.html) -local app = {} - ----Return the name of the current script running. ----The name will be the name as passed on the command line ----@return string -- filename ----@nodiscard -function app.script_name() end - ----Prefixes the current script's path to the Lua module path. Applies to both ----the source and the binary module paths. It makes it easy for the main file ----of a multi-file program to access its modules in the same directory. base ----allows these modules to be put in a specified subdirectory, to allow for ----cleaner deployment and resolve potential conflicts between a script name ----and its library directory. ---- ----Note: the path is prefixed, so it is searched first when requiring modules. ----@param base string -- optional base directory (absolute, or relative path). ----@param nofollow boolean -- always use the invocation's directory, even if the invoked file is a symlink ----@return string -- the current script's path with a trailing slash -function app.require_here(base, nofollow) end - ----Return a suitable path for files private to this application. These will ----look like '\~/.SNAME/file', with '\~' as with expanduser and SNAME is the ----name of the script without .lua extension. If the directory does not exist, ----it will be created. ----@param file string -- a filename (w/out path) ----@return string? -- a full pathname, or nil ----@return string? -- cannot create directory error ----@nodiscard ---- ----Usage: ---- ----```lua ------ when run from a script called 'testapp' (on Windows): ----local app = require 'pl.app' ----print(app.appfile 'test.txt') ------ C:\Documents and Settings\steve\.testapp\test.txt ----``` -function app.appfile(file) end - ----Return string indicating operating system. ----@return string -- \'Windows', 'OSX' whatever uname returns (e.g. 'Linux') ----@nodiscard -function app.platform() end - ----Return the full command-line used to invoke this script. It will not ----include the scriptname itself. ----@see app.script_name ----@return string -- command-line ----@return string -- name of Lua program used ----@nodiscard ---- ----Usage: ---- ----```lua ------ execute: lua -lluacov -e 'print(_VERSION)' myscript.lua ---- ------ myscript.lua ----print(require("pl.app").lua()) --> "lua -lluacov -e 'print(_VERSION)'", "lua" ----``` -function app.lua() end - ----parse command-line arguments into flags and parameters. Understands ----GNU-style command-line flags; short (-f) and long (--flag). ---- ----These may be given a value with either '=' or ':' (-k:2,--alpha=3.2,-n2), a ----number value can be given without a space. If the flag is marked as having ----a value, then a space-separated value is also accepted (-i hello), see the ----flags_with_values argument. ---- ----Multiple short args can be combined like so: ( -abcd). ---- ----When specifying the flags_valid parameter, its contents can also contain ----aliasses, to convert short/long flags to the same output name. See the ----example below. ---- ----Note: if a flag is repeated, the last value wins. ----@param args string[] -- an array of strings (default is the global `arg`). ----@param flags_with_values table -- any flags that take values, either list or hash table e.g. `{ out=true }` or `{ "out" }`. ----@param flags_valid table -- flags that are valid, either list or hashtable. If not given, everything will be accepted(everything in flags_with_values will automatically be allowed). ----@return table -- a table of flags (flag=value pairs) ----@return table -- an array of parameters ----@nodiscard ---- ----Usage: ---- ----```lua ------ Simple form: ----local flags, params = app.parse_args(nil, ---- { "hello", "world" }, -- list of flags taking values ---- { "l", "a", "b"}) -- list of allowed flags (value ones will be added) ---- ------ More complex example using aliasses: ----local valid = { ---- long = "l", -- if 'l' is specified, it is reported as 'long' ---- new = { "n", "old" }, -- here both 'n' and 'old' will go into 'new' ----} ----local values = { ---- "value", -- will automatically be added to the allowed set of flags ---- "new", -- will mark 'n' and 'old' as requiring a value as well ----} ----local flags, params = app.parse_args(nil, values, valid) ---- ------ command: myapp.lua -l --old:hello --value world param1 param2 ------ will yield: ----flags = { ---- long = true, -- input from 'l' ---- new = "hello", -- input from 'old' ---- value = "world", -- allowed because it was in 'values', note: space separated! ----} ----params = { ---- [1] = "param1" ---- [2] = "param2" ----} ----``` -function app.parse_args(args, flags_with_values, flags_valid) end - -return app diff --git a/.luacats/pl/array2d.lua b/.luacats/pl/array2d.lua deleted file mode 100644 index 6f9840f..0000000 --- a/.luacats/pl/array2d.lua +++ /dev/null @@ -1,325 +0,0 @@ ----@meta - ----# Module [`pl.array2d`](https://lunarmodules.github.io/Penlight/libraries/pl.array2d.html) ---- ----Operations on two-dimensional arrays. ---- ----See [The Guide](https://lunarmodules.github.io/Penlight/manual/02-arrays.md.html#Operations_on_two_dimensional_tables) ---- ----The size of the arrays is determined by using the length operator # hence the ----module is not nil safe, and the usual precautions apply. ---- ----Note: all functions taking i1,j1,i2,j2 as arguments will normalize the arguments using `array2d.default_range`. ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#), ---- [`pl.types`](https://lunarmodules.github.io/Penlight/libraries/pl.types.html#) -local array2d = {} - ----return the row and column size. Size is calculated using the Lua length ----operator #, so usual precautions regarding nil values apply. ----@param a any[][] -- a 2d array ----@return integer -- number of rows (`#a`) ----@return integer -- number of cols (`#a[1]`) ----@nodiscard -function array2d.size(a) end - ----extract a column from the 2D array. ----@generic T ----@param a T[][] -- 2d array ----@param j integer -- column index ----@return T[] -- 1d array ----@nodiscard -function array2d.column(a, j) end - ----extract a row from the 2D array. Added in line with column, for read-only ----purposes directly accessing `a[i]` is more performant. ----@generic T ----@param a T[][] -- 2d array ----@param i integer -- row index ----@return T[] -- 1d array (copy of the row) ----@nodiscard -function array2d.row(a, i) end - ----@generic T, A, R ----@param f fun(value: T, arg: A): R ----@param a T[][] ----@param arg A ----@return R[][] ----@nodiscard -function array2d.map(f, a, arg) end - ----map a function over a 2D array ----@param f pl.OpString -- a function of at least one argument ----@param a any[][] -- 2d array ----@param arg any -- an optional extra argument to be passed to the function. ----@return any[][] -- 2d array ----@nodiscard -function array2d.map(f, a, arg) end - ----reduce the rows using a function. ----@generic T ----@param f fun(value: T, memo: T): T -- a binary function ----@param a T[][] -- 2d array ----@return T[] -- 1d array ----@nodiscard -function array2d.reduce_rows(f, a) end - ----reduce the columns using a function. ----@generic T ----@param f fun(value: T, memo: T): T -- a binary function ----@param a T[][] -- 2d array ----@return T[] -- 1d array ----@nodiscard -function array2d.reduce_cols(f, a) end - ----reduce a 2D array into a scalar, using two operations. ----@generic T ----@param opc fun(value: T, memo: T): T -- operation to reduce the final result ----@param opr fun(value: T, memo: T): T -- operation to reduce the rows ----@param a T[][] -- 2D array ----@return T ----@nodiscard -function array2d.reduce2(opc, opr, a) end - ----@generic T, U, R ----@param f fun(aval: T, bval: U): R ----@param ad 1 | 2 ----@param bd 1 | 2 ----@param a T[]|T[][] ----@param b U[]|U[][] ----@param arg any ----@return R[]|R[][] ----@nodiscard -function array2d.map2(f, ad, bd, a, b, arg) end - ----map a function over two arrays. They can be both or either 2D arrays ----@param f pl.UnOpString|pl.BinOpString -- function of at least two arguments ----@param ad 1 | 2 -- order of first array (`1` if `a` is a list/array, `2` if it is a 2d array) ----@param bd 1 | 2 -- order of second array (`1` if `b` is a list/array, `2` if it is a 2d array) ----@param a any[]|any[][] -- 1d or 2d array ----@param b any[]|any[][] -- 1d or 2d array ----@param arg any -- optional extra argument to pass to function ----@return any[]|any[][] -- 2D array, unless both arrays are 1D ----@nodiscard -function array2d.map2(f, ad, bd, a, b, arg) end - ----@generic T, U, R ----@param f fun(val1: T, val2: U): R ----@param t1 T[] ----@param t2 U[] ----@return R[][] -function array2d.product(f, t1, t2) end - ----cartesian product of two 1d arrays. ----@param f pl.BinOpString -- a function of 2 arguments ----@param t1 any[] -- a 1d table ----@param t2 any[] -- a 1d table ----@return any[][] -- 2d table ----@nodiscard ---- ----Usage: ---- ----```lua ----product('..',{1,2},{'a','b'}) == {{'1a','2a'},{'1b','2b'}} ----``` -function array2d.product(f, t1, t2) end - ----flatten a 2D array. (this goes over columns first.) ----@generic T ----@param t T[][] -- 2d table ----@return T[] -- a 1d table ----@nodiscard ---- ----Usage: ---- ----```lua ----flatten {{1,2},{3,4},{5,6}} == {1,2,3,4,5,6} ----``` -function array2d.flatten(t) end - ----reshape a 2D array. Reshape the array by specifying a new number of rows. ----@generic T ----@param t T[][] -- 2d array ----@param nrows integer -- new number of rows ----@param co? boolean -- use column-order (Fortran-style) (default false) ----@return T[][] -- a new 2d array ----@nodiscard -function array2d.reshape(t, nrows, co) end - ----transpose a 2D array. ----@generic T ----@param t T[][] -- 2d array ----@return T[][] -- a new 2d array ----@nodiscard -function array2d.transpose(t) end - ----swap two rows of an array. ----@generic T ----@param t T[][] -- a 2d array ----@param i1 integer -- a row index ----@param i2 integer -- a row index ----@return T[][] t -- (same, modified 2d array) -function array2d.swap_rows(t, i1, i2) end - ----swap two columns of an array. ----@generic T ----@param t T[][] -- a 2d array ----@param j1 integer -- a column index ----@param j2 integer -- a column index ----@return T[][] t -- (same, modified 2d array) -function array2d.swap_cols(t, j1, j2) end - ----extract the specified rows. ----@generic T ----@param t T[][] -- 2d array ----@param ridx integer[] -- a table of row indices ----@return T[][] -- a new 2d array with the extracted rows ----@nodiscard -function array2d.extract_rows(t, ridx) end - ----extract the specified columns. ----@generic T ----@param t T[][] -- 2d array ----@param cidx integer[] -- a table of column indices ----@return T[][] -- a new 2d array with the extracted columns ----@nodiscard -function array2d.extract_cols(t, cidx) end - ----remove a row from an array. ----@generic T ----@param t T[][] -- a 2d array ----@param i integer -- a row index -function array2d.remove_row(t, i) end - ----remove a column from an array. ----@generic T ----@param t T[][] -- a 2d array ----@param j integer -- a column index -function array2d.remove_col(t, j) end - ----parse a spreadsheet range or cell. The range/cell can be specified either ----as 'A1:B2' or 'R1C1:R2C2' or for single cells as 'A1' or 'R1C1'. ----@param s string -- a range (case insensitive). ----@return integer -- start row ----@return integer -- start col ----@return integer -- end row (or nil if the range was a single cell) ----@return integer -- end col (or nil if the range was a single cell) ----@nodiscard -function array2d.parse_range(s) end - ----get a slice of a 2D array. Same as `array2d.slice`. ----@generic T ----@param t T[][] -- a 2D array ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) ----@return T[]|T[][] -- an array, 2D in general but 1D in special cases. ----@nodiscard -function array2d.range(t, i1, j1, i2, j2) end - ----normalizes coordinates to valid positive entries and defaults. Negative indices ----will be counted from the end, too low, or too high will be limited by the array sizes. ----@param t any[][] -- a 2D array ----@param i1? integer|string -- start row or spreadsheet range passed to `array2d.parse_range` (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) ----@return integer i1, integer j1, integer i2, integer j2 ----@nodiscard -function array2d.default_range(t, i1, j1, i2, j2) end - ----get a slice of a 2D array. Note that if the specified range has a 1D result, ----the rank of the result will be 1. ----@generic T ----@param t T[][] -- a 2D array ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) ----@return T[]|T[][] -- an array, 2D in general but 1D in special cases. ----@nodiscard -function array2d.slice(t, i1, j1, i2, j2) end - ----set a specified range of an array to a value. ----@generic T ----@param t T[][] -- a 2D array ----@param value T|(fun(i: integer, j: integer): T) -- the value (may be a function, called as `val(i, j)`) ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) -function array2d.set(t, value, i1, j1, i2, j2) end - ----write a 2D array to a file. ----@param t any[][] 2D array ----@param f? file* -- a file object (default `stdout`) ----@param fmt string -- a format string (default is just to use tostring) ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) -function array2d.write(t, f, fmt, i1, j1, i2, j2) end - ----perform an operation for all values in a 2D array. ----@generic T ----@param t T[][] -- 2D array ----@param row_op fun(row: T[], j: integer) -- function to call on each value; `row_op(row, j)` ----@param end_row_op? fun(i: integer) -- function to call at end of each row; `end_row_op(i)` ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) -function array2d.forall(t, row_op, end_row_op, i1, j1, i2, j2) end - ----move a block from the destination to the source. ----@generic T ----@param dest T[][] -- a 2D array ----@param di integer -- start row in dest ----@param dj integer -- start col in dest ----@param src T[][] -- a 2D array ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) -function array2d.move(dest, di, dj, src, i1, j1, i2, j2) end - ----iterate over all elements in a 2D array, with optional indices. ----@generic T ----@param a T[][] -- a 2D array ----@param indices? boolean -- with indices (default false) ----@param i1? integer|string -- start row or spreadsheet range passed to parse_range (default 1) ----@param j1? integer -- start col (default 1) ----@param i2? integer -- end row (default N) ----@param j2? integer -- end col (default M) ----@return (fun(): integer, integer, T)|(fun(): T) -- returns either value or i,j,value depending on the value of indices ----@nodiscard -function array2d.iter(a, indices, i1, j1, i2, j2) end - ----iterate over all columns. ----@generic T ----@param a T[][] -- a 2D array ----@return (fun(): T[], T) -- returns column, column-index ----@nodiscard -function array2d.columns(a) end - ----iterate over all rows. Returns a copy of the row, for read-only purposes ----directly iterating is more performant; `ipairs(a)` ----@generic T ----@param a T[][] -- a 2D array ----@return (fun(): T[], T) -- returns row, row-index ----@nodiscard -function array2d.rows(a) end - ----new array of specified dimensions ----@generic T ----@param rows integer -- number of rows ----@param cols integer -- number of cols ----@param val (fun(i: integer, j: integer): T)|T -- initial value; if it's a function then use `val(i,j)` ----@return T[][] -- new 2d array ----@nodiscard -function array2d.new(rows, cols, val) end - -return array2d diff --git a/.luacats/pl/class.lua b/.luacats/pl/class.lua deleted file mode 100644 index 8d72495..0000000 --- a/.luacats/pl/class.lua +++ /dev/null @@ -1,56 +0,0 @@ ----@meta ----# Module [`pl.class`](https://lunarmodules.github.io/Penlight/libraries/pl.class.html) ---- ----Provides a reuseable and convenient framework for creating classes in Lua. ---- ----Two possible notations: ---- ----```lua ----B = class(A) ----class.B(A) ----``` ----The latter form creates a named class within the current environment. Note ----that this implicitly brings in [pl.utils](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html) as a dependency. ---- ----See the Guide for further [discussion](https://lunarmodules.github.io/Penlight/manual/01-introduction.md.html#Simplifying_Object_Oriented_Programming_in_Lua) ----@class pl.ClassModule ----@operator call(pl.Class?): pl.Class -local class = {} - ----@class pl.Class ----@operator call(...): pl.Instance -local Class = {} - ----initializes an instance upon creation. ----@param ... any -- parameters passed to the constructor -function Class._init(...) end - ----checks whether an instance is derived from this class. Works the other way around as `is_a`. ----@param some_instance pl.Instance ----@return boolean -- true if `some_instance` is derived from this class ----@nodiscard -function class:class_of(some_instance) end - ----cast an object to another class. It is not clever (or safe!) so use ----carefully. ----@generic T: pl.Class ----@param self T ----@param some_instance pl.Instance -- the object to be changed -function class:cast(some_instance) end - ----@class pl.Instance -local Instance = {} - ----checks whether an instance is derived from some class. Works the other way ----around as class_of. It has two ways of using; 1) call with a class to check ----against, 2) call without params. ----@param some_class pl.Class -- class to check against, or `nil` to return the class ----@return boolean -- `true` if instance is derived from some_class ----@nodiscard -function Instance:is_a(some_class) end - ----@return pl.Class ----@nodiscard -function Instance:is_a() end - -return class diff --git a/.luacats/pl/compat.lua b/.luacats/pl/compat.lua deleted file mode 100644 index 0072a9b..0000000 --- a/.luacats/pl/compat.lua +++ /dev/null @@ -1,66 +0,0 @@ ----@meta ----# Module [`pl.compat`](https://lunarmodules.github.io/Penlight/libraries/pl.compat.html) ---- ----Lua 5.1/5.2/5.3 compatibility. ---- ----Injects `table.pack`, `table.unpack`, and `package.searchpath` in the global ----environment, to make sure they are available for Lua 5.1 and LuaJIT. ---- ----All other functions are exported as usual in the returned module table. ---- ----NOTE: everything in this module is also available in pl.utils. -local compat = { - - ---boolean flag this is Lua 5.1 (or LuaJIT). - lua51 = _VERSION == "Lua 5.1", - - ---boolean flag this is LuaJIT. - jit = (tostring(assert):match("builtin") ~= nil), - - ---boolean flag this is LuaJIT with 5.2 compatibility compiled in. - jit52 = not loadstring("local goto = 1"), - - ---the directory separator character for the current platform. - dir_separator = _G.package.config:sub(1, 1), -} - ----boolean flag this is a Windows platform. -compat.is_windows = compat.dir_separator == "\\" - ----execute a shell command, in a compatible and platform independent way. This ----is a compatibility function that returns the same for Lua 5.1 and Lua 5.2+. ---- ----NOTE: Windows systems can use signed 32bit integer exitcodes. Posix systems ----only use exitcodes 0-255, anything else is undefined. ---- ----NOTE2: In Lua 5.2 and 5.3 a Windows exitcode of -1 would not properly be ----returned, this function will return it properly for all versions. ----@param cmd string -- a shell command ----@return boolean -- true if successful ----@return integer -- actual return code -function compat.execute(cmd) end - ----Load Lua code as a text or binary chunk (in a Lua 5.2 compatible way). ----@param ld string -- code string or loader ----@param source? string -- name of chunk for errors (optional) ----@param mode? "b"|"t"|"bt" -- \'b', 't' or 'bt' (optional) ----@param env? table -- environment to load the chunk in (optional) ----@return function?, string? ----@nodiscard -function compat.load(ld, source, mode, env) end - ----Get environment of a function (in a Lua 5.1 compatible way). Not 100% ----compatible, so with Lua 5.2 it may return nil for a function with no global ----references! Based on code by [Sergey Rozhenko](http://lua-users.org/lists/lua-l/2010-06/msg00313.html) ----@param f function|integer -- a function or a call stack reference ----@return table? ----@nodiscard -function compat.getfenv(f) end - ----Set environment of a function (in a Lua 5.1 compatible way). ----@param f function|integer -- a function or a call stack reference ----@param env table -- a table that becomes the new environment for `f` ----@return function? -function compat.setfenv(f, env) end - -return compat diff --git a/.luacats/pl/comprehension.lua b/.luacats/pl/comprehension.lua deleted file mode 100644 index 31764c2..0000000 --- a/.luacats/pl/comprehension.lua +++ /dev/null @@ -1,47 +0,0 @@ ----@meta ----# Module [`pl.comprehension`](https://lunarmodules.github.io/Penlight/libraries/pl.comprehension.html) ---- ----List comprehensions implemented in Lua. ---- ----See the [wiki page](http://lua-users.org/wiki/ListComprehensions) ---- ----```lua ----local C= require 'pl.comprehension' . new() ---- ----C ('x for x=1,10') () ----==> {1,2,3,4,5,6,7,8,9,10} ----C 'x^2 for x=1,4' () ----==> {1,4,9,16} ----C '{x,x^2} for x=1,4' () ----==> {{1,1},{2,4},{3,9},{4,16}} ----C '2*x for x' {1,2,3} ----==> {2,4,6} ----dbl = C '2*x for x' ----dbl {10,20,30} ----==> {20,40,60} ----C 'x for x if x % 2 == 0' {1,2,3,4,5} ----==> {2,4} ----C '{x,y} for x = 1,2 for y = 1,2' () ----==> {{1,1},{1,2},{2,1},{2,2}} ----C '{x,y} for x for y' ({1,2},{10,20}) ----==> {{1,10},{1,20},{2,10},{2,20}} ----assert(C 'sum(x^2 for x)' {2,3,4} == 2^2+3^2+4^2) ----``` ---- ----(c) 2008 David Manura. Licensed under the same terms as Lua (MIT license). ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.luabalanced`](https://lunarmodules.github.io/Penlight/libraries/pl.luabalanced.html#) ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/07-functional.md.html#List_Comprehensions) ----@class pl.Comprehension ----@operator call(string): any -local comprehension = {} - ----@param env? table -- defaults to caller of `comprehension.new` ----@return fun(expr: string): fun(list?: any[]):any ----@nodiscard -function comprehension.new(env) end - -return comprehension diff --git a/.luacats/pl/config.lua b/.luacats/pl/config.lua deleted file mode 100644 index 7fc55c8..0000000 --- a/.luacats/pl/config.lua +++ /dev/null @@ -1,65 +0,0 @@ ----@meta ----# Module [`pl.config`](https://lunarmodules.github.io/Penlight/libraries/pl.config.html) ---- ----Reads configuration files into a Lua table. ---- ----Understands INI files, classic Unix config files, and simple delimited ----columns of values. See [the Guide](https://lunarmodules.github.io/Penlight/manual/06-data.md.html#Reading_Configuration_Files) ---- ----`test.config` ---- ----```ini ----# Read timeout in seconds ----read.timeout=10 ----# Write timeout in seconds ----write.timeout=5 ----#acceptable ports ----ports = 1002,1003,1004 ----``` ---- ----`readconfig.lua` ---- ----```lua ----local config = require 'config' ----local t = config.read 'test.config' ----print(pretty.write(t)) ---- ------ output ----{ ---- ports = { ---- 1002, ---- 1003, ---- 1004 ---- }, ---- write_timeout = 5, ---- read_timeout = 10 ----} ----``` -local config = {} - ----like `io.lines()`, but allows for lines to be continued with `"`. ----@param file { read: fun(): string } -- a file-like object (anything where read() returns the next line) or a filename. Defaults to stardard input. ----@return (fun(): string)? -- an iterator over the lines, or `nil` ----@return string? -- error 'not a file-like object' or 'file is nil' ----@nodiscard -function config.lines(file) end - ----a configuration table for the `config.read` function ----@class pl.ConfigReadConfig ----@field smart boolean? -- try to deduce what kind of config file we have (default false) ----@field variabilize boolean? -- make names into valid Lua identifiers (default true) ----@field convert_numbers boolean? -- try to convert values into numbers (default true) ----@field trim_space boolean? -- ensure that there is no starting or trailing whitespace with values (default true) ----@field trim_quotes boolean? -- remove quotes from strings (default false) ----@field list_delim string? -- delimiter to use when separating columns (default ',') ----@field keysep string? -- separator between key and value pairs (default '=') - ----read a configuration file into a table ----@param file string|file* -- either a file-like object or a string, which must be a filename ----@param cnfg? pl.ConfigReadConfig -- see `ConfigReadConfig` type for more info (optional) ----@return table? -- a table containing items, or `nil` ----@return string? -- error 'not a file-like object' or 'file is nil' ----@nodiscard -function config.read(file, cnfg) end - -return config diff --git a/.luacats/pl/data.lua b/.luacats/pl/data.lua deleted file mode 100644 index a31bb7a..0000000 --- a/.luacats/pl/data.lua +++ /dev/null @@ -1,138 +0,0 @@ ----@meta ----# Module [`pl.data`](https://lunarmodules.github.io/Penlight/libraries/pl.data.html) ---- ----Reading and querying simple tabular data. ---- ----```lua ----data.read 'test.txt' ----==> {{10,20},{2,5},{40,50},fieldnames={'x','y'},delim=','} ----``` ---- ----Provides a way of creating basic SQL-like queries. ---- ----```lua ----require 'pl' ----local d = data.read('xyz.txt') ----local q = d:select('x,y,z where x > 3 and z < 2 sort by y') ----for x,y,z in q do ---- print(x,y,z) ----end ----``` ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/06-data.md.html#Reading_Columnar_Data) ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.array2d`](https://lunarmodules.github.io/Penlight/libraries/pl.array2d.html) (fallback methods) -local data = {} - ----@class pl.Data -local prototype_Data = {} - ----return a particular column as a list of values (method). ----@param name string|integer -- either name of column, or numerical index. ----@nodiscard -function prototype_Data:column_by_name(name) end - ----return a query iterator on this data (method). ----@param condn string -- the query expression ----@return fun(): ... ----@nodiscard -function prototype_Data:select(condn) end - ----return a row iterator on this data (method). ----@param condn string -- the query expression ----@return fun(): ... ----@nodiscard -function prototype_Data:select_row(condn) end - ----return a new data object based on this query (method). ----@param condn string -- the query expression ----@return pl.Data ----@nodiscard -function prototype_Data:copy_select(condn) end - ----return the field names of this data object (method). ----@return string[] ----@nodiscard -function prototype_Data:column_names() end - ----write out a row (method). ----@param f file* -- file-like object ----@param row any[] -function prototype_Data:write_row(f, row) end - ----write data out to file (method). ----@param f file* -- file-like object -function prototype_Data:write(f) end - ----@class pl.Data.ReadConfig ----@field delim string -- a string pattern to split fields ----@field fieldnames string[] -- (i.e. don't read from first line) ----@field no_convert boolean -- (default is to try conversion on first data line) ----@field convert { [string]: (fun(value: string): any?, string?) } -- table of custom conversion functions with column keys ----@field numfields integer -- indices of columns known to be numbers ----@field last_field_collect boolean -- only split as many fields as fieldnames. ----@field thousands_dot integer -- thousands separator in Excel CSV is '.' ----@field csv boolean -- fields may be double-quoted and contain commas; Also, empty fields are considered to be equivalent to zero. - ----@param file string|file* -- a filename or a file-like object ----@param cnfg pl.Data.ReadConfig -- parsing options. See `DataReadConfig` type for more info ----@return pl.Data? -- data object, or `nil` ----@return string? -- error message. May be a file error, 'not a file-like object' or a conversion error ----@nodiscard -function data.read(file, cnfg) end - ----write 2D data to a file. Does not assume that the data has actually been ----generated with `data.new` or `data.read`. ----@param d any[][] -- 2D array ----@param file string|file* -- filename or file-like object ----@param fieldnames? string[] -- list of fields (optional) ----@param delim? string -- delimiter (default '\t') ----@return true|nil ----@return string? -- error -function data.write(d, file, fieldnames, delim) end - ----@class pl.Data.Options ----@field [integer] any[] ----@field fieldnames string|string[]? -- a string of delimiter-separated names, or a table of names ----@field delim string? -- delimiter (default `fieldnames`'s delimiter' or '\t') - ----create a new dataset from a table of rows. Can specify the fieldnames, else ----the table must have a field called 'fieldnames', which is either a string ----of delimiter-separated names, or a table of names. ----If the table does not have a field called 'delim', then an attempt will be ----made to guess it from the fieldnames string, defaults otherwise to tab. ----@param d pl.Data.Options -- the table. ----@param fieldnames? string[] -- fieldnames (default `d.fieldnames`) ----@nodiscard -function data.new(d, fieldnames) end - ----@class pl.Data.QueryArg ----@field fields string|string[] ----@field sort_by string ----@field where string|(fun(v: any): boolean) - ----create a query iterator from a select string. Select string has this format: ---- ----```plain ----FIELDLIST [ where LUA-CONDN [ sort by FIELD] ] ----FIELDLIST is a comma-separated list of valid fields, or '*'. ----``` ---- ----@param d pl.Data -- table produced by `data.read` ----@param condn string|string[] -- select string or table ----@param context? {[string]: any}[] -- a list of tables to be searched when resolving functions ----@param return_row? boolean -- if true, wrap the results in a row table ----@return (fun(): ...)? -- an iterator over specified fields, or `nil` ----@return string? -- an error message ----@nodiscard -function data.query(d, condn, context, return_row) end - ----Filter input using a query. ----@param Q string -- a query string ----@param infile? string|file* -- filename or file-like object (default stdin) ----@param outfile? string|file* -- filename or file-like object (default stdout) ----@param dont_fail boolean -- true if you want to return an error, not just fail -function data.filter(Q, infile, outfile, dont_fail) end - -return data diff --git a/.luacats/pl/dir.lua b/.luacats/pl/dir.lua deleted file mode 100644 index 6d4ab91..0000000 --- a/.luacats/pl/dir.lua +++ /dev/null @@ -1,72 +0,0 @@ ----@meta ----# Module [`pl.dir`](https://lunarmodules.github.io/Penlight/libraries/pl.dir.html) ---- ----Listing files in directories and creating/removing directory paths. ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html), ---- [`pl.path`](https://lunarmodules.github.io/Penlight/libraries/pl.path.html) ---- ----Soft Dependencies: `alien`, `ffi` (either are used on Windows for copying/moving files) -local dir = {} - ----Test whether a file name matches a shell pattern. Both parameters are ----case-normalized if operating system is case-insensitive. ----@param filename string -- A file name. ----@param pattern string -- A shell pattern. The only special characters are '*' and '?': '*' matches any sequence of characters and '?' matches any single character. ----@return boolean ----@nodiscard -function dir.fnmatch(filename, pattern) end - ----Return a list of all file names within an array which match a pattern. ----@param filenames string[] -- An array containing file names. ----@param pattern string -- A shell pattern (see `dir.fnmatch`). ----@return string[] -- List of matching file names. ----@nodiscard -function dir.filter(filenames, pattern) end - ----return a list of all files in a directory which match a shell pattern. ----@param dirname? string -- A directory. (default '.') ----@param mask? string -- A shell pattern (see `dir.fnmatch`). If not given, all files are returned. (optional) ----@return string[] -- list of files ----@nodiscard -function dir.getfiles(dirname, mask) end - ----return a list of all subdirectories of the directory. ----@param dirname? string -- A directory. (default '.') ----@return string[] -- a list of directories ----@nodiscard ---- ----Raises: dir must be a valid directory -function dir.getdirectories(dirname) end - ----copy a file. ----@param src string -- source file ----@param dest string -- destination file or directory ----@param flag boolean -- true if you want to force the copy (default) ----@return boolean -- operation succeeded -function dir.copyfile(src, dest, flag) end - ----move a file. ----@param src string -- source file ----@param dest string -- destination file or directory ----@return boolean -- operation succeeded -function dir.movefile(src, dest) end - ----return an iterator which walks through a directory tree starting at root. ----The iterator returns (root,dirs,files) Note that dirs and files are lists ----of names (i.e. you must say path.join(root,d) to get the actual full ----path) If bottom_up is false (or not present), then the entries at the ----current level are returned before we go deeper. This means that you can ----modify the returned list of directories before continuing. This is a clone ----of os.walk from the Python libraries. ----@param root string -- A starting directory ----@param bottom_up? boolean -- False if we start listing entries immediately. ----@param follow_links? boolean -- follow symbolic links ----@return fun(): string -- an iterator returning root,dirs,files ----@nodiscard ---- ----Raises: root must be a directory -function dir.walk(root, bottom_up, follow_links) end - -return dir diff --git a/.luacats/pl/file.lua b/.luacats/pl/file.lua deleted file mode 100644 index 042ef71..0000000 --- a/.luacats/pl/file.lua +++ /dev/null @@ -1,29 +0,0 @@ ----@meta - -local os = os -local utils = require("pl.utils") -local dir = require("pl.dir") -local path = require("pl.path") - ----# Module [`pl.file`](https://lunarmodules.github.io/Penlight/libraries/pl.file.html) ---- ----File manipulation functions: reading, writing, moving and copying. ---- ----This module wraps a number of functions from other modules into a file related module for convenience. ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.dir`](https://lunarmodules.github.io/Penlight/libraries/pl.dir.html#), ---- [`pl.path`](https://lunarmodules.github.io/Penlight/libraries/pl.path.html#) -local file = { - read = utils.readfile, - write = utils.writefile, - copy = dir.copyfile, - move = dir.movefile, - access_time = path.getatime, - creation_time = path.getctime, - modified_time = path.getmtime, - delete = os.remove, -} - -return file diff --git a/.luacats/pl/func.lua b/.luacats/pl/func.lua deleted file mode 100644 index e6072d7..0000000 --- a/.luacats/pl/func.lua +++ /dev/null @@ -1,135 +0,0 @@ ----@meta ----# Module [`pl.func`](https://lunarmodules.github.io/Penlight/libraries/pl.func.html) ---- ----Functional helpers like composition, binding and placeholder expressions. ---- ----Placeholder expressions are useful for short anonymous functions, and were ----inspired by the Boost Lambda library. ---- ----```lua ----> utils.import 'pl.func' ----> ls = List{10,20,30} ----> = ls:map(_1+1) ----{11,21,31} ----``` ---- ----They can also be used to *bind* particular arguments of a function. ----```lua ----> p = bind(print,'start>',_0) ----> p(10,20,30) ----> start> 10 20 30 ----``` ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/07-functional.md.html#Creating_Functions_from_Functions) ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#) -local func = {} - ----@class pl.PlaceholderExpression - ----wrap a table of functions. This makes them available for use in placeholder expressions. ----@param tname string -- a table name ----@param context? table -- context to put results, defaults to environment of caller -function func.import(tname, context) end - ----register a function for use in placeholder expressions. ----@param fun function -- a function ----@param name? string -- a name (optional) ----@return pl.PlaceholderExpression -- a placeholder function -function func.register(fun, name) end - ----all elements of a table except the first. ----@generic T ----@param ls T[] -- a list-like table ----@return T[] ----@nodiscard -function func.tail(ls) end - ----create a string representation of a placeholder expression. ----@param e pl.PlaceholderExpression|any -- a placeholder expression ----@return string ----@nodiscard -function func.repr(e) end - ----instantiate a placeholder expression into an actual function. First we find ----the largest placeholder used, e.g. 2; from this a list of the formal ----parameters can be build. Then we collect and replace any non-PE values from ----the PE, and build up a constant binding list. Finally, the expression can be ----compiled, and `e.PEfunction` is set. ----@param e pl.PlaceholderExpression -- a placeholder expression ----@return function -- a function -function func.instantiate(e) end - ----instantiate a placeholder expression unless it has already been done. ----@param e pl.PlaceholderExpression -- a placeholder expression ----@return function -- the function -function func.I(e) end - -local empty = function() end - ---- represents a variadic (`...`) -func._0 = func.register(empty) - ---- represents argument #1 -func._1 = func.register(empty) - ---- represents argument #2 -func._2 = func.register(empty) - ---- represents argument #3 -func._3 = func.register(empty) - ---- represents argument #4 -func._4 = func.register(empty) - ---- represents argument #5 -func._5 = func.register(empty) - ----bind the first parameter of the function to a value. ----@generic T ----@param fn fun(p: T, ...: any): any -- a function of one or more arguments ----@param p T -- a value ----@return fun(...: any): any -- a function ----@nodiscard ---- ----Usage: ---- ----```lua ----(func.bind1(math.max,10))(20) == math.max(10,20) ----``` -function func.bind1(fn, p) end - ----@deprecated -func.curry = func.bind1 - ----create a function which chains two functions. ----@param f function -- a function of at least one argument ----@param g function -- a function of at least one argument ----@return function fog -- a function ----@nodiscard ---- ----Usage: ---- ----```lua ----printf = compose(io.write,string.format) ----``` -function func.compose(f, g) end - ----bind the arguments of a function to given values. `func.bind(fn,v,_2)` is equivalent to `func.bind1(fn,v)`. ----@param fn function -- a function of at least one argument ----@param ... any -- values or placeholder variables ----@return function -- a function ----@nodiscard ---- ----Usage: ---- ----```lua ----(bind(f, func._1, a))(b) == f(a,b) ---- ----(bind(f, func._2, func._1))(a,b) == f(b,a) ----``` -function func.bind(fn, ...) end - -return func diff --git a/.luacats/pl/import_into.lua b/.luacats/pl/import_into.lua deleted file mode 100644 index 73ac93d..0000000 --- a/.luacats/pl/import_into.lua +++ /dev/null @@ -1,20 +0,0 @@ ----@meta ----# Module `pl.import_into` ---- ----PL loader, for loading all PL libraries, only on demand. ---- ----Whenever a module is implicitly accesssed, the table will have the module ----automatically injected. (e.g. _ENV.tablex) then that module is dynamically ----loaded. The submodules are all brought into the table that is provided as ----the argument, or returned in a new table. If a table is provided, that ----table's metatable is clobbered, but the values are not. This module returns ----a single function, which is passed the environment. If this is true, then ----return a 'shadow table' as the module. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/01-introduction.md.html#To_Inject_or_not_to_Inject_) ----@param env? table|true ----@return table -- `env` ----@return table -- `mod` -local function import_into(env) end - -return import_into diff --git a/.luacats/pl/input.lua b/.luacats/pl/input.lua deleted file mode 100644 index 44e2d2f..0000000 --- a/.luacats/pl/input.lua +++ /dev/null @@ -1,77 +0,0 @@ ----@meta ----# Module [`pl.input`](https://lunarmodules.github.io/Penlight/libraries/pl.input.html) ---- ----Iterators for extracting words or numbers from an input source. ---- ----```lua ----require 'pl' ----local total, n = seq.sum(input.numbers()) ----print('average',total/n) ----``` ---- ----*source* is defined as a string or a file-like object (i.e. has a read() method which returns the next line) ---- ----See [here](https://lunarmodules.github.io/Penlight/manual/06-data.md.html#Reading_Unstructured_Text_Data) ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#) -local input = {} - ----create an iterator over all tokens. based on `allwords()` from [PiL, 7.1](https://www.lua.org/pil/7.1.html) ----@param getter fun(): string -- any function that returns a line of text ----@param pattern string ----@param fn? string -- a function to process each token as it's found. (optional) ----@return fun(): string -- an iterator ----@nodiscard ---- ----Usage: ---- ----```lua ----for word in input.alltokens(io.read, "%w+") do ---- print("found word in input:", word) ----end ----``` -function input.alltokens(getter, pattern, fn) end - ----create a function which grabs the next value from a source. If the source ----is a string, then the getter will return the string and thereafter return ----nil. If not specified then the source is assumed to be stdin. ----@generic T: string ----@param f string|file* -- string or a file-like object (i.e. has a read() method which returns the next line) ----@return fun(): T -- a getter function ----@nodiscard -function input.create_getter(f) end - ----generate a sequence of numbers from a source. ----@param f string|file* -- a source ----@return fun(): number -- an iterator ----@nodiscard -function input.numbers(f) end - ----generate a sequence of words from a source. ----@param f string|file* -- a source ----@return fun(): string -- an iterator ----@nodiscard -function input.words(f) end - ----@class pl.InputFieldsOptions ----@field no_fail boolean -- default `true` ----@field no_convert boolean -- default `false` - ----parse an input source into fields. By default, will fail if it cannot ----convert a field to a number. ----@param ids integer[]|integer -- a list of field indices, or a maximum field index ----@param delim? string -- delimiter to parse fields (default space) ----@param f? string|file* -- a source (default stdin) ----@param opts? pl.InputFieldsOptions -- an option table, (default `{no_fail=true, no_convert=false}`) ----@return fun(): ...: string -- an iterator with the field values ----@nodiscard ---- ----Usage: ---- ----```lua ----for x,y in fields {2,3} do print(x,y) end -- 2nd and 3rd fields from stdin ----``` -function input.fields(ids, delim, f, opts) end - -return input diff --git a/.luacats/pl/lapp.lua b/.luacats/pl/lapp.lua deleted file mode 100644 index 899e182..0000000 --- a/.luacats/pl/lapp.lua +++ /dev/null @@ -1,71 +0,0 @@ ----@meta ----# Module [`pl.lapp`](https://lunarmodules.github.io/Penlight/libraries/pl.lapp.html) ---- ----Simple command-line parsing using human-readable specification. ---- ----Supports GNU-style parameters. ---- ----```lua ----lapp = require 'pl.lapp' ----local args = lapp [[ ----Does some calculations ---- -o,--offset (default 0.0) Offset to add to scaled number ---- -s,--scale (number) Scaling factor ---- (number) Number to be scaled ----]] ---- ----print(args.offset + args.scale * args.number) ----``` ---- ----Lines beginning with '-' are flags; there may be a short and a long name; ----lines beginning with '' are arguments. Anything in parens after the ----flag/argument is either a default, a type name or a range constraint. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/08-additional.md.html#Command_line_Programs_with_Lapp) ---- ----Dependencies: ---- [`pl.sip`](https://lunarmodules.github.io/Penlight/libraries/pl.sip.html#) ----@overload fun(str: string, args?: string[]): { [string]: string } -local lapp = { - ---controls whether to dump usage on error. Defaults to `true` - show_usage_error = true,--[[@as boolean]] -} - ----quit this script immediately. ----@param msg? string -- optional message ----@param no_usage? boolean|"throw" -- suppress 'usage' display or error -function lapp.quit(msg, no_usage) end - ---- print an error to stderr and quit. ----@param msg string -- a message ----@param no_usage? boolean|"throw" -- suppress 'usage' display -function lapp.error(msg, no_usage) end - ----open a file. This will quit on error, and keep a list of file objects for ----later cleanup. ----@param file string -- filename ----@param opt? openmode -- same as second parameter of io.open ----@return file* ----@nodiscard -function lapp.open(file, opt) end - ----quit if the condition is false. ----@param condn boolean -- a condition ----@param msg string -- message text -function lapp.assert(condn, msg) end - ----add a new type to Lapp. These appear in parens after the value like a range ----constraint, e.g. ' (integer) Process PID' ----@param name string -- name of type ----@param converter (fun(val: string): string)|string -- either a function to convert values, or a Lua type name. ----@param constraint? fun(val: string) -- function to verify values, should use `lapp.error` if failed -function lapp.add_type(name, converter, constraint) end - ----process a Lapp options string. Usually called as `lapp()`. ----@param str string -- the options text ----@param args? string[] -- a table of arguments (default is _G.arg) ----@return { [string]: string } -- a table with parameter-value pairs ----@nodiscard -function lapp.process_options_string(str, args) end - -return lapp diff --git a/.luacats/pl/lexer.lua b/.luacats/pl/lexer.lua deleted file mode 100644 index e576f64..0000000 --- a/.luacats/pl/lexer.lua +++ /dev/null @@ -1,110 +0,0 @@ ----@meta ----# Module [`pl.lexer`](https://lunarmodules.github.io/Penlight/libraries/pl.lexer.html) ---- ----Lexical scanner for creating a sequence of tokens from text. ---- ----`lexer.scan(s)` returns an iterator over all tokens found in the string s. ----This iterator returns two values, a token type string (such as 'string' for ----quoted string, 'iden' for identifier) and the value of the token. ---- ----Versions specialized for Lua and C are available; these also handle block ----comments and classify keywords as 'keyword' tokens. For example: ---- ----```lua ----> s = 'for i=1,n do' ----> for t,v in lexer.lua(s) do print(t,v) end ----keyword for ----iden i ----= = ----number 1 ----, , ----iden n ----keyword do ----``` ---- ----See the Guide for further [discussion](https://lunarmodules.github.io/Penlight/manual/06-data.md.html#Lexical_Scanning) -local lexer = {} - ----@alias pl.TokenStream fun(): (string, string) - ----@alias pl.LexerFilter { [function]: true, space?: boolean, comments?: boolean } - ----@alias pl.LexerOptions {[string]: any} - ----create a plain token iterator from a string or file-like object. ----@param s string|file* -- a string or a file-like object with :read() method returning lines. ----@param matches? {[1]: string, [2]: fun(token: string, options: {[string]: any}, bounds: { [1]: integer, [2]: integer })}[] -- an optional match table - array of token descriptions. A token is described by a `{pattern, action}` pair, where pattern should match token body and action is a function called when a token of described type is found. ----@param filter? pl.LexerFilter -- a table of token types to exclude, by default `{ space = true }` ----@param options? {[string]: any} -- a table of options; by default, `{ number = true, string = true }` which means convert numbers and strip string quotes. ----@return pl.TokenStream -- a token stream ----@nodiscard -function lexer.scan(s, matches, filter, options) end - ----insert tokens into a stream. ----@param tok pl.TokenStream -- a token stream ----@param a1 string -- a string is the type, a table is a token list and a function is assumed to be a token-like iterator (returns type & value) ----@param a2 string -- a string is the value ----@overload fun(tok: pl.TokenStream, a1: fun(): pl.TokenStream) ----@overload fun(tok: pl.TokenStream, a1: {[1]: string, [2]: string}[]) -function lexer.insert(tok, a1, a2) end - -lexer.insert(lexer.scan(""), { { "e", "r" } }) - ----get current line number. ----@param tok pl.TokenStream -- a token stream ----@return integer -- the line number. ----@return integer -- if the input source is a file-like object, also return the column. ----@nodiscard -function lexer.lineno(tok) end - ----get the rest of the stream. ----@param tok pl.TokenStream -- a token stream ----@return string -- a string ----@nodiscard -function lexer.getrest(tok) end - ----get the Lua keywords as a set-like table. So res["and"] etc would be true. ----@return { [string]: true? } -- a table ----@nodiscard -function lexer.get_keywords() end - ----create a Lua token iterator from a string or file-like object. Will return ----the token type and value. ----@param s string -- the string ----@param filter? pl.LexerFilter -- a table of token types to exclude, by default `{ space = true, comments = true }` (optional) ----@param options? pl.LexerOptions -- a table of options; by default, `{ number = true, string = true }`, which means convert numbers and strip string quotes. (optional) ----@return pl.TokenStream ----@nodiscard -function lexer.lua(s, filter, options) end - ----create a C/C++ token iterator from a string or file-like object. Will return ----the token type type and value. ----@param s string -- the string ----@param filter? pl.LexerFilter -- a table of token types to exclude, by default `{ space = true, comments = true }` (optional) ----@param options? pl.LexerOptions -- a table of options; by default, `{ number = true, string = true }`, which means convert numbers and strip string quotes. (optional) ----@return pl.TokenStream ----@nodiscard -function lexer.cpp(s, filter, options) end - ----get a list of parameters separated by a delimiter from a stream. ----@param tok pl.TokenStream -- the token stream ----@param endtoken string -- end of list. Can be '\n' (default `)`) ----@param delim string -- separator (default `,`) ----@nodiscard -function lexer.get_separated_list(tok, endtoken, delim) end - ----get the next non-space token from the stream. ----@param tok pl.TokenStream -- the token stream. ----@return string, string ----@nodiscard -function lexer.skipws(tok) end - ----get the next token, which must be of the expected type. Throws an error if ----this type does not match! ----@param tok pl.TokenStream -- the token stream ----@param expected_type string -- the token type ----@param no_skip_ws? boolean -- whether we should skip whitespace ----@return string -- the value -function lexer.expecting(tok, expected_type, no_skip_ws) end - -return lexer diff --git a/.luacats/pl/luabalanced.lua b/.luacats/pl/luabalanced.lua deleted file mode 100644 index 98ef21d..0000000 --- a/.luacats/pl/luabalanced.lua +++ /dev/null @@ -1,88 +0,0 @@ ----@meta ----# Module [`pl.luabalanced`](https://lunarmodules.github.io/Penlight/libraries/pl.luabalanced.html) ---- ----Extract delimited Lua sequences from strings. ---- ----Inspired by Damian Conway's Text::Balanced in Perl. ---- ----[1] [Lua Wiki Page](http://lua-users.org/wiki/LuaBalanced) ---- ----[2] http://search.cpan.org/dist/Text-Balanced/lib/Text/Balanced.pm ---- ----```lua ---- local lb = require "pl.luabalanced" ---- ------Extract Lua expression starting at position 4. ---- print(lb.match_expression("if x^2 + x > 5 then print(x) end", 4)) ---- --> x^2 + x > 5 16 ---- ------Extract Lua string starting at (default) position 1. ----print(lb.match_string([["test\"123" .. "more"]])) ------> "test\"123" 12 ----``` -local luabalanced = {} - ----Match Lua string in string `s` starting at position `pos`. ----@param s string ----@param pos integer ----@return string? string -- the matched string (or `nil` on no match) ----@return integer newpos -- the position following the match (or `pos` on no match) ----@nodiscard -function luabalanced.match_string(s, pos) end - ----Match bracketed Lua expression, e.g. `"(...)"`, `"{...}"`, `"[...]"`, ----`"[[...]]"`, `[=[...]=]`, etc. ---- ----Function interface is similar to match_string. ----@param s string ----@param pos integer ----@return string? string -- the matched string (or `nil` on no match) ----@return integer newpos -- the position following the match (or `pos` on no match) ----@nodiscard -function luabalanced.match_bracketed(s, pos) end - ----Match Lua expression, e.g. "a + b * c[e]". ---- ----Function interface is similar to match_string. ----@param s string ----@param pos integer ----@return string? string -- the matched string (or `nil` on no match) ----@return integer newpos -- the position following the match (or `pos` on no match) ----@nodiscard -function luabalanced.match_expression(s, pos) end - ----Match name list (zero or more names). E.g. "a,b,c" ---- ----Function interface is similar to match_string, but returns array as match. ----@param s string ----@param pos integer ----@return string[] strings -- the matched strings ----@return integer newpos -- the position following the match (or `pos` on no match) ----@nodiscard -function luabalanced.match_namelist(s, pos) end - ----Match expression list (zero or more expressions). E.g. "a+b,b*c". ----Function interface is similar to match_string, but returns array as match. ----@param s string ----@param pos integer ----@return string[] strings -- the matched strings ----@return integer newpos -- the position following the match (or `pos` on no match) ----@nodiscard -function luabalanced.match_explist(s, pos) end - ----Replace snippets of code in Lua code string `s` using replacement function ----`f(u, sin) --> sout`. ---- ----`u` is the type of snippet ----('c' = comment, 's' = string, 'e' = any other code). ----Snippet is replaced with `sout` (unless `sout` is nil or false, in which ----case the original snippet is kept). ---- ----This is somewhat analogous to `string.gsub`. ----@param s string ----@param f fun(u: string, sin: string): (sout: string|false|nil) ----@return string ----@nodiscard -function luabalanced.gsub(s, f) end - -return luabalanced diff --git a/.luacats/pl/operator.lua b/.luacats/pl/operator.lua deleted file mode 100644 index b665266..0000000 --- a/.luacats/pl/operator.lua +++ /dev/null @@ -1,278 +0,0 @@ ----@meta ----# Module [`pl.operator`](https://lunarmodules.github.io/Penlight/libraries/pl.operator.html) ---- ----Lua operators available as functions. ---- ----(similar to the Python module of the same name) ---- ----There is a module field `optable` which maps the operator strings onto ----these functions, e.g. `operator.optable['()'] = =operator.call` ---- ----Operator strings like `'>'` and `'{}'` can be passed to most Penlight functions ----expecting a function argument. -local operator = {} - ----apply function to some arguments `()` ----@param fn fun(...: any): any -- a function or callable object ----@param ... any -- arguments ----@return any ... ----@nodiscard -function operator.call(fn, ...) end - ----get the indexed value from a table `[]` ----@param t any -- a table or any indexable object ----@param k any -- the key ----@return any ----@nodiscard -function operator.index(t, k) end - ----returns true if arguments are equal `==` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.eq(a, b) end - ----returns true if arguments are not equal `~=` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.neq(a, b) end - ----returns true if `a` is less than `b` `<` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.lt(a, b) end - ----returns true if `a` is less or equal to `b` `<=` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.le(a, b) end - ----returns true if `a` is greater than `b` `>` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.gt(a, b) end - ----returns true if `a` is greater or equal to `b` `>=` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.ge(a, b) end - ----returns length of string or table `#` ----@param a any -- a string or a table ----@return integer ----@nodiscard -function operator.len(a) end - ----add two values `+` ----@param a any -- value ----@param b any -- value ----@return any ----@nodiscard -function operator.add(a, b) end - ----subtract `b` from `a` `-` ----@param a any -- value ----@param b any -- value ----@return any ----@nodiscard -function operator.sub(a, b) end - ----multiply two values `*` ----@param a any -- value ----@param b any -- value ----@return any -function operator.mul(a, b) end - ----divide `a` by `b` `/` ----@param a any -- value ----@param b any -- value ----@return any ----@nodiscard -function operator.div(a, b) end - ----raise `a` to the power of `b` `^` ----@param a any -- value ----@param b any -- value ----@return any -function operator.pow(a, b) end - ----modulo; remainder of `a` divided by `b` `%` ----@param a any -- value ----@param b any -- value ----@return any ----@nodiscard -function operator.mod(a, b) end - ----concatenate two values (either strings or `__concat` defined) `..` ----@param a any -- value ----@param b any -- value ----@return any ----@nodiscard -function operator.concat(a, b) end - ----return the negative of a value `-` ----@param a any -- value ----@return any ----@nodiscard -function operator.unm(a) end - ----false if value evaluates as true `not` ----@param a any -- value ----@return boolean ----@nodiscard -function operator.lnot(a) end - ----true if both values evaluate as true `and` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.land(a, b) end - ----true if either value evaluate as true `or` ----@param a any -- value ----@param b any -- value ----@return boolean ----@nodiscard -function operator.lor(a, b) end - ----make a table from the arguments `{}` ----@param ... any -- non-nil arguments ----@return any[] -- a table ----@nodiscard -function operator.table(...) end - ----match two strings `~`. uses `string.find` ----@param a string ----@param b string ----@return boolean ----@nodiscard -function operator.match(a, b) end - ----the null operation. ----@param ... any -- arguments ----@return any ... -- the arguments -function operator.nop(...) end - ----@alias pl.BoolBinOpString ----| "<" ----| "<=" ----| ">" ----| ">=" ----| "==" ----| "~=" ----| "()" ----| "and" ----| "or" ----| "~" - ---- Stores all the non-commutative boolean operators for sorting functions ----@alias pl.BoolOrderedBinOpString ----| "<" ----| "<=" ----| ">" ----| ">=" ----| "()" ----| "~" - ----@alias pl.BinOpString ----| "+" ----| "-" ----| "*" ----| "/" ----| "%" ----| "^" ----| ".." ----| "()" ----| "{}" ----| "[]" ----| "<" ----| "<=" ----| ">" ----| ">=" ----| "==" ----| "~=" ----| "and" ----| "or" ----| "~" ----| "" - --- apparently "# renders currently when compared to "#" - ----@alias pl.UnOpString ----| "#" ----| "()" ----| "{}" ----| "" - ----@alias pl.MultiOpString ----| "()" ----| "{}" ----| "" - ----@alias pl.OpString ----| "+" ----| "-" ----| "*" ----| "/" ----| "%" ----| "^" ----| ".." ----| "()" ----| "{}" ----| "[]" ----| "<" ----| "<=" ----| ">" ----| ">=" ----| "==" ----| "~=" ----| "and" ----| "or" ----| "~" ----| "#" ----| "" - ----Map from operator symbol to function. Most of these map directly from ----operators; But note these extras ---- ---- * `'()'` = call ---- * `'[]'` = index ---- * `'{}'` = table ---- * `'~'` = match -operator.optable = { - ["+"] = operator.add, - ["-"] = operator.sub, - ["*"] = operator.mul, - ["/"] = operator.div, - ["%"] = operator.mod, - ["^"] = operator.pow, - [".."] = operator.concat, - ["()"] = operator.call, - ["[]"] = operator.index, - ["<"] = operator.lt, - ["<="] = operator.le, - [">"] = operator.gt, - [">="] = operator.ge, - ["=="] = operator.eq, - ["~="] = operator.neq, - ["#"] = operator.len, - ["and"] = operator.land, - ["or"] = operator.lor, - ["{}"] = operator.table, - ["~"] = operator.match, - [""] = operator.nop, -} - -return operator diff --git a/.luacats/pl/path.lua b/.luacats/pl/path.lua deleted file mode 100644 index 33deeee..0000000 --- a/.luacats/pl/path.lua +++ /dev/null @@ -1,276 +0,0 @@ -local lfs = require("lfs") - ----@meta ----# Module [`pl.path`](https://lunarmodules.github.io/Penlight/libraries/pl.path.html) ---- ----Path manipulation and file queries. ---- ----This is modelled after Python's os.path library (10.1); see [the Guide](https://lunarmodules.github.io/Penlight/manual/04-paths.md.html#). ---- ----NOTE: the functions assume the paths being dealt with to originate from the ----OS the application is running on. Windows drive letters are not to be used ----when running on a Unix system for example. The one exception is Windows ----paths to allow both forward and backward slashes (since Lua also accepts ----those) ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`lfs`](http://stevedonovan.github.io/lua-stdlibs/modules/lfs.html) -local path = { - ---are we running Windows? - is_windows = true or false,--[[@as boolean]] - - ---path separator for this platform. - sep = "/" or "\\",--[[@as string]] - - ---separator for PATH for this platform - dirsep = ";" or ";;",--[[@as string]] -} - -path.dir = lfs.dir -path.mkdir = lfs.mkdir -path.rmdir = lfs.rmdir -path.attrib = lfs.attributes -path.currentdir = lfs.currentdir -path.link_attrib = lfs.symlinkattributes -path.chdir = lfs.chdir - ----is this a directory? ----@param P string -- A file path ----@return boolean ----@nodiscard -function path.isdir(P) end - ----is this a file? ----@param P string -- A file path ----@return boolean ----@nodiscard -function path.isfile(P) end - ----is this a symbolic link? ----@param P string -- A file path ----@return boolean ----@nodiscard -function path.islink(P) end - ----return size of a file. ----@param P string -- A file path ----@return integer -function path.getsize(P) end - ----does a path exist? ----@param P string -- A file path ----@return boolean ----@nodiscard -function path.exists(P) end - ----Return the time of last access as the number of seconds since the epoch. ----@param P string -- A file path ----@return integer ----@nodiscard -function path.getatime(P) end - ----Return the time of last modification as the number of seconds since the epoch. ----@param P string -- A file path ----@return integer ----@nodiscard -function path.getmtime(P) end - ----Return the system's ctime as the number of seconds since the epoch. ----@param P string -- A file path ----@return integer ----@nodiscard -function path.getctime(P) end - ----given a path, return the directory part and a file part. if there's no ----directory part, the first value will be empty ----@param P string -- A file path ----@return string -- directory part ----@return string -- file part ----@nodiscard ---- ----Usage: ---- ----```lua ----local dir, file = path.splitpath("some/dir/myfile.txt") ----assert(dir == "some/dir") ----assert(file == "myfile.txt") ---- ----local dir, file = path.splitpath("some/dir/") ----assert(dir == "some/dir") ----assert(file == "") ---- ----local dir, file = path.splitpath("some_dir") ----assert(dir == "") ----assert(file == "some_dir") ----``` -function path.splitpath(P) end - ----return an absolute path. ----@param P string -- A file path ----@param pwd? string -- start path to use (default is current dir) ----@return string ----@nodiscard -function path.abspath(P, pwd) end - ----given a path, return the root part and the extension part. if there's no ----extension part, the second value will be empty ----@param P string -- A file path ----@return string -- root part (everything up to the ".", maybe empty) ----@return string -- extension part (including the ".", maybe empty) ----@nodiscard ---- ----Usage: ---- ----```lua ----local file_path, ext = path.splitext("/bonzo/dog_stuff/cat.txt") ----assert(file_path == "/bonzo/dog_stuff/cat") ----assert(ext == ".txt") ---- ----local file_path, ext = path.splitext("") ----assert(file_path == "") ----assert(ext == "") ----``` -function path.splitext(P) end - ----return the directory part of a path ----@param P string -- A file path ----@return string -- everything before the last dir-separator ----@nodiscard ---- ----Usage: ---- ----```lua ----path.dirname("/some/path/file.txt") -- "/some/path" ----path.dirname("file.txt") -- "" (empty string) ----``` -function path.dirname(P) end - ----return the file part of a path ----@param P string -- A file path ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----path.basename("/some/path/file.txt") -- "file.txt" ----path.basename("/some/path/file/") -- "" (empty string) ----``` -function path.basename(P) end - ----get the extension part of a path. ----@param P string -- A file path ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----path.extension("/some/path/file.txt") -- ".txt" ----path.extension("/some/path/file_txt") -- "" (empty string) ----``` -function path.extension(P) end - ----is this an absolute path? ----@param P string ----@return boolean ----@nodiscard ---- ----Usage: ---- ----```lua ----path.isabs("hello/path") -- false ----path.isabs("/hello/path") -- true ------ Windows; ----path.isabs("hello\\path") -- false ----path.isabs("\\hello\\path") -- true ----path.isabs("C:\\hello\\path") -- true ----path.isabs("C:hello\\path") -- false ----``` -function path.isabs(P) end - ----return the path resulting from combining the individual paths. if the second ----(or later) path is absolute, we return the last absolute path (joined with ----any non-absolute paths following). empty elements (except the last) will be ----ignored. ----@param p1 string -- A file path ----@param p2 string -- A file path ----@param ... string -- more file paths ----@return string -- the combined path ----@nodiscard ---- ----Usage: ---- ----```lua ----path.join("/first","second","third") -- "/first/second/third" ----path.join("first","second/third") -- "first/second/third" ----path.join("/first","/second","third") -- "/second/third" ----``` -function path.join(p1, p2, ...) end - ----normalize the case of a pathname. On Unix, this returns the path unchanged, for Windows it converts; ---- ---- * the path to lowercase ---- * forward slashes to backward slashes ---- ----@param P string -- A file path ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----path.normcase("/Some/Path/File.txt") ------ Windows: "\some\path\file.txt" ------ Others : "/Some/Path/File.txt" ----``` -function path.normcase(P) end - ----normalize a path name. `A//B`, `A/./B`, and `A/foo/../B` all become `A/B`. ---- ----An empty path results in `'.'`. ----@param P string -- a file path ----@return string ----@nodiscard -function path.normpath(P) end - ----relative path from current directory or optional start point ----@param P string -- a path ----@param start? string -- start point (default current directory) ----@return string ----@nodiscard -function path.relpath(P, start) end - ----Replace a starting `'~'` with the user's home directory. In windows, if HOME ----isn't set, then `USERPROFILE` is used in preference to `HOMEDRIVE` `HOMEPATH`. ----This is guaranteed to be writeable on all versions of Windows. ----@param P string -- A file path ----@return string ----@nodiscard -function path.expanduser(P) end - ----Return a suitable full path to a new temporary file name. unlike ----`os.tmpname()`, it always gives you a writeable path (uses `TEMP` environment ----variable on Windows) ----@return string ----@nodiscard -function path.tmpname() end - ----return the largest common prefix path of two paths. ----@param path1 string -- a file path ----@param path2 string -- a file path ----@return string -- the common prefix (Windows: separators will be normalized, casing will be original) ----@nodiscard -function path.common_prefix(path1, path2) end - ----return the full path where a particular Lua module would be found. Both ----package.path and package.cpath is searched, so the result may either be a ----Lua file or a shared library. ----@param mod string -- name of the module ----@return string? -- path of module (`nil` on fail) ----@return boolean|string -- whether the module is in Lua or binary (error string listing paths tried on fail) ----@nodiscard -function path.package_path(mod) end - -return path diff --git a/.luacats/pl/permute.lua b/.luacats/pl/permute.lua deleted file mode 100644 index 55c6949..0000000 --- a/.luacats/pl/permute.lua +++ /dev/null @@ -1,94 +0,0 @@ ----@meta ----# Module [`pl.permute`](https://lunarmodules.github.io/Penlight/libraries/pl.permute.html) ---- ----Permutation operations. ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#) -local permute = {} - ----an iterator over all order-permutations of the elements of a list. Please ----note that the same list is returned each time, so do not keep references! ----@generic T ----@param a T[] -- a list-like table ----@return fun(): T[] -- an iterator which provides the next permutation as a list ----@nodiscard -function permute.order_iter(a) end - ----construct a table containing all the order-permutations of a list. ----@generic T ----@param a T[] -- list-like table ----@return T[][] -- a table of tables ----@nodiscard ---- ----Usage: ---- ----```lua ----local results = permute.order_table {1,2,3} ------ results = { ------ { 2, 3, 1 }, ------ { 3, 2, 1 }, ------ { 3, 1, 2 }, ------ { 1, 3, 2 }, ------ { 2, 1, 3 }, ------ { 1, 2, 3 }, ------ } ---- ----``` -function permute.order_table(a) end - ----an iterator over all permutations of the elements of the given lists. ----@param ... any[] -- list-like tables, they are nil-safe if a length-field `n` is provided (see `utils.pack`) ----@return fun(): (integer, ...: any) -- an iterator which provides the next permutation as return values in the same order as the provided lists, preceeded by an index ----@nodiscard ---- ----Usage: ---- ----```lua ----local strs = utils.pack("one", nil, "three") -- adds an 'n' field for nil-safety ----local bools = utils.pack(true, false) ----local iter = permute.list_iter(strs, bools) ---- ----print(iter()) --> 1, one, true ----print(iter()) --> 2, nil, true ----print(iter()) --> 3, three, true ----print(iter()) --> 4, one, false ----print(iter()) --> 5, nil, false ----print(iter()) --> 6, three, false ----``` -function permute.list_iter(...) end - ----construct a table containing all the permutations of a set of lists. ----@param ... any[] -- list-like tables, they are nil-safe if a length-field `n` is provided ----@return any[][] -- a list of lists, the sub-lists have an 'n' field for nil-safety ----@nodiscard ---- ----Usage: ---- ----```lua ----local strs = utils.pack("one", nil, "three") -- adds an 'n' field for nil-safety ----local bools = utils.pack(true, false) ----local results = permute.list_table(strs, bools) ------ results = { ------ { "one", true, n = 2 }, ------ { nil, true, n = 2 }, ------ { "three", true, n = 2 }, ------ { "one", false, n = 2 }, ------ { nil, false, n = 2 }, ------ { "three", false, n = 2 }, ------ } ----``` -function permute.list_table(...) end - ----@deprecated ----deprecated. Use `permute.order_iter`. ----@param ... any -function permute.iter(...) end - ----@deprecated ----@param ... any ----deprecated. Use `permute.order_table`. -function permute.table(...) end - -return permute diff --git a/.luacats/pl/pretty.lua b/.luacats/pl/pretty.lua deleted file mode 100644 index 20cc644..0000000 --- a/.luacats/pl/pretty.lua +++ /dev/null @@ -1,98 +0,0 @@ ----@meta ----# Module [`pl.pretty`](https://lunarmodules.github.io/Penlight/libraries/pl.pretty.html) ---- ----Pretty-printing Lua tables. ---- ----Also provides a sandboxed Lua table reader and a function to present large ----numbers in human-friendly format. ---- ----Dependencies: ---- [pl.utils](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [pl.lexer](https://lunarmodules.github.io/Penlight/libraries/pl.lexer.html#), ---- [pl.stringx](https://lunarmodules.github.io/Penlight/libraries/pl.stringx.html#), ---- [debug](https://www.lua.org/manual/5.1/manual.html#5.9) ----@overload fun(...) -local pretty = {} - ----Read a string representation of a Lua table. This function loads and runs the ----string as Lua code, but bails out if it contains a function definition. ----Loaded string is executed in an empty environment. ----@param s string -- string to read in `{...}` format, possibly with some whitespace before or after the curly braces. A single line comment may be present at the beginning. ----@return table? -- a table in case of success, `nil` on fail. ----@return string? -- error message ----@nodiscard -function pretty.read(s) end - ----Read a Lua chunk. ----@param s string -- Lua code. ----@param env? table -- environment used to run the code, empty by default. ----@param paranoid? boolean -- abort loading if any looping constructs are found in the code and disable string methods. ----@return table? -- the environment in case of success, `nil` on fail. ----@return string? -- syntax or runtime error if something went wrong. -function pretty.load(s, env, paranoid) end - ----Create a string representation of a Lua table. This function never fails, ----but may complain by returning an extra value. Normally puts out one item per ----line, using the provided indent; set the second parameter to an empty string ----if you want output on one line. ---- ----NOTE: this is NOT a serialization function, not a full blown debug function. ----Check out respectively the `serpent` or `inspect` Lua modules for that if you need them. ----@param tbl table -- Table to serialize to a string. ----@param space? string -- The indent to use. Defaults to two spaces; pass an empty string for no indentation. ----@param not_clever? boolean -- Pass true for plain output, e.g. `{['key']=1}`. Defaults to `false`. ----@return string -- a string ----@return string? -- an optional error message ----@nodiscard -function pretty.write(tbl, space, not_clever) end - ----Dump a Lua table out to a file or stdout. ----@param t table -- The table to write to a file or stdout. ----@param filename? string -- File name to write to. Defaults to writing to stdout. -function pretty.dump(t, filename) end - ----Dump a series of arguments to stdout for debug purposes. This function is ----attached to the module table __call method, to make it extra easy to access. ----So the full: ---- ----```lua ----print(require("pl.pretty").write({...})) ----``` ---- ----Can be shortened to: ---- ----```lua ----require"pl.pretty" (...) ----``` ---- ----Any `nil` entries will be printed as `""` to make them explicit. ----@param ... any -- the parameters to dump to stdout. ---- ----Usage: ---- ----```lua ------ example debug output ----require"pl.pretty" ("hello", nil, "world", { bye = "world", true} ) ---- ------ output: ----{ ---- ["arg 1"] = "hello", ---- ["arg 2"] = "", ---- ["arg 3"] = "world", ---- ["arg 4"] = { ---- true, ---- bye = "world" ---- } ----} ----``` -function pretty.debug(...) end - ----Format large numbers nicely for human consumption. ----@param num number -- a number. ----@param kind? string -- one of `'M'` (memory in KiB, MiB, etc.), `'N'` (postfixes are 'K', 'M' and 'B'), or `'T'` (use commas as thousands separator), `'N'` by default. ----@param prec? integer -- number of digits to use for 'M' and 'N', `1` by default. ----@return string ----@nodiscard -function pretty.number(num, kind, prec) end - -return pretty diff --git a/.luacats/pl/seq.lua b/.luacats/pl/seq.lua deleted file mode 100644 index aa238d9..0000000 --- a/.luacats/pl/seq.lua +++ /dev/null @@ -1,701 +0,0 @@ ----@meta ----# Module [`pl.seq`](https://lunarmodules.github.io/Penlight/libraries/pl.seq.html) ---- ----Manipulating iterators as sequences. ---- ----See [The Guide](https://lunarmodules.github.io/Penlight/manual/07-functional.md.html#Sequences) ---- ----Dependencies: ---- [pl.utils](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [pl.types](https://lunarmodules.github.io/Penlight/libraries/pl.types.html#), ---- [debug](https://www.lua.org/manual/5.1/manual.html#5.9) ----@overload fun(iter: any[]|fun(): any|pl.Sequence): pl.Sequence -local seq = {} - ----given a number, return a `function(y)` which returns `true` if `y > x` ----@param x number -- a number ----@return fun(y: number): boolean ----@nodiscard -function seq.greater_than(x) end - ----given a number, returns a `function(y)` which returns `true` if `y < x` ----@param x any -- a value ----@return fun(y: any): boolean ----@nodiscard -function seq.less_than(x) end - ----given any value, return a `function(y)` which returns `true` if `y == x` ----@param x number -- a number ----@return fun(y: number): boolean ----@nodiscard -function seq.equal_to(x) end - ----given a string, return a `function(s)` which matches `s` against the string. ----@param pattern string -- a string ----@return fun(s: string): (integer?, integer?, ...: any?) ----@nodiscard ---- ----Usage: ---- ----```lua ----seq.matching(pattern)(s) == string.find(s, pattern) ----seq{s}:matching(pattern) == string.find(s, pattern) ----``` -function seq.matching(pattern) end - ----sequence adaptor for a table. Note that if any generic function is passed a ----table, it will automatically use `seq.list()` ----@generic T ----@param t T[] -- a list-like table ----@return fun(): T ----@nodiscard ---- ----Usage: ---- ----```lua ----seq(t):sum() --> the sum of all elements of t ----``` ---- ----```lua ----for x in list(t) do ... end ----``` -function seq.list(t) end - ----return the keys of the table. ----@generic K ----@param t { [K]: any } -- an arbitrary table ----@return fun(): K -- iterator over keys ----@nodiscard -function seq.keys(t) end - ----@generic T ----@param iter T[]|fun(): T|pl.Sequence ----@return fun(): T ----@nodiscard -function seq.iter(iter) end - ----create an iterator over a numerical range. Like the standard Python function xrange. ----@param start number -- a number ----@param finish number -- a number greater than `start` ----@return fun(): number ----@nodiscard -function seq.range(start, finish) end - ----@generic T ----@param iter T[]|fun(): T|pl.Sequence ----@param condn fun(val: T): boolean ----@return integer ----@nodiscard -function seq.count(iter, condn) end - ----@generic T, A ----@param iter T[]|fun(): T|pl.Sequence ----@param condn fun(val: T, arg: A): boolean ----@return integer ----@nodiscard -function seq.count(iter, condn) end - ----count the number of elements in the sequence which satisfy the predicate ----@generic T, A ----@param iter T[]|fun(): T|pl.Sequence -- a sequence ----@param condn pl.BoolBinOpString -- a predicate function (must return either true or false) ----@param arg T -- optional argument to be passed to predicate as second argument. ----@return integer -- count ----@nodiscard -function seq.count(iter, condn, arg) end - ----return the minimum and the maximum value of the sequence. ----@param iter number[]|fun(): number|pl.Sequence -- a sequence ----@return number -- minimum value ----@return number -- maximum value ----@nodiscard -function seq.minmax(iter) end - ----return the sum and element count of the sequence. ----@param iter number[]|fun(): number|pl.Sequence -- a sequence ----@param fn? fun(val: number): number -- an optional function to apply to the values ----@return number -- the sum ----@return integer -- the element count ----@nodiscard -function seq.sum(iter, fn) end - ----create a table from the sequence. (This will make the result in a `List`.) ----@generic T ----@param iter T[]|fun(): T -- a sequence ----@return pl.List -- a List ----@nodiscard ---- ----Usage: ---- ----```lua ----seq.copy(seq.list(ls)) == ls ---- ----seq.copy(seq.list {1,2,3}) == List{1,2,3} ----``` -function seq.copy(iter) end - ----create a table of pairs from the double-valued sequence. ----@generic K, V, I1, I2 ----@param iter fun(i1: I1, i2: I2): (K, V)|pl.Sequence -- a double-valued sequence ----@param i1? I1 -- used to capture extra iterator values as with `pairs` & `ipairs` ----@param i2? I2 -- used to capture extra iterator values as with `pairs` & `ipairs` ----@return { [1]: K, [2]: V }[] -- a list-like table ----@nodiscard ---- ----Usage: ---- ----```lua ----seq.copy2(ipairs{10,20,30}) == {{1,10},{2,20},{3,30}} ----``` -function seq.copy2(iter, i1, i2) end - ----create a table of 'tuples' from a multi-valued sequence. ----A generalization of `seq.copy2` ----@param iter any[]|fun(): (...: any)|pl.Sequence -- a multiple-valued sequence ----@return any[] -- a list-like table ----@nodiscard -function seq.copy_tuples(iter) end - ----@param n integer ----@return fun(): number ----@nodiscard -function seq.random(n) end - ----@param n integer ----@param l integer ----@return fun(): integer ----@nodiscard -function seq.random(n, l) end - ----return an iterator of random numbers. ----@param n integer -- the length of the sequence ----@param l integer -- same as the first optional argument to `math.random` ----@param u integer -- same as the second optional argument to `math.random` ----@return fun(): integer -- a sequence ----@nodiscard -function seq.random(n, l, u) end - ----return an iterator to the sorted elements of a sequence. ----@generic T ----@param iter fun(): T|pl.Sequence -- a sequence ----@param comp fun(a: T, b: T): boolean -- an optional comparison function (comp(x,y) is true if x < y) ----@return fun(): T ----@nodiscard -function seq.sort(iter, comp) end - ----return an iterator which returns elements of two sequences. ----@generic T, U ----@param iter1 T[]|fun(): T|pl.Sequence -- a sequence ----@param iter2 U[]|fun(): U|pl.Sequence -- a sequence ----@return fun(): (T, U) ----@nodiscard ---- ----Usage: ---- ----```lua ----for x,y in seq.zip(ls1,ls2) do ... end ----``` -function seq.zip(iter1, iter2) end - ---- Makes a table where the key/values are the values and value counts of the sequence. ---- ----This version works with 'hashable' values like strings and numbers. ---- ----`pl.tablex.count_map` is more general. ----@generic T ----@param iter T[]|fun(): T|pl.Sequence -- a sequence ----@return pl.Map -- a map-like table ----@nodiscard -function seq.count_map(iter) end - ----@generic T ----@param iter T[]|fun(): T|pl.Sequence ----@return fun(): T ----@nodiscard -function seq.unique(iter) end - ----given a sequence, return all the unique values in that sequence. ----@generic T ----@param iter T[]|fun(): T|pl.Sequence -- a sequence ----@param returns_table true -- true if we return a table, not a sequence ----@return T[] -- a sequence or a table; defaults to a sequence. ----@nodiscard -function seq.unique(iter, returns_table) end - ----print out a sequence iter with a separator. ----@generic T ----@param iter T[]|fun(): T|pl.Sequence -- a sequence ----@param sep? string -- the separator (default space) ----@param nfields? integer -- maximum number of values per line (default 7) ----@param fmt? fun(v: T): string -- optional format function for each value -function seq.printall(iter, sep, nfields, fmt) end - --- return an iterator running over every element of two sequences (concatenation). ----@generic T1, T2 ----@param iter1 fun(): T1|pl.Sequence -- a sequence ----@param iter2 fun(): T2|pl.Sequence -- a sequence ----@return fun(): T1|T2 ----@nodiscard -function seq.splice(iter1, iter2) end - ----@generic K, A, R ----@param fn fun(value1: K, value2: A): R ----@param iter fun(): (K, A)|pl.Sequence ----@return fun(): R ----@nodiscard -function seq.map(fn, iter) end - ----return a sequence where every element of a sequence has been transformed by ----a function. If you don't supply an argument, then the function will receive ----both values of a double-valued sequence, otherwise behaves rather like ----`tablex.map`. ----@generic K, A, R ----@param fn pl.BinOpString|pl.UnOpString|fun(value1: K, value2: A): R -- a function to apply to elements; may take two arguments ----@param iter K[]|fun(): K|pl.Sequence -- a sequence of one or two values ----@param arg A -- optional argument to pass to function. ----@return fun(): R ----@nodiscard -function seq.map(fn, iter, arg) end - ----@generic K, A ----@param iter fun(): (K, A)|pl.Sequence ----@param pred fun(value1: K, value2: A): boolean ----@return fun(): (K, A) ----@nodiscard -function seq.filter(iter, pred) end - ----@generic K, A ----@param iter fun(): (K, A)|pl.Sequence ----@param pred pl.BoolBinOpString ----@return fun(): (K, A) ----@nodiscard -function seq.filter(iter, pred) end - ----@generic K, A ----@param iter fun(): K|pl.Sequence ----@param pred fun(value1: K, value2: A): boolean ----@param arg A ----@return fun(): K ----@nodiscard -function seq.filter(iter, pred, arg) end - ----filter a sequence using a predicate function. ----@generic K, A ----@param iter fun(): K|pl.Sequence -- a sequence of one or two values ----@param pred pl.BoolBinOpString -- a boolean function; may take two arguments ----@param arg A -- optional argument to pass to function. ----@return fun(): K ----@nodiscard -function seq.filter(iter, pred, arg) end - ----@generic L, T ----@param fn fun(last: L, current: T): L ----@param iter fun(): T|pl.Sequence ----@param initval L ----@return L ----@nodiscard -function seq.reduce(fn, iter, initval) end - ----'reduce' a sequence using a binary function. ----@generic L, T ----@param fn pl.BinOpString -- a function of two arguments ----@param iter fun(): T|pl.Sequence -- a sequence ----@param initval L -- optional initial value ----@return L ----@nodiscard ---- ----Usage: ---- ----```lua ----seq.reduce(operator.add,seq.list{1,2,3,4}) == 10 ---- ----seq.reduce('-',{1,2,3,4,5}) == -13 ----``` -function seq.reduce(fn, iter, initval) end - ----@generic T ----@param fn fun(last: T, current: T): T ----@param iter fun(): T|pl.Sequence ----@return T ----@nodiscard -function seq.reduce(fn, iter) end - ----@generic T ----@param fn pl.BinOpString ----@param iter fun(): T|pl.Sequence ----@return T ----@nodiscard -function seq.reduce(fn, iter) end - ----take the first `n` values from the sequence. ----@generic T ----@param iter T[]|fun(): T|pl.Sequence -- a sequence of one or two values ----@param n integer -- number of items to take ----@return fun(): T -- a sequence of at most `n` items ----@nodiscard -function seq.take(iter, n) end - ----skip the first `n` values of a sequence ----@generic T ----@param iter T[]|fun(): T|pl.Sequence -- a sequence of one or more values ----@param n integer -- number of items to skip ----@return fun(): T ----@nodiscard -function seq.skip(iter, n) end - ---- a sequence with a sequence count and the original value. ----`enum(copy(ls))` is a roundabout way of saying `ipairs(ls)`. ----@generic T1, T2 ----@param iter T1[]|fun(): (T1, T2)|pl.Sequence -- a single or double valued sequence ----@return fun(): (integer, T1, T2) -- sequence of (i,v), i = 1..n and v is from iter. ----@nodiscard -function seq.enum(iter) end - ----@alias pl.ObjectWithMethodAndTwoArguments { [S]: fun(self: pl.ObjectWithMethodAndTwoArguments, arg1: A1, arg2: A2, ...: any): (...: any) } ----@alias pl.ObjectWithMethodAndOneArgument { [S]: fun(self: pl.ObjectWithMethodAndOneArgument, arg1: A): (...: any) } ----@alias pl.ObjectWithMethodAndNoArguments { [S]: fun(self: pl.ObjectWithMethodAndNoArguments): (...: any) } - ----map using a named method over a sequence. ----@generic S, A1, A2 ----@param iter pl.ObjectWithMethodAndTwoArguments[]|(fun(): pl.ObjectWithMethodAndTwoArguments)|pl.Sequence -- a sequence ----@param name S -- the method name ----@param arg1 A1 -- optional first extra argument ----@param arg2 A2 -- optional second extra argument ----@return fun(): (...: any) ----@nodiscard -function seq.mapmethod(iter, name, arg1, arg2) end - ----@generic S, A ----@param iter pl.ObjectWithMethodAndOneArgument[]|(fun(): pl.ObjectWithMethodAndOneArgument)|pl.Sequence ----@param name S ----@param arg1 A ----@return fun(): (...: any) ----@nodiscard -function seq.mapmethod(iter, name, arg1) end - ----@generic S ----@param iter pl.ObjectWithMethodAndNoArguments[]|(fun(): pl.ObjectWithMethodAndNoArguments)|pl.Sequence ----@param name S ----@return fun(): (...: any) ----@nodiscard -function seq.mapmethod(iter, name) end - ----returns a sequence of (last,current) values from another sequence. ----This will return S(i-1),S(i) if given S(i) ----@generic T ----@param iter T[]|fun(): T|pl.Sequence -- a sequence ----@nodiscard ----@return fun(): (T, T) -function seq.last(iter) end - ----call the function on each element of the sequence. ----@generic T ----@param iter T[] -- a sequence with up to 3 values ----@param fn fun(v: T) -- a function -function seq.foreach(iter, fn) end - ----call the function on each element of the sequence. ----@generic T1, T2, T3 ----@param iter fun(): (T1, T2, T3)|pl.Sequence -- a sequence with up to 3 values ----@param fn fun(v1: T1, v2: T2, v3: T3) -- a function -function seq.foreach(iter, fn) end - ----@class pl.Sequence ----@overload fun(): any ----@field iter fun(...: any): (...: any) -local Sequence = {} - ----count the number of elements in the sequence which satisfy the predicate ----@generic T, A ----@param self pl.Sequence ----@param condn pl.BoolBinOpString|fun(val: T, arg: A): boolean -- a predicate function (must return either true or false) ----@param arg A -- optional argument to be passed to predicate as second argument. ----@return integer -- count ----@nodiscard -function Sequence:count(condn, arg) end - ----@generic T ----@param self pl.Sequence ----@param condn fun(val: T): boolean ----@return integer ----@nodiscard -function Sequence:count(condn) end - ----return the minimum and the maximum value of the sequence. ----@generic T: number ----@param self pl.Sequence ----@return number -- minimum value ----@return number -- maximum value ----@nodiscard -function Sequence:minmax() end - ----return the sum and element count of the sequence. ----@generic T: number ----@param self pl.Sequence ----@param fn? fun(val: number): number -- an optional function to apply to the values ----@return number -- the sum ----@return integer -- the element count ----@nodiscard -function Sequence:sum(fn) end - ---- create a table from the sequence. (This will make the result in a `List`.) ----@generic T ----@param self pl.Sequence ----@return pl.List -- a List ----@nodiscard ---- ----Usage: ---- ----```lua ----seq.copy(seq.list(ls)) == ls ---- ----seq.copy(seq.list {1,2,3}) == List{1,2,3} ----``` -function Sequence:copy() end - ----create a table of pairs from the double-valued sequence. ----@generic K, V, I1, I2 ----@param self pl.Sequence ----@param i1? I1 -- used to capture extra iterator values as with `pairs` & `ipairs` ----@param i2? I2 -- used to capture extra iterator values as with `pairs` & `ipairs` ----@return { [1]: K, [2]: V }[] -- a list-like table ----@nodiscard ---- ----Usage: ---- ----```lua ----seq(ipairs{}):copy2({10,20,30}, 0) == {{1,10},{2,20},{3,30}} ----``` -function Sequence:copy2(i1, i2) end - ----create a table of 'tuples' from a multi-valued sequence. ----A generalization of `seq.copy2` ----@param self pl.Sequence ----@return any[] -- a list-like table ----@nodiscard -function Sequence:copy_tuples() end - ----return an iterator to the sorted elements of a sequence. ----@generic T ----@param self pl.Sequence ----@param comp fun(a: T, b: T): boolean -- an optional comparison function (comp(x,y) is true if x < y) ----@return pl.Sequence ----@nodiscard -function Sequence:sort(comp) end - ----return an iterator which returns elements of two sequences. ----@generic T, U ----@param self pl.Sequence ----@param iter2 U[]|fun(): U|pl.Sequence -- a sequence ----@return pl.Sequence ----@nodiscard ---- ----Usage: ---- ----```lua ----for x,y in seq.zip(ls1,ls2) do ... end ----``` -function Sequence:zip(iter2) end - ---- Makes a table where the key/values are the values and value counts of the sequence. ---- ----This version works with 'hashable' values like strings and numbers. ---- ----`pl.tablex.count_map` is more general. ----@generic T ----@param self pl.Sequence -- a sequence ----@return pl.Map -- a map-like table ----@nodiscard -function Sequence:count_map() end - ----given a sequence, return all the unique values in that sequence. ----@generic T ----@param self pl.Sequence -- a sequence ----@param returns_table true -- true if we return a table, not a sequence ----@return T[] -- a sequence or a table; defaults to a sequence. ----@nodiscard -function Sequence:unique(returns_table) end - ----@generic T ----@param self pl.Sequence ----@return pl.Sequence ----@nodiscard -function Sequence:unique() end - ----print out a sequence iter with a separator. ----@generic T ----@param self pl.Sequence -- a sequence ----@param sep? string -- the separator (default space) ----@param nfields? integer -- maximum number of values per line (default 7) ----@param fmt? fun(v: T): string -- optional format function for each value -function Sequence:printall(sep, nfields, fmt) end - --- return an iterator running over every element of two sequences (concatenation). ----@generic T2 ----@param self pl.Sequence ----@param iter2 fun(): T2|pl.Sequence -- a sequence ----@return pl.Sequence ----@nodiscard -function Sequence:splice(iter2) end - ----return a sequence where every element of a sequence has been transformed by ----a function. If you don't supply an argument, then the function will receive ----both values of a double-valued sequence, otherwise behaves rather like ----`tablex.map`. ----@generic K, A, R ----@param self pl.Sequence ----@param fn fun(value1: K, value2: A): R -- a function to apply to elements; may take two arguments ----@param arg A -- optional argument to pass to function. ----@return pl.Sequence ----@nodiscard -function Sequence:map(fn, arg) end - ----@generic A ----@param self pl.Sequence ----@param fn pl.BinOpString|pl.UnOpString ----@param arg A ----@return pl.Sequence ----@nodiscard -function Sequence:map(fn, arg) end - ----@generic K, A, R ----@param self pl.Sequence ----@param fn fun(value1: K, value2: A): R ----@return pl.Sequence ----@nodiscard -function Sequence:map(fn) end - ----@param self pl.Sequence ----@param fn pl.BinOpString|pl.UnOpString ----@return pl.Sequence ----@nodiscard -function Sequence:map(fn) end - ----filter a sequence using a predicate function. ----@generic K, A ----@param self pl.Sequence ----@param pred fun(value1: K, value2: A): boolean -- a boolean function; may take two arguments ----@param arg A -- optional argument to pass to function. ----@return pl.Sequence ----@nodiscard -function Sequence:filter(pred, arg) end - ----filter a sequence using a predicate function. ----@generic K, A ----@param self pl.Sequence ----@param pred pl.BoolBinOpString ----@param arg A ----@return pl.Sequence ----@nodiscard -function Sequence:filter(pred, arg) end - ----@generic K, A ----@param self pl.Sequence ----@param pred fun(value1: K, value2: A): boolean ----@return pl.Sequence ----@nodiscard -function Sequence:filter(pred) end - ----@generic K, A ----@param self pl.Sequence ----@param pred pl.BoolBinOpString ----@return pl.Sequence ----@nodiscard -function Sequence:filter(pred) end - ----'reduce' a sequence using a binary function. ----@generic L, T ----@param self pl.Sequence ----@param fn fun(last: L, current: T): L -- a function of two arguments ----@param initval L -- optional initial value ----@return L ----@nodiscard ---- ----Usage: ---- ----```lua ----seq.reduce(operator.add,seq.list{1,2,3,4}) == 10 ---- ----seq.reduce('-',{1,2,3,4,5}) == -13 ----``` -function Sequence:reduce(fn, initval) end - ----@generic L, T ----@param self pl.Sequence ----@param fn pl.BinOpString ----@param initval L ----@return L ----@nodiscard -function Sequence:reduce(fn, initval) end - ----@generic T ----@param self pl.Sequence ----@param fn fun(last: T, current: T): T ----@return T ----@nodiscard -function Sequence:reduce(fn) end - ----@generic T ----@param self pl.Sequence ----@param fn pl.BinOpString ----@return T ----@nodiscard -function Sequence:reduce(fn) end - ----take the first `n` values from the sequence. ----@param self pl.Sequence ----@param n integer -- number of items to take ----@return pl.Sequence ----@nodiscard -function Sequence:take(n) end - ----skip the first `n` values of a sequence ----@param self pl.Sequence ----@param n integer -- number of items to skip ----@return pl.Sequence ----@nodiscard -function Sequence:skip(n) end - ---- a sequence with a sequence count and the original value. ----`enum(copy(ls))` is a roundabout way of saying `ipairs(ls)`. ----@param self pl.Sequence ----@return pl.Sequence ----@nodiscard -function Sequence:enum() end - ----map using a named method over a sequence. ----@param self pl.Sequence ----@param name string -- the method name ----@param arg1 any -- optional first extra argument ----@param arg2 any -- optional second extra argument ----@return pl.Sequence ----@nodiscard -function Sequence:mapmethod(name, arg1, arg2) end - ----@param self pl.Sequence ----@param name string ----@param arg1 any ----@return pl.Sequence ----@nodiscard -function Sequence:mapmethod(name, arg1) end - ----@param self pl.Sequence ----@param name string ----@return pl.Sequence ----@nodiscard -function Sequence:mapmethod(name) end - ----returns a sequence of (last,current) values from another sequence. ----This will return S(i-1),S(i) if given S(i) ----@generic T ----@param self pl.Sequence ----@return pl.Sequence ----@nodiscard -function Sequence:last() end - ----call the function on each element of the sequence. ----@param self pl.Sequence ----@param fn fun(v1: any, v2: any, v3: any) -- a function -function Sequence:foreach(fn) end - -return seq diff --git a/.luacats/pl/sip.lua b/.luacats/pl/sip.lua deleted file mode 100644 index ca23408..0000000 --- a/.luacats/pl/sip.lua +++ /dev/null @@ -1,82 +0,0 @@ ----@meta ----# Module [`pl.sip`](https://lunarmodules.github.io/Penlight/libraries/pl.sip.html) ---- ----Simple Input Patterns (SIP). ---- ----SIP patterns start with '$', then a one-letter type, and then an optional variable in curly braces. ---- ----```lua ----sip.match('$v=$q','name="dolly"',res) ----==> res=={'name','dolly'} ----sip.match('($q{first},$q{second})','("john","smith")',res) ----==> res=={second='smith',first='john'} ----``` ---- ----Type names: ---- ----```lua ----v identifier ----i integer ----f floating-point ----q quoted string ----([{< match up to closing bracket ----``` ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/08-additional.md.html#Simple_Input_Patterns) -local sip = {} - ----@alias pl.SipOptions { at_start: boolean? } - ----convert a SIP pattern into the equivalent Lua string pattern. ----@param spec string -- a SIP pattern ----@param options pl.SipOptions -- a table; only the `at_start` field is currently meaningful and ensures that the pattern is anchored at the start of the string. ----@return string -- a Lua string pattern. ----@nodiscard -function sip.create_pattern(spec, options) end - ----convert a SIP pattern into a matching function. The returned function takes ----two arguments, the line and an empty table. If the line matched the pattern, ----then this function returns true and the table is filled with field-value ----pairs. ----@param spec string -- a SIP pattern ----@param options pl.SipOptions -- a table; only the `at_start` field is currently meaningful and ensures that the pattern is anchored at the start of the string. ----@return (fun(line: string, res: table): boolean)? -- a function if successful, or nil on error ----@return string? -- nil if successful, or an error message ----@nodiscard -function sip.compile(spec, options) end - ----match a SIP pattern against a string. ----@param spec string -- a SIP pattern ----@param line string -- a string ----@param res table -- a table to receive values ----@param options pl.SipOptions -- option table ----@return boolean ----@nodiscard -function sip.match(spec, line, res, options) end - ----match a SIP pattern against the start of a string. ----@param spec string -- a SIP pattern ----@param line string -- a string ----@param res table -- a table to receive values ----@return boolean ----@nodiscard -function sip.match_at_start(spec, line, res) end - ----given a pattern and a file object, return an iterator over the results ----@param spec string -- a SIP pattern ----@param f file* -- a file-like object ----@return fun(): (...: string) ----@nodiscard -function sip.fields(spec, f) end - ----register a match which will be used in the `sip.read` function. ----@param spec string -- a SIP pattern ----@param fun function -- a function to be called with the results of the match -function sip.pattern(spec, fun) end - ----enter a loop which applies all registered matches to the input file. ----@param f file* -- a file-like object ----@param matches ({[1]: string, [2]: fun(...: string)}|{[1]: string, [2]: fun(matches: {[string]: string })})[] -- optional list of {spec,fun} pairs, as for pattern above. -function sip.read(f, matches) end - -return sip diff --git a/.luacats/pl/strict.lua b/.luacats/pl/strict.lua deleted file mode 100644 index 034ffdf..0000000 --- a/.luacats/pl/strict.lua +++ /dev/null @@ -1,61 +0,0 @@ ----@meta ----# Module [`pl.strict`](https://lunarmodules.github.io/Penlight/libraries/pl.strict.html) ---- ----Checks uses of undeclared global variables. ---- ----All global variables must be 'declared' through a regular assignment (even ----assigning nil will do) in a main chunk before being used anywhere or ----assigned to inside a function. Existing metatables `__newindex` and `__index` ----metamethods are respected. ---- ----You can set any table to have strict behaviour using `strict.module`. Creating ----a new module with `strict.closed_module` makes the module immune to ----monkey-patching, if you don't wish to encourage monkey business. ---- ----If the global `PENLIGHT_NO_GLOBAL_STRICT` is defined, then this module won't ----make the global environment strict - if you just want to explicitly set ----table strictness. -local strict = {} - ----@param name? string ----@param mod nil ----@param predeclared? { [any]: true } ----@return table ----@nodiscard -function strict.module(name, mod, predeclared) end - ----make an existing table strict. ----@param name? string -- name of table ----@param mod table -- the table to protect - if nil then we'll return a new table ----@param predeclared? { [any]: true } -- table of variables that are to be considered predeclared. ----@return table mod -- the given table, or a new table ---- ----Usage: ---- ----```lua ----local M = { hello = "world" } ----strict.module ("Awesome_Module", M, { ---- Lua = true, -- defines allowed keys ----}) ---- ----assert(M.hello == "world") ----assert(M.Lua == nil) -- access allowed, but has no value yet ----M.Lua = "Rocks" ----assert(M.Lua == "Rocks") ----M.not_allowed = "bad boy" -- throws an error ----``` -function strict.module(name, mod, predeclared) end - ----make all tables in a table strict. So `strict.make_all_strict(_G)` prevents ----monkey-patching of any global table ----@param T table -- the table containing the tables to protect. Table `T` itself will NOT be protected. -function strict.make_all_strict(T) end - ----make a new module table which is closed to further changes. ----@param mod table -- module table ----@param name string -- module name ----@return table ----@nodiscard -function strict.closed_module(mod, name) end - -return strict diff --git a/.luacats/pl/stringio.lua b/.luacats/pl/stringio.lua deleted file mode 100644 index d116698..0000000 --- a/.luacats/pl/stringio.lua +++ /dev/null @@ -1,94 +0,0 @@ ----@meta ----# Module [`pl.stringio`](https://lunarmodules.github.io/Penlight/libraries/pl.stringio.html) ---- ----Reading and writing strings using file-like objects. ---- ----```lua ----f = stringio.open(text) ----l1 = f:read() -- read first line ----n,m = f:read ('*n','*n') -- read two numbers ----for line in f:lines() do print(line) end -- iterate over all lines ----f = stringio.create() ----f:write('hello') ----f:write('dolly') ----assert(f:value(),'hellodolly') ----``` ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/03-strings.md.html#File_style_I_O_on_Strings). -local stringio = {} - ----@class pl.StringIOWriter -local stringIOWriter = {} - ----@param self pl.StringIOWriter ----@param ... string -function stringIOWriter:write(...) end - ----@param self pl.StringIOWriter ----@param fmt string ----@param ... any -function stringIOWriter:writef(fmt, ...) end - ----@param self pl.StringIOWriter ----@return string ----@nodiscard -function stringIOWriter:value() end - ----for compatibility only -function stringIOWriter:close() end - ----for compatibility only -function stringIOWriter:seek() end - ----@class pl.StringIOReader -local stringIOReader = {} - ----@param ... "*l"|"*L"|"*a"|"*n"|integer ----@return string|integer ... -function stringIOReader:read(...) end - ----@param self pl.StringIOReader ----@param whence "set"|"cur"|"end" ----@param offset? integer -function stringIOReader:seek(whence, offset) end - ----@param ... "*l"|"*L"|"*a"|"*n"|integer ----@return fun(): (...: string|integer) ----@nodiscard -function stringIOReader:lines(...) end - ----for compatibility only -function stringIOReader:close() end - ----create a file-like object which can be used to construct a string. The ----resulting object has an extra `value()` method for retrieving the string ----value. Implements `file:write`, `file:seek`, `file:lines`, plus an extra ----`writef` method which works like `utils.printf`. ----@return pl.StringIOWriter ----@nodiscard ---- ----Usage: ---- ----```lua ----f = stringio.create() ----f:write('hello, dolly\n') ----print(f:value()) ----``` -function stringio.create() end - ----create a file-like object for reading from a given string. Implements ----`file:read`. ----@param s string -- The input string. ----@return pl.StringIOReader ----@nodiscard ---- ----Usage: ---- ----```lua ----f = stringio.open '20 10' ----x,y = f:read ('*n','*n') ----assert(x == 20 and y == 10) ----``` -function stringio.open(s) end - -return stringio diff --git a/.luacats/pl/stringx.lua b/.luacats/pl/stringx.lua deleted file mode 100644 index 2da918c..0000000 --- a/.luacats/pl/stringx.lua +++ /dev/null @@ -1,466 +0,0 @@ ----@meta ----# Module [`pl.stringx`](https://lunarmodules.github.io/Penlight/libraries/pl.stringx.html) ---- ----Python-style extended string library. ---- ----see 3.6.1 of the Python reference. If you want to make these available as ----string methods, then say `stringx.import()` to bring them into the standard ----[string](https://www.lua.org/manual/5.1/manual.html#5.4) table. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/03-strings.md.html#) ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#) ---- [`pl.types`](https://lunarmodules.github.io/Penlight/libraries/pl.types.html#) -local stringx = {} - ----does `s` only contain alphabetic characters? ----@param s string -- a string ----@return boolean ----@nodiscard -function stringx.isalpha(s) end - ----does `s` only contain digits? ----@param s string -- a string ----@return boolean ----@nodiscard -function stringx.isdigit(s) end - ----does s only contain alphanumeric characters? ----@param s string -- a string ----@return boolean ----@nodiscard -function stringx.isalnum(s) end - ----does `s` only contain whitespace? Matches on pattern '%s' so matches space, ----newline, tabs, etc. ----@param s string -- a string ----@return boolean ----@nodiscard -function stringx.isspace(s) end - ----does `s` only contain lower case characters? ----@param s string -- a string ----@return boolean ----@nodiscard -function stringx.islower(s) end - ----does `s` only contain upper case characters? ----@param s string -- a string ----@return boolean ----@nodiscard -function stringx.isupper(s) end - ----does `s` start with `prefix` or one of prefixes? ----@param s string -- a string ----@param prefix string[]|string -- a string or an array of strings ----@return boolean ----@nodiscard -function stringx.startswith(s, prefix) end - ----does `s` end with `suffix` or one of suffixes? ----@param s string -- a string ----@param suffix string[]|string -- a string or an array of strings ----@return boolean ----@nodiscard -function stringx.endswith(s, suffix) end - ----concatenate the strings using this string as a delimiter. Note that the ----arguments are reversed from `table.concat`. ----@param s string -- the string ----@param seq (string|number)[] -- a table of strings or numbers ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.join(' ', {1,2,3}) == '1 2 3' ----``` -function stringx.join(s, seq) end - ----Split a string into a list of lines. "\r", "\n", and "\r\n" are considered ----line ends. They are not included in the lines unless keepends is passed. ----Terminal line end does not produce an extra line. Splitting an empty string ----results in an empty list. ----@param s string -- the string. ----@param keep_ends? boolean -- include line ends. ----@return string[] -- List of lines ----@nodiscard -function stringx.splitlines(s, keep_ends) end - ----split a string into a list of strings using a delimiter. ----@param s string -- the string ----@param re? string -- a delimiter (defaults to whitespace) ----@param n? integer -- maximum number of results ----@return pl.List -- List ----@nodiscard ---- ----Usage: ---- ----```lua ----#(stringx.split('one two')) == 2 ---- ----stringx.split('one,two,three', ',') == List{ 'one', 'two', 'three' } ---- ----stringx.split('one,two,three', ',', 2) == List{ 'one', 'two,three' } ----``` -function stringx.split(s, re, n) end - ----replace all tabs in `s` with `tabsize` spaces. If not specified, `tabsize` ----defaults to 8. Tab stops will be honored. ----@param s string -- the string ----@param tabsize? integer -- number of spaces to expand each tab (defaults to 8) ----@return string -- expanded string ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.expandtabs('\tone,two,three', 4) == ' one,two,three' ---- ----stringx.expandtabs(' \tone,two,three', 4) == ' one,two,three' ----``` -function stringx.expandtabs(s, tabsize) end - ----find index of first instance of `sub` in `s` from the left. ----@param s string -- the string ----@param sub string -- substring ----@param first? integer -- first index ----@param last? integer -- last index ----@return integer? -- start index, or nil if not found ----@nodiscard -function stringx.lfind(s, sub, first, last) end - ----find index of first instance of sub in s from the right. ----@param s string -- the string ----@param sub string -- substring ----@param first? integer -- first index ----@param last? integer -- last index ----@return integer? -- start index, or nil if not found ----@nodiscard -function stringx.rfind(s, sub, first, last) end - ----replace up to `n` instances of `old` by `new` in the string `s`. If `n` is ----not present, replace all instances. ----@param s string -- the string ----@param old string -- the target substring ----@param new string -- the substitution ----@param n? integer -- optional maximum number of substitutions ----@return string -- result string ----@nodiscard -function stringx.replace(s, old, new, n) end - ----count all instances of `sub` in `s`. ----@param s string -- the string ----@param sub string -- substring ----@param allow_overlap? boolean -- allow matches to overlap ----@return integer ----@nodiscard ---- ----Usage: ---- ----```lua ----assert(stringx.count('banana', 'ana') == 1) ----assert(stringx.count('banana', 'ana', true) == 2) ----``` -function stringx.count(s, sub, allow_overlap) end - ----left-justify `s` with width `w`. ----@param s string -- the string ----@param w integer -- width of justification ----@param ch? string -- padding character (default `' '`) ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.ljust('hello', 10, '*') == '*****hello' ----``` -function stringx.ljust(s, w, ch) end - ----right-justify `s` with width `w`. ----@param s string -- the string ----@param w integer -- width of justification ----@param ch? string -- padding character (default `' '`) ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.rjust('hello', 10, '*') == 'hello*****' ----``` -function stringx.rjust(s, w, ch) end - ----center-justify `s` with width `w`. ----@param s string -- the string ----@param w integer -- width of justification ----@param ch? string -- padding character (default `' '`) ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.center('hello', 10, '*') == '**hello***' ----``` -function stringx.center(s, w, ch) end - ---- trim any characters on the left of `s`. ----@param s string -- the string ----@param chrs? string -- defaults to any whitespace character, but can be a string of characters to be trimmed ----@return string ----@nodiscard -function stringx.lstrip(s, chrs) end - ----trim any characters on the right of `s`. ----@param s string -- the string ----@param chrs? string -- defaults to any whitespace character, but can be a string of characters to be trimmed ----@return string ----@nodiscard -function stringx.rstrip(s, chrs) end - ----trim any characters on both left and right of `s`. ----@param s string -- the string ----@param chrs? string -- defaults to any whitespace character, but can be a string of characters to be trimmed ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.strip(' --== Hello ==-- ', "- =") --> 'Hello' ----``` -function stringx.strip(s, chrs) end - ----split a string using a pattern. Note that at least one value will be returned! ----@param s string -- the string ----@param re? string -- a Lua string pattern (defaults to whitespace) ----@return string, string ... -- the parts of the string ----@nodiscard ---- ----Usage: ---- ----```lua ----line = 'aaa=bbb' ----stringx.splitv(line, '=') == 'aaa', 'bbb' ----``` -function stringx.splitv(s, re) end - ----partition the string using first occurance of a delimiter ----@param s string -- the string ----@param ch string -- delimiter (match as plain string, no patterns) ----@return string -- part before `ch` ----@return string -- `ch` ----@return string -- part after `ch` ----@nodiscard ---- ----Usage: ---- ----```lua ----{stringx.partition('a,b,c', ',')} == {'a', ',', 'b,c'} ---- ----{stringx.partition('abc', 'x')} == {'abc', '', ''} ----``` -function stringx.partition(s, ch) end - ----partition the string using last occurance of a delimiter ----@param s string -- the string ----@param ch string -- delimiter (match as plain string, no patterns) ----@return string -- part before `ch` ----@return string -- `ch` ----@return string -- part after `ch` ----@nodiscard ---- ----Usage: ---- ----```lua ----{stringx.rpartition('a,b,c', ',')} == {'a,b', ',', 'c'} ---- ----{stringx.rpartition('abc', 'x')} == {'', '', 'abc'} ----``` -function stringx.rpartition(s, ch) end - ----return the 'character' at the index. ----@param s string -- the string ----@param idx integer -- an index (can be negative) ----@return string -- a substring of length 1 if successful, empty string otherwise. ----@nodiscard -function stringx.at(s, idx) end - ----indent a multiline string. ----@param s string -- the (multiline) string ----@param n integer -- the size of the indent ----@param ch string? -- the character to use when indenting (default `' '`) ----@return string -- indented string ----@nodiscard -function stringx.indent(s, n, ch) end - ----dedent a multiline string by removing any initial indent. Useful when ----working with `[[ ... ]]` strings. Empty lines are ignored. ----@param s string -- the (multiline) string ----@return string -- a string with initial indent zero. ----@nodiscard ---- ----Usage: ---- ----```lua ----local s = dedent [[ ---- One ---- ---- Two ---- ---- Three ----]] ---- ----assert(s == [[ ---- One ---- ---- Two ---- ----Three ----]]) ----``` -function stringx.dedent(s) end - ----format a paragraph into lines so that they fit into a line width. It will ----not break long words by default, so lines can be over the length to that ----extent. ----@param s string -- the string to format ----@param width? integer -- the margin width (default `70`) ----@param breaklong? boolean -- if truthy, words longer than the width given will be forced split. (default `false`) ----@return pl.List -- a list of lines (`List` object), use `stringx.fill` to return a string instead of a `List`. ----@nodiscard -function stringx.wrap(s, width, breaklong) end - ----format a paragraph so that it fits into a line width. ----@param s string -- the string to format ----@param width? integer -- the margin width (default `70`) ----@param breaklong? boolean -- if truthy, words longer than the width given will be forced split. (default `false`) ----@return string -- a string, use `stringx.wrap` to return a list of lines instead of a string. -function stringx.fill(s, width, breaklong) end - ----@class pl.Template ----Creates a new `Template` class. This is a shortcut to `Template.new(tmpl)`. ----@operator call(string): pl.Template -local prototype_Template = {} - -stringx.Template = prototype_Template - ----Creates a new Template class. ----@param tmpl string -- the template string ----@return pl.Template ----@nodiscard -function prototype_Template.new(tmpl) end - ----substitute values into a template, throwing an error. This will throw an ----error if no name is found. ----@param tbl {[string]: string|number|false} -- a table of name-value pairs. ----@return string -- string with place holders substituted ----@nodiscard -function prototype_Template:substitute(tbl) end - ----substitute values into a template. This version just passes unknown names ----through. ----@param tbl {[string]: string|number|false} -- a table of name-value pairs. ----@return string -- string with place holders substituted ----@nodiscard -function prototype_Template:safe_substitute(tbl) end - ----substitute values into a template, preserving indentation. ---- ----If the value is a multiline string or a template, it will insert the lines ----at the correct indentation. ---- ----Furthermore, if a template, then that template will be substituted using ----the same table. ----@param tbl {[string]: string|number|false} -- a table of name-value pairs. ----@return string -- string with place holders substituted ----@nodiscard -function prototype_Template:indent_substitute(tbl) end - ----return an iterator over all lines in a string ----@param s string -- the string ----@return fun(): string -- an iterator ----@nodiscard ---- ----Usage: ---- ----```lua ----local line_no = 1 ----for line in stringx.lines(some_text) do ---- print(line_no, line) ---- line_no = line_no + 1 ----end ----``` -function stringx.lines(s) end - ----inital word letters uppercase ('title case'). Here 'words' mean chunks of ----non-space characters. ----@param s string -- the string ----@return string -- a string with each word's first letter uppercase ----@nodiscard ---- ----Usage: ---- ----```lua ----stringx.title("hello world") == "Hello World" ----``` -function stringx.title(s) end - ----Return a shortened version of a string. Fits string within `w` characters. ----Removed characters are marked with ellipsis. ----@param s string -- the string ----@param w integer -- the maximum size allowed ----@param tail? boolean -- `true` if we want to show the end of the string (head otherwise) ----@return string ----@nodiscard ---- ----Usage: ---- ----```lua ----('1234567890'):shorten(8) == '12345...' ---- ----('1234567890'):shorten(8, true) == '...67890' ---- ----('1234567890'):shorten(20) == '1234567890' ----``` -function stringx.shorten(s, w, tail) end - ----Quote the given string and preserve any control or escape characters, such ----that reloading the string in Lua returns the same result. ----@param s string -- the string to be quoted ----@return string -- The quoted string. ----@nodiscard -function stringx.quote_string(s) end - ----Python-style formatting operator. Calling text.format_operator() overloads the ----`%` operator for strings to give Python/Ruby style formated output. This is ----extended to also do template-like substitution for map-like data. ---- ----Note this goes further than the original, and will allow these cases: ---- ----1. a single value ----2. a list of values ----3. a map of var=value pairs ----4. a function, as in gsub ---- ----For the last two cases, it uses $-variable substitution. ---- ----See the [lua-users wiki](http://lua-users.org/wiki/StringInterpolation) ---- ----Usage: ---- ----```lua ----require 'pl.text'.format_operator() ----local out1 = '%s = %5.3f' % {'PI',math.pi} --> 'PI = 3.142' ----local out2 = '$name = $value' % {name='dog',value='Pluto'} --> 'dog = Pluto' ----``` -function stringx.format_operator() end - ----import the `stringx` functions into the global string (meta)table -function stringx.import() end - -return stringx diff --git a/.luacats/pl/tablex.lua b/.luacats/pl/tablex.lua deleted file mode 100644 index 340b1ed..0000000 --- a/.luacats/pl/tablex.lua +++ /dev/null @@ -1,698 +0,0 @@ ----@meta ----# Module [`pl.tablex`](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html) ---- ----Extended operations on Lua tables. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/02-arrays.md.html#Useful_Operations_on_Tables) ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [`pl.types`](https://lunarmodules.github.io/Penlight/libraries/pl.types.html#) -local tablex = {} - ----total number of elements in this table. Note that this is distinct from ----`#t`, which is the number of values in the array part; this value will ----always be greater or equal. The difference gives the size of the hash part, ----for practical purposes. Works for any object with a `__pairs` metamethod. ----@param t table -- a table ----@return integer -- the size ----@nodiscard -function tablex.size(t) end - ----return a list of all values in a table indexed by another list. ----@generic K, V ----@param tbl { [K]: V } -- a table ----@param idx K[] -- an index table (a list of keys) ----@return V[] -- a list-like table ----@nodiscard ---- ----Usage: ---- ----```lua ----index_by({10, 20, 30, 40}, {2, 4}) == {20, 40} ---- ----index_by({one=1, two=2, three=3}, {'one', 'three'}) == {1, 3} ----``` -function tablex.index_by(tbl, idx) end - ----@param fun fun(val: any, ...: any): any ----@param t table ----@param ... any ----@return table t -function tablex.transform(fun, t, ...) end - ----apply a function to all values of a table, in-place. Any extra arguments are ----passed to the function. ----@param fun pl.OpString -- A function that takes at least one argument ----@param t table -- a table ----@param ... any -- extra arguments passed to `fun` ----@return table t -function tablex.transform(fun, t, ...) end - ----generate a table of all numbers in a range. This is consistent with a ----numerical for loop. ----@param start integer -- number ----@param finish integer -- number ----@param step? integer -- make this negative for `start < finish` (default 1) ----@return integer[] ----@nodiscard -function tablex.range(start, finish, step) end - ----@generic T ----@param fun fun(memo: T, val: T): T ----@param t T[] ----@return T ----@nodiscard -function tablex.reduce(fun, t) end - ----@generic T, U ----@param fun fun(memo: U, val: T): U ----@param t T[] ----@param memo U ----@return U ----@nodiscard -function tablex.reduce(fun, t, memo) end - ----'reduce' a list using a binary function. ----@param fun pl.BinOpString -- a function of two arguments ----@param t any[] -- a list-like table ----@param memo? any -- optional initial memo value. Defaults to first value in table. ----@return any -- the result of the function ----@nodiscard ---- ----Usage: ---- ----```lua ----reduce('+', {1, 2, 3, 4}) == 10 ----``` -function tablex.reduce(fun, t, memo) end - ----create an index map from a list-like table. The original values become keys, ----and the associated values are the indices into the original list. ----@generic T ----@param t T[] -- a list-like table ----@return {[T]: integer} -- a map-like table ----@nodiscard -function tablex.index_map(t) end - ----create a set from a list-like table. A set is a table where the original ----values become keys, and the associated values are all true. ----@generic T ----@param t T[] -- a list-like table ----@return pl.Set -- a set (a map-like table) ----@nodiscard -function tablex.makeset(t) end - ----the union of two map-like tables. If there are duplicate keys, the second ----table wins. ----@param t1 table -- a table ----@param t2 table -- a table ----@return table ----@nodiscard -function tablex.union(t1, t2) end - ----the intersection of two map-like tables. ----@param t1 table -- a table ----@param t2 table -- a table ----@return table ----@nodiscard -function tablex.intersection(t1, t2) end - ----@generic T ----@param t T[] ----@param cmp? fun(a: T, b: T): boolean ----@return { [T]: integer } ----@nodiscard -function tablex.count_map(t, cmp) end - ----A table where the key/values are the values and value counts of the table. ----@generic T ----@param t T[] -- a list-like table ----@param cmp? pl.BoolBinOpString -- a function that defines equality (otherwise uses `==`) ----@return { [T]: integer } -- a map-like table ----@nodiscard -function tablex.count_map(t, cmp) end - ----set an array range to a value. If it's a function we use the result of applying it to the indices. ----@generic T ----@param t T[] -- a list-like table ----@param val T -- a value ----@param i1? integer -- start range (default `1`) ----@param i2? integer -- end range (default `#t`) -function tablex.set(t, val, i1, i2) end - ----create a new array of specified size with initial value. ----@generic T ----@param n integer -- size ----@param val? T -- an initial value (can be `nil`, but don't expect `#` to work!) ----@return T[] -- a table ----@nodiscard -function tablex.new(n, val) end - ----clear out the contents of a table. ----@param t any[] -- a list ----@param istart? integer -- optional start position -function tablex.clear(t, istart) end - ----remove a range of values from a table. End of range may be negative. ----@generic T ----@param t T[] -- a list-like table ----@param i1? integer -- start index ----@param i2? integer -- end index ----@return T[] t -- the table -function tablex.removevalues(t, i1, i2) end - ----modifies a table to be read only. This only offers weak protection. Tables ----can still be modified with `table.insert` and `rawset`. ---- ----NOTE: for Lua 5.1 length, pairs and ipairs will not work, since the ----equivalent metamethods are only available in Lua 5.2 and newer. ----@param t table -- the table ----@return table -- the table read only (a proxy). ----@nodiscard -function tablex.readonly(t) end - ----copy a table into another, in-place. ----@param dest table -- destination table ----@param src table -- source (actually any iterable object) ----@return table dest -- first table -function tablex.update(dest, src) end - ----make a shallow copy of a table ----@param t table -- an iterable source ----@return table -- new table ----@nodiscard -function tablex.copy(t) end - ----make a deep copy of a table, recursively copying all the keys and fields. ----This supports cycles in tables; cycles will be reproduced in the copy. This ----will also set the copied table's metatable to that of the original. ----@param t table -- A table ----@return table -- new table ----@nodiscard -function tablex.deepcopy(t) end - ----copy an array into another one, clearing `dest` after `idest+nsrc`, if ----necessary. ----@param dest any[] -- a list-like table ----@param src any[] -- a list-like table ----@param idest? integer -- where to start copying values into destination (default 1) ----@param isrc? integer -- where to start copying values from source (default 1) ----@param nsrc? integer -- number of elements to copy from source (default `#src`) ----@return any[] dest -function tablex.icopy(dest, src, idest, isrc, nsrc) end - ----copy an array into another one. ----@param dest any[] -- a list-like table ----@param src any[] -- a list-like table ----@param idest? integer -- where to start copying values into destination (default 1) ----@param isrc? integer -- where to start copying values from source (default 1) ----@param nsrc? integer -- number of elements to copy from source (default `#src`) ----@return any[] dest -function tablex.move(dest, src, idest, isrc, nsrc) end - ----insert values into a table. similar to `table.insert` but inserts values ----from given table values, not the object itself, into table `t` at position ----`pos`. ----@param t any[] -- the list ----@param pos? integer -- (default is at end) ----@param values any[] ----@return any[] t -- table argument -function tablex.insertvalues(t, pos, values) end - ----compare two values. if they are tables, then compare their keys and fields ----recursively. ----@param t1 any -- A value ----@param t2 any -- A value ----@param ignore_mt? boolean -- if `true`, ignore `__eq` metamethod (default `false`) ----@param eps? number -- if defined, then used for checking nearness in any number comparisons ----@return boolean ----@nodiscard -function tablex.deepcompare(t1, t2, ignore_mt, eps) end - ----@param t1 any[] ----@param t2 any[] ----@param cmp fun(v1: any, v2: any): boolean ----@return boolean ----@nodiscard -function tablex.compare(t1, t2, cmp) end - ----compare two arrays using a predicate. ----@param t1 any[] -- an array ----@param t2 any[] -- an array ----@param cmp pl.BoolBinOpString -- A comparison function; `bool = cmp(t1_value, t2_value)` ----@return boolean ----@nodiscard ---- ----Usage: ---- ----```lua ----assert(tablex.compare({ 1, 2, 3 }, { 1, 2, 3 }, "==")) ---- ----assert(tablex.compare( ---- {1, 2, 3, hello = "world"}, -- fields are not compared! ---- {1, 2, 3}, function(v1, v2) return v1 == v2 end) ----``` -function tablex.compare(t1, t2, cmp) end - ----@param t1 any[] ----@param t2 any[] ----@param cmp? fun(v1: any, v2: any): boolean ----@return boolean ----@nodiscard -function tablex.compare_no_order(t1, t2, cmp) end - ----compare two list-like tables using an optional predicate, without regard ----for element order. ----@param t1 any[] -- a list-like table ----@param t2 any[] -- a list-like table ----@param cmp? pl.BoolBinOpString -- A comparison function (may be nil) ----@return boolean ----@nodiscard -function tablex.compare_no_order(t1, t2, cmp) end - ----return the index of a value in a list. Like `string.find`, there is an ----optional index to start searching, which can be negative. ----@generic T ----@param t T[] -- A list-like table ----@param val T -- A value ----@param idx? integer -- index to start; `-1` means last element, etc (default `1`) ----@return integer? -- index of value or `nil` if not found ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.find({10, 20, 30}, 20) == 2 ----tablex.find({'a', 'b', 'a', 'c'}, 'a', 2) == 3 ----``` -function tablex.find(t, val, idx) end - ----return the index of a value in a list, searching from the end. Like ----`string.find`, there is an optional index to start searching, which can be ----negative. ----@generic T ----@param t T[] -- A list-like table ----@param val T -- A value ----@param idx? integer -- index to start; `-1` means last element, etc (default `#t`) ----@return integer? -- index of value or nil if not found ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.rfind({10,10,10},10) == 3 ----``` -function tablex.rfind(t, val, idx) end - ----@param t table ----@param cmp fun(v, arg): any ----@param arg? any ----@return any?, any -function tablex.find_if(t, cmp, arg) end - ----return the index (or key) of a value in a table using a comparison function. ----NOTE: the 2nd return value of this function, the value returned by the ----comparison function, has a limitation that it cannot be false. Because if it ----is, then it indicates the comparison failed, and the function will continue ----the search. See examples. ----@param t table -- A table ----@param cmp pl.BoolBinOpString -- A comparison function ----@param arg? any -- an optional second argument to the function ----@return any? -- index of value, or nil if not found ----@return boolean? -- value returned by comparison function (cannot be `false`!) ----@nodiscard ---- ----Usage: ---- ----```lua ------ using an operator ----local lst = { "Rudolph", true, false, 15 } ----local idx, cmp_result = tablex.rfind(lst, "==", "Rudolph") ----assert(idx == 1) ----assert(cmp_result == true) ---- ----local idx, cmp_result = tablex.rfind(lst, "==", false) ----assert(idx == 3) ----assert(cmp_result == true) -- looking up 'false' works! ---- ------ using a function returning the value looked up ----local cmp = function(v1, v2) return v1 == v2 and v2 end ----local idx, cmp_result = tablex.rfind(lst, cmp, "Rudolph") ----assert(idx == 1) ----assert(cmp_result == "Rudolph") -- the value is returned ---- ------ NOTE: this fails, since 'false' cannot be returned! ----local idx, cmp_result = tablex.rfind(lst, cmp, false) ----assert(idx == nil) -- looking up 'false' failed! ----assert(cmp_result == nil) ----``` -function tablex.find_if(t, cmp, arg) end - ----find a value in a table by recursive search. ----@param t table -- the table ----@param value any -- the value ----@param exclude? table[] -- any tables to avoid searching ----@return string -- a fieldspec, e.g. `'a.b'` or `'math.sin'` ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.search(_G, math.sin, {package.path}) == 'math.sin' ----``` -function tablex.search(t, value, exclude) end - ----@param fun fun(val, ...): any ----@param t table ----@param ... any ----@return table ----@nodiscard -function tablex.map(fun, t, ...) end - ----apply a function to all values of a table. This returns a table of the ----results. Any extra arguments are passed to the function. ----@param fun pl.OpString -- A function that takes at least one argument ----@param t table -- A table ----@param ... any -- optional arguments ----@return table ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.map(function(v) return v*v end, {10, 20, 30, fred=2}) == {100, 400, 900, fred=4} ----``` -function tablex.map(fun, t, ...) end - ----@generic T, U ----@param fun fun(val: T, ...: any): U ----@param t T[] ----@param ... any ----@return pl.List ----@nodiscard -function tablex.imap(fun, t, ...) end - ----apply a function to all values of a list. This returns a table of the ----results. Any extra arguments are passed to the function. ----@generic T ----@param fun pl.OpString -- A function that takes at least one argument ----@param t T[] -- a table (applies to array part) ----@param ... any -- optional arguments ----@return pl.List -- a list-like table ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.imap(function(v) return v*v end, {10, 20, 30, fred=2}) == {100, 400, 900} ----``` -function tablex.imap(fun, t, ...) end - ----@alias pl.ObjectWithMethod { [S]: fun(self: pl.ObjectWithMethod, ...: A...): R } - ----apply a named method to values from a table. ----@param name string -- the method name ----@param t table[] -- a list-like table ----@param ... any -- extra arguments to the method ----@return pl.List -- a List with the results of the method (1st result only) ----@nodiscard ---- ----Usage: ---- ----```lua ----local Car = {} ----Car.__index = Car ----function Car.new(car) ---- return setmetatable(car or {}, Car) ----end ----Car.speed = 0 ----function Car:faster(increase) ---- self.speed = self.speed + increase ---- return self.speed ----end ---- ----local ferrari = Car.new{ name = "Ferrari" } ----local lamborghini = Car.new{ name = "Lamborghini", speed = 50 } ----local cars = { ferrari, lamborghini } ---- ----assert(ferrari.speed == 0) ----assert(lamborghini.speed == 50) ----tablex.map_named_method("faster", cars, 10) ----assert(ferrari.speed == 10) ----assert(lamborghini.speed == 60) ----``` -function tablex.map_named_method(name, t, ...) end - ----@param fun fun(val1, val2, ...): any ----@param t1 table ----@param t2 table ----@param ... any ----@return table ----@nodiscard -function tablex.map2(fun, t1, t2, ...) end - ----apply a function to values from two tables. ----@param fun pl.OpString -- a function of at least two arguments ----@param t1 table -- a table ----@param t2 table -- a table ----@param ... any -- extra arguments ----@return table -- a table ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.map2('+', {1, 2, 3, m=4}, {10, 20, 30, m=40}) == {11, 22, 33, m=44} ----``` -function tablex.map2(fun, t1, t2, ...) end - ----@param fun fun(val1, val2, ...): any ----@param t1 any[] ----@param t2 any[] ----@param ... any ----@return any[] ----@nodiscard -function tablex.imap2(fun, t1, t2, ...) end - ----apply a function to values from two arrays. The result will be the length of the shortest array. ----@param fun pl.OpString -- a function of at least two arguments ----@param t1 any[] -- a list-like table ----@param t2 any[] -- a list-like table ----@param ... any -- extra arguments ----@return any[] ----@nodiscard ---- ----Usage: ---- ----```lua ----tablex.imap2('+', {1, 2, 3, m=4}, {10, 20, 30, m=40}) == {11, 22, 33} ----``` -function tablex.imap2(fun, t1, t2, ...) end - ----@param fun function ----@param ... table ----@return table ----@nodiscard -function tablex.mapn(fun, ...) end - ----Apply a function to a number of tables. A more general version of ----`tablex.map`. The result is a table containing the result of applying that ----function to the ith value of each table. Length of output list is the ----minimum length of all the lists ----@param fun pl.OpString -- A function that takes `n` tables ----@param ... table -- `n` tables ----@return table ----@nodiscard ---- ----Usage: ---- ----```lua ----mapn(function(x,y,z) return x+y+z end, {1, 2, 3}, {10, 20, 30}, {100, 200, 300}) == {111, 222, 333} ---- ----mapn(math.max, {1, 20, 300}, {10, 2, 3}, {100, 200, 100}) == {100, 200, 300} ----``` -function tablex.mapn(fun, ...) end - ----@param fun fun(k, v, ...: any): (new_v: any, new_k: any) ----@param t table ----@param ... any ----@return table ----@nodiscard -function tablex.pairmap(fun, t, ...) end - ----call the function with the key and value pairs from a table. The function ----can return a value and a key (note the order!). If both are not nil, then ----this pair is inserted into the result: if the key already exists, we convert ----the value for that key into a table and append into it. If only value is not ----nil, then it is appended to the result. ----@param fun pl.OpString -- A function which will be passed each key and value as arguments, plus any extra arguments to `tablex.pairmap`. ----@param t table -- A table ----@param ... any -- optional arguments ----@return table ----@nodiscard ---- ----Usage: ---- ----```lua ----pairmap(function(k,v) return v end,{fred=10,bonzo=20}) == {10,20} or {20,10} ---- ----pairmap(function(k, v) return {k, v}, k end,{one=1, two=2}) == {one={'one', 1}, two={'two', 2}} ----``` -function tablex.pairmap(fun, t, ...) end - ----@generic T, A ----@param t T[] ----@param pred fun(val: T, arg: A): any ----@param arg A ----@return T[] ----@nodiscard -function tablex.filter(t, pred, arg) end - ----filter an array's values using a predicate function ----@generic T ----@param t T[] -- a list-like table ----@param pred pl.BoolBinOpString -- a boolean function ----@param arg any -- optional argument to be passed as second argument of the predicate ----@return T[] ----@nodiscard -function tablex.filter(t, pred, arg) end - ----@generic K, V ----@param t { [K]: V } ----@param fun fun(value: V, key: K, ...: any) ----@param ... any -function tablex.foreach(t, fun, ...) end - ----apply a function to all elements of a table. The arguments to the function ----will be the value, the key and finally any extra arguments passed to this ----function. Note that the Lua 5.0 function `table.foreach` passed the key ----first. ----@param t table -- a table ----@param fun pl.OpString -- a function on the elements ----@param ... any -- extra arguments passed to `fun` -function tablex.foreach(t, fun, ...) end - ----@generic T ----@param t T[] ----@param fun fun(value: T, index: integer, ...: any) ----@param ... any -function tablex.foreachi(t, fun, ...) end - ----apply a function to all elements of a list-like table in order. The ----arguments to the function will be the value, the index and finally any extra ----arguments passed to this function. ----@param t any[] -- a table ----@param fun pl.OpString -- a function with at least one argument ----@param ... any -- optional arguments -function tablex.foreachi(t, fun, ...) end - ----@generic K, V ----@param t { [K]: V } ----@param f? fun(key1: K, key2: K): boolean ----@return fun(): (K, V) ----@nodiscard -function tablex.sort(t, f) end - ----return an iterator to a table sorted by its keys ----@generic K, V ----@param t { [K]: V } -- the table ----@param f? pl.BoolOrderedBinOpString -- an optional comparison function (`f(x, y)` is true if `x < y`) ----@return fun(): (K, V) -- an iterator to traverse elements sorted by the values ----@nodiscard ---- ----Usage: ---- ----```lua ----for k, v in tablex.sort(t) do print(k, v) end ----``` -function tablex.sort(t, f) end - ----@generic K, V ----@param t { [K]: V } ----@param f? fun(value1: V, value2: V): boolean ----@return fun(): (K, V) ----@nodiscard -function tablex.sortv(t, f) end - ----return an iterator to a table sorted by its values ----@generic K, V ----@param t { [K]: V } -- the table ----@param f? pl.BoolOrderedBinOpString -- an optional comparison function (`f(x, y)` is true if `x < y`) ----@return fun(): (K, V) -- an iterator to traverse elements sorted by the values ----@nodiscard ---- ----Usage: ---- ----```lua ----for k, v in tablex.sortv(t) do print(k, v) end ----``` -function tablex.sortv(t, f) end - ----return all the keys of a table in arbitrary order. ----@generic K ----@param t { [K]: any } -- the table ----@return K[] -- A list-like table where the values are the keys of the input table ----@nodiscard -function tablex.keys(t) end - ----return all the values of the table in arbitrary order ----@generic V ----@param t { [any]: V } -- the table ----@return V[] -- A list-like table where the values are the values of the input table ----@nodiscard -function tablex.values(t) end - ----Extract a range from a table, like `string.sub`. If first or last are ----negative then they are relative to the end of the list eg. `sub(t,-2)` gives ----last 2 entries in a list, and `sub(t,-4,-2)` gives from -4th to -2nd ----@generic T ----@param t T[] -- a list-like table ----@param first integer -- An index ----@param last integer -- An index ----@return pl.List -- a new List ----@nodiscard -function tablex.sub(t, first, last) end - ----combine two tables, either as union or intersection. Corresponds to set ----operations for sets but more general. Not particularly useful for list-like ----tables. ----@param t1 table -- a table ----@param t2 table -- a table ----@param dup? boolean -- `true` for a union, `false` for an intersection. (default `false`) ----@return table ----@nodiscard ---- ----Usage: ---- ----```lua ----merge({alice=23, fred=34}, {bob=25, fred=34}) == {fred=34} ---- ----merge({alice=23, fred=34}, {bob=25, fred=34}, true) == {bob=25, fred=34, alice=23} ----``` -function tablex.merge(t1, t2, dup) end - ----a new table which is the difference of two tables. With sets (where the ----values are all true) this is set difference and symmetric difference ----depending on the third parameter. ----@param s1 table -- a map-like table or set ----@param s2 table -- a map-like table or set ----@param symm? boolean -- symmetric difference (default `false`) ----@return table -- a map-like table or set ----@nodiscard -function tablex.difference(s1, s2, symm) end - ----return a table where each element is a table of the ith values of an ----arbitrary number of tables. It is equivalent to a matrix transpose. ----@param ... any[] -- arrays to be zipped ----@return any[][] ----@nodiscard ---- ----Usage: ---- ----```lua ----zip({10, 20, 30}, {100, 200, 300}) == {{10, 100}, {20, 200}, {30, 300}} ----``` -function tablex.zip(...) end - -return tablex diff --git a/.luacats/pl/template.lua b/.luacats/pl/template.lua deleted file mode 100644 index f4a98be..0000000 --- a/.luacats/pl/template.lua +++ /dev/null @@ -1,115 +0,0 @@ ----@meta ----# Module [`pl.template`](https://lunarmodules.github.io/Penlight/libraries/pl.template.html) ---- ----A template preprocessor. ---- ----Originally by [Ricki Lake](http://lua-users.org/wiki/SlightlyLessSimpleLuaPreprocessor) ---- ----There are two rules: ---- ----* lines starting with `#` are Lua ----* otherwise, `$(expr)` is the result of evaluating `expr` ---- ----Example: ---- ----```lua ----# for i = 1,3 do ---- $(i) Hello, Word! ----# end ----===> ----1 Hello, Word! ----2 Hello, Word! ----3 Hello, Word! ----``` ---- ----Other escape characters can be used, when the defaults conflict with the ----output language. ---- ----```lua ----> for _,n in pairs{'one','two','three'} do ----static int l_${n} (luaState *state); ----> end ----``` ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/03-strings.md.html#Another_Style_of_Template). ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#) -local template = {} - ----expand the template using the specified environment. This function will ----compile and render the template. For more performant recurring usage use the ----two step approach by using `template.compile` and `ct:render`. There are six ----special fields in the environment table `env` ---- ----* `_parent`: continue looking up in this table (e.g. `_parent=_G`). ----* `_brackets`: bracket pair that wraps inline Lua expressions, default is `()`. ----* `_escape`: character marking Lua lines, default is `#`. ----* `_inline_escape`: character marking inline Lua expression, default is `$`. ----* `_chunk_name`: chunk name for loaded templates, used if there is an error in Lua code. Default is `TMP`. ----* `_debug`: if truthy, the generated code will be printed upon a render error ---- ----@param str string -- the template string ----@param env? table -- the environment ----@return string? rendered_template -- `nil` on error ----@return string? error -- `nil` on success ----@return string? source_code -- only returned if the debug option is used ----@nodiscard -function template.substitute(str, env) end - ----@class pl.CompiledTemplate -local CompiledTemplate = {} - ----executes the previously compiled template and renders it. ----@param env? table -- the environment. ----@param parent? table -- continue looking up in this table (e.g. `parent=_G`) ----@param db? boolean -- if truthy, it will print the code upon a render error (provided the template was compiled with the debug option). ----@return string? rendered_template -- `nil` on error ----@return string? error -- `nil` on success ----@return string? source_code -- only returned if the template was compiled with the debug option ----@nodiscard -function CompiledTemplate:render(env, parent, db) end - ----@class pl.CompiledTemplate.Options ----chunk name for loaded templates, used if there is an error in Lua code. ----Default is `TMP`. ----@field chunk_name? string ----character marking Lua lines, default is `#`. ----@field escape? string ----character marking inline Lua expression, default is `$`. ----@field inline_escape? string ----bracket pair that wraps inline Lua expressions, default is `()`. ----@field inline_brackets? string ----string to replace newline characters, default is `nil` (not replacing newlines). ----@field newline? string ----if truthy, the generated source code will be retained within the compiled template object, default is `nil`. ----@field debug? any - ----compiles the template. Returns an object that can repeatedly be rendered ----without parsing/compiling the template again. The options passed in the opts ----table support the following options: ---- ---- ----* `chunk_name`: chunk name for loaded templates, used if there is an error in Lua code. Default is `TMP`. ----* `escape`: character marking Lua lines, default is `#`. ----* `inline_escape`: character marking inline Lua expression, default is `$`. ----* `inline_brackets`: bracket pair that wraps inline Lua expressions, default is `()`. ----* `newline`: string to replace newline characters, default is `nil` (not replacing newlines). ----* `debug`: if truthy, the generated source code will be retained within the compiled template object, default is `nil`. ---- ----@param str string -- the template string ----@param opts? pl.CompiledTemplate.Options -- the compilation options to use ----@return pl.CompiledTemplate? ct -- `nil` on error ----@return string? error -- `nil` on success ----@return string? source_code -- only returned if the debug option is used ----@nodiscard ---- ----Usage: ---- ----```lua ----local ct, err = template.compile(my_template) ----local rendered, err = ct:render(my_env, parent) ----``` -function template.compile(str, opts) end - -return template diff --git a/.luacats/pl/test.lua b/.luacats/pl/test.lua deleted file mode 100644 index e0c5de2..0000000 --- a/.luacats/pl/test.lua +++ /dev/null @@ -1,102 +0,0 @@ -local utils = require("pl.utils") - ----@meta ----# Module [`pl.test`](https://lunarmodules.github.io/Penlight/libraries/pl.test.html) ---- ----Useful test utilities. ---- ----```lua ----test.asserteq({1,2},{1,2}) -- can compare tables ----test.asserteq(1.2,1.19,0.02) -- compare FP numbers within precision ----T = test.tuple -- used for comparing multiple results ----test.asserteq(T(string.find(" me","me")),T(2,3)) ----``` ---- ----Dependencies: ---- [pl.utils](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#), ---- [pl.tablex](https://lunarmodules.github.io/Penlight/libraries/pl.tablex.html#), ---- [pl.pretty](https://lunarmodules.github.io/Penlight/libraries/pl.pretty.html#), ---- [pl.path](https://lunarmodules.github.io/Penlight/libraries/pl.path.html#), ---- [debug](https://www.lua.org/manual/5.1/manual.html#5.9) -local test = {} - ----error handling for test results. By default, this writes to stderr and ----exits the program. Re-define this function to raise an error and/or redirect output ----comment ----@param file string ----@param line string|integer ----@param got_text string ----@param needed_text string ----@param msg? string -- (default `"these values were not equal"`) -function test.error_handler(file, line, got_text, needed_text, msg) end - ----general test complain message. Useful for composing new test functions (see ----`tests/tablex.lua` for an example) ----@param x any -- a value ----@param y any -- value to compare first value against ----@param msg string -- message ----@param where? integer -- extra level offset for errors -function test.complain(x, y, msg, where) end - ----like assert, except takes two arguments that must be equal and can be ----tables. If they are plain tables, it will use `tablex.deepcompare`. ----@param x any -- any value ----@param y any -- a value equal to x ----@param eps? number -- an optional tolerance for numerical comparisons ----@param where? integer -- extra level offset -function test.asserteq(x, y, eps, where) end - ----assert that the first string matches the second. ----@param s1 string -- a string ----@param s2 string -- a string ----@param where? integer -- extra level offset -function test.assertmatch(s1, s2, where) end - ----assert that the function raises a particular error. ----@param fn function|{ [1]: function, [integer]: any } -- a function or a table of the form {function, arg1, ...} ----@param e string -- a string to match the error against ----@param where? integer -- extra level offset -function test.assertraise(fn, e, where) end - ----a version of asserteq that takes two pairs of values. `x1==y1` and `x2==y2` ----must be true. Useful for functions that naturally return two values. ----@param x1 any -- any value ----@param x2 any -- any value ----@param y1 any -- any value ----@param y2 any -- any value ----@param where? integer -- extra level offset -function test.asserteq2(x1, x2, y1, y2, where) end - ----@class pl.Tuple ----@operator len: integer -local Tuple = {} - -Tuple.unpack = utils.unpack - ----encode an arbitrary argument list as a tuple. This can be used to compare ----to other argument lists, which is very useful for testing functions which ----return a number of values. Unlike regular array-like tables ('sequences') ----they may contain nils. Tuples understand equality and know how to print ----themselves out. The `#` operator is defined to be the size, irrespective of ----any nils, and there is an `unpack` method. ----@param ... any ----@return pl.Tuple ----@nodiscard ---- ----Usage: ---- ----```lua ----asserteq(tuple(('ab'):find 'a'), tuple(1, 1)) ----``` -function test.tuple(...) end - ----Time a function. Call the function a given number of times, and report the ----number of seconds taken, together with a message. Any extra arguments will ----be passed to the function. ----@param msg string -- a descriptive message ----@param n integer -- number of times to call the function ----@param fun function -- the function ----@param ... any -- optional arguments to `fun` -function test.timer(msg, n, fun, ...) end - -return test diff --git a/.luacats/pl/text.lua b/.luacats/pl/text.lua deleted file mode 100644 index 64d7a81..0000000 --- a/.luacats/pl/text.lua +++ /dev/null @@ -1,22 +0,0 @@ ----@meta ----# Module [`pl.text`](https://lunarmodules.github.io/Penlight/libraries/pl.text.html) ---- ----Text processing utilities. ---- ----This provides a `Template` class (modeled after the same from the Python ----libraries, see `string.Template`). It also provides similar functions to ----those found in the `textwrap` module. ---- ----IMPORTANT: this module has been deprecated and will be removed in a future ----version (2.0). The contents of this module have moved to the `pl.stringx` ----module. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/03-strings.md.html#String_Templates). ---- ----Dependencies: ---- [`pl.stringx`](https://lunarmodules.github.io/Penlight/libraries/pl.stringx.html#), ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html#) ----@deprecated -- use pl.stringx -local text = require("pl.stringx") - -return text diff --git a/.luacats/pl/types.lua b/.luacats/pl/types.lua deleted file mode 100644 index 943cb86..0000000 --- a/.luacats/pl/types.lua +++ /dev/null @@ -1,98 +0,0 @@ -local utils = require("pl.utils") - ----@meta ----# Module [`pl.types`](https://lunarmodules.github.io/Penlight/libraries/pl.types.html) ---- ----Dealing with Detailed Type Information ---- ----Dependencies: ---- [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html) -local types = {} - ----is the object either a function or a callable object? ----@param obj any -- Object to check. ----@return boolean ----@nodiscard -function types.is_callable(obj) end - -types.is_type = utils.is_type - ----a string representation of a type. For tables and userdata with metatables, ----we assume that the metatable has a `_name` field. If the field is not ----present it will return 'unknown table' or 'unknown userdata'. Lua file ----objects return the type 'file'. ----@param obj any -- an object ----@return string -- a string like 'number', 'table', 'file' or 'List' ----@nodiscard -function types.type(obj) end - ----is this number an integer? ----@param x number -- a number ----@return boolean ----@nodiscard ---- ----Raises: error if `x` is not a number -function types.is_integer(x) end - ----Check if the object is "empty". An object is considered empty if it is: ---- ---- * `nil` ---- * a table without any items (key-value pairs or indexes) ---- * a string with no content (`""`) ---- * not a nil/table/string ----@param o any -- The object to check if it is empty. ----@param ignore_spaces? boolean -- If the object is a string and this is `true`, the string is considered empty if it only contains spaces. ----@return boolean? -- `true` if the object is empty, otherwise a falsy value. ----@nodiscard -function types.is_empty(o, ignore_spaces) end - ----is an object 'array-like'? An object is array like if: ---- ---- * it is a table, or ---- * it has a metatable with `__len` and `__index` methods ---- ----NOTE: since `__len` is 5.2+, on 5.1 it usually returns `false` for userdata ---- ----@param val any -- any value ----@return boolean? -- `true` if the object is array-like, otherwise a falsy value. ----@nodiscard -function types.is_indexable(val) end - ----can an object be iterated over with [`pairs`](https://www.lua.org/manual/5.1/manual.html#pdf-pairs)? An object is iterable if: ---- ---- * it is a table, or ---- * it has a metatable with a `__pairs` meta method ---- ----NOTE: since `__pairs` is 5.2+, on 5.1 it usually returns `false` for userdata ---- ----@param val any -- any value ----@return boolean? -- `true` if the object is iterable, otherwise a falsy value. ----@nodiscard -function types.is_iterable(val) end - ----can an object accept new key-value pairs? An object is iterable if: ---- ---- * it is a table, or ---- * it has a metatable with a `__newindex` meta method ---- ----@param val any -- any value ----@return boolean? -- `true` if the object is writeable, otherwise a falsy value. ----@nodiscard -function types.is_writeable(val) end - ----Convert to a boolean value. True values are: ---- ---- * `boolean`: true. ---- * `string`: `'yes'`, `'y'`, `'true'`, `'t'`, `'1'` or additional strings specified by `true_strs`. ---- * `number`: Any non-zero value. ---- * `table`: Is not empty and `check_objs` is true. ---- * everything else: Is not `nil` and `check_objs` is true. ---- ----@param o any -- The object to evaluate ----@param true_strs? string[] -- Additional strings that when matched should evaluate to true. Comparison is case insensitive. This should be a List of strings. E.g. "ja" to support German. ----@param check_objs? boolean -- True if objects should be evaluated (default `false`). ----@return boolean -- `true` if the input evaluates to `true`, otherwise `false`. ----@nodiscard -function types.to_bool(o, true_strs, check_objs) end - -return types diff --git a/.luacats/pl/url.lua b/.luacats/pl/url.lua deleted file mode 100644 index 1d8370b..0000000 --- a/.luacats/pl/url.lua +++ /dev/null @@ -1,20 +0,0 @@ ----@meta ----# Module [`pl.url`](https://lunarmodules.github.io/Penlight/libraries/pl.url.html) ---- ----Python-style URL quoting library. -local url = {} - ----Quote the url, replacing special characters using the '%xx' escape. ----@param s string -- the string ----@param quote_plus? boolean -- Also escape slashes and replace spaces by plus signs (default `false`). ----@return string -- The quoted string, or if `s` wasn't a string, just plain unaltered `s`. ----@nodiscard -function url.quote(s, quote_plus) end - ----Unquote the url, replacing '%xx' escapes and plus signs. ----@param s string -- the string ----@return string -- The unquoted string, or if `s` wasn't a string, just plain unaltered `s`. ----@nodiscard -function url.unquote(s) end - -return url diff --git a/.luacats/pl/utils.lua b/.luacats/pl/utils.lua deleted file mode 100644 index a8b9410..0000000 --- a/.luacats/pl/utils.lua +++ /dev/null @@ -1,567 +0,0 @@ ----@meta ----# Module [`pl.utils`](https://lunarmodules.github.io/Penlight/libraries/pl.utils.html) ---- ----Generally useful routines. ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/01-introduction.md.html#Generally_useful_functions_). ---- ----Dependencies: ---- [`pl.compat`](https://lunarmodules.github.io/Penlight/libraries/pl.compat.html#), ---- all exported fields and functions from [`pl.compat`](https://lunarmodules.github.io/Penlight/libraries/pl.compat.html#) are also available in this module. -local utils = {} - ----pack an argument list into a table. ----@param ... any -- any arguments ----@return { n: integer, [integer]: any } -- a table with field `n` set to the length ----@nodiscard -function utils.pack(...) end - ----unpack a table and return its contents. ---- ----NOTE: this implementation differs from the Lua implementation in the way ----that this one DOES honor the `n` field in the table t, such that it is 'nil-safe'. ----@param t table -- table to unpack ----@param i? integer -- index from which to start unpacking, defaults to `1` ----@param j? integer -- index of the last element to unpack, defaults to `t.n` or else `#t` ----@return any ... -- multiple return values from the table ----@nodiscard ---- ----Usage: ---- ----```lua ----local t = table.pack(nil, nil, nil, 4) ----local a, b, c, d = table.unpack(t) -- this unpack is NOT nil-safe, so d == nil ---- ----local a, b, c, d = utils.unpack(t) -- this is nil-safe, so d == 4 ----``` -function utils.unpack(t, i, j) end - ----print an arbitrary number of arguments using a format. Output will be sent to `stdout`. ----@param fmt string -- The format (see [`string.format`](https://www.lua.org/manual/5.1/manual.html#pdf-string.format)) ----@param ... any -- Extra arguments for format -function utils.printf(fmt, ...) end - ----write an arbitrary number of arguments to a file using a format. ----@param f file* -- File handle to write to. ----@param fmt string -- The format (see [`string.format`](https://www.lua.org/manual/5.1/manual.html#pdf-string.format)) ----@param ... any -- Extra arguments for format -function utils.fprintf(f, fmt, ...) end - ----take a table and 'inject' it into the local namespace. ----@param t table|string -- The table (table), or module name (string), defaults to this `utils` module table ----@param T table -- An optional destination table (defaults to caller's environment) -function utils.import(t, T) end - ----return either of two values, depending on a condition. ----@param cond any -- A condition ----@param value1 any -- Value returned if `cond` is truthy ----@param value2 any -- Value returned if `cond` is falsy ----@return any ----@nodiscard -function utils.choose(cond, value1, value2) end - ----convert an array of values to strings. ----@param t any[] -- a list-like table ----@param temp? table -- buffer to use, otherwise allocate ----@param tostr? fun(value: any, index: integer): string -- custom `tostring` function, called with `(value, index)`. Defaults to [`tostring`](https://www.lua.org/manual/5.1/manual.html#pdf-tostring). ----@return string ----@nodiscard ----@nodiscard -function utils.array_tostring(t, temp, tostr) end - ----is the object of the specified type? If the type is a string, then use type, ----otherwise compare with metatable ----@param obj any -- An object to check ----@param tp string|table -- String or metatable of what type it should be ----@return boolean ----@nodiscard ---- ----Usage: ---- ----```lua ----utils.is_type("hello world", "string") --> true ---- ------ or check metatable ----local my_mt = {} ----local my_obj = setmetatable(my_obj, my_mt) ----utils.is_type(my_obj, my_mt) --> true ----``` -function utils.is_type(obj, tp) end - ----an iterator with indices, similar to [`ipairs`](https://www.lua.org/manual/5.1/manual.html#pdf-ipairs), ----but with a range. This is a nil-safe index based iterator that will return ----`nil` when there is a hole in a list. To be safe ensure that table `t.n` ----contains the length. ----@param t table -- the table to iterate over ----@param i_start? integer -- start index (default `1`) ----@param i_end? integer -- end index (default `t.n` or `#t`) ----@param step? integer -- step size (default `1`) ----@return fun(): (index: integer, value: any) -- index and value at index (which can be `nil`!) ----@nodiscard ---- ----Usage: ---- ----```lua ----local t = utils.pack(nil, 123, nil) -- adds an n field when packing ---- ----for i, v in utils.npairs(t, 2) do -- start at index 2 ---- t[i] = tostring(t[i]) ----end ---- ------ t = { n = 3, [2] = "123", [3] = "nil" } ----``` -function utils.npairs(t, i_start, i_end, step) end - ----an iterator over all non-integer keys (inverse of [`ipairs`](https://www.lua.org/manual/5.1/manual.html#pdf-ipairs) ----). It will skip any key that is an integer number, so negative indices or an ----array with holes will not return those either (so it returns slightly less ----than 'the inverse of [ipairs](https://www.lua.org/manual/5.1/manual.html#pdf-ipairs)' ----). ---- ----This uses [`pairs`](https://www.lua.org/manual/5.1/manual.html#pdf-pairs) ----under the hood, so any value that is iterable using [`pairs`](https://www.lua.org/manual/5.1/manual.html#pdf-pairs) ----will work with this function. ----@param t table -- the table to iterate over ----@return fun(): (key: any, value: any) ----@nodiscard ---- ----Usage: ---- ----```lua ----local t = { ---- "hello", ---- "world", ---- hello = "hallo", ---- world = "Welt", ----} ---- ----for k, v in utils.kpairs(t) do ---- print("German: ", v) ----end ---- ------ output; ------ German: hallo ------ German: Welt ----``` -function utils.kpairs(t) end - ----Some standard patterns -utils.patterns = { - ---floating point number - FLOAT = "[%+%-%d]%d*%.?%d*[eE]?[%+%-]?%d*", - - ---integer number - INTEGER = "[+%-%d]%d*", - - ---identifier - IDEN = "[%a_][%w_]*", - - -- note that I use '\\\\' here for documentation accuracy - - ---file - FILE = "[%a%.\\\\][:%][%w%._%-\\\\]*", -} - ----Standard meta-tables as used by other Penlight modules -utils.stdmt = { - ---the `List` metatable - List = { _name = "List" }, - - ---the `Map` metatable - Map = { _name = "Map" }, - - ---the `Set` metatable - Set = { _name = "Set" }, - - ---the `MultiMap` metatable - MultiMap = { _name = "MultiMap" }, -} - ----assert that the given argument is in fact of the correct type. ----@param n integer -- argument index ----@param val any -- the value ----@param tp type -- the type ----@param verify? fun(val: any): boolean -- an optional verification function ----@param msg? string -- an optional custom message ----@param lev? integer -- optional stack position for trace (default `2`) ----@return any val -- the validated value ---- ----Raises: if `val` is not the correct type ---- ----Usage: ---- ----```lua ----local param1 = assert_arg(1,"hello",'table') --> error: argument 1 expected a 'table', got a 'string' ----local param4 = assert_arg(4,'!@#$%^&*','string',path.isdir,'not a directory') ---- --> error: argument 4: '!@#$%^&*' not a directory ----``` -function utils.assert_arg(n, val, tp, verify, msg, lev) end - ----creates an Enum or constants lookup table for improved error handling. This ----helps prevent magic strings in code by throwing errors for accessing ----non-existing values, and/or converting strings/identifiers to other values. ---- ----Calling on the object does the same, but returns a soft error; `nil + err`, if ----the call is successful (the key exists), it will return the value. ---- ----When calling with varargs or an array the values will be equal to the keys. ----The enum object is read-only. ----@param ... any -- the input for the Enum. If `...` or an array then the values in the Enum will be equal to the names (must be strings), if a hash-table then values remain (any type), and the keys must be strings. ----@return table enum_object -- Enum object (read-only table/object) ----@nodiscard ---- ----Usage: ---- ----```lua ------ Enum access at runtime ----local obj = {} ----obj.MOVEMENT = utils.enum("FORWARD", "REVERSE", "LEFT", "RIGHT") ---- ----if current_movement == obj.MOVEMENT.FORWARD then ---- -- do something ---- ----elseif current_movement == obj.MOVEMENT.REVERES then ---- -- throws error due to typo 'REVERES', so a silent mistake becomes a hard error ---- -- "'REVERES' is not a valid value (expected one of: 'FORWARD', 'REVERSE', 'LEFT', 'RIGHT')" ---- ----end ---- ---- ---- ------ standardized error codes ----local obj = { ---- ERR = utils.enum { ---- NOT_FOUND = "the item was not found", ---- OUT_OF_BOUNDS = "the index is outside the allowed range" ---- }, ---- ---- some_method = function(self) ---- return self.ERR.OUT_OF_BOUNDS ---- end, ----} ---- ----local result, err = obj:some_method() ----if not result then ---- if err == obj.ERR.NOT_FOUND then ---- -- check on error code, not magic strings ---- ---- else ---- -- return the error description, contained in the constant ---- return nil, "error: "..err -- "error: the index is outside the allowed range" ---- end ----end ---- ---- ---- ------ validating/converting user-input ----local color = "purple" ----local ansi_colors = utils.enum { ---- black = 30, ---- red = 31, ---- green = 32, ----} ----local color_code, err = ansi_colors(color) -- calling on the object, returns the value from the enum ----if not color_code then ---- print("bad 'color', " .. err) ---- -- "bad 'color', 'purple' is not a valid value (expected one of: 'black', 'red', 'green')" ---- os.exit(1) ----end ----``` -function utils.enum(...) end - ----process a function argument. This is used throughout Penlight and defines ----what is meant by a function: Something that is callable, or an operator ----string as defined by `pl.operator`, such as `'>'` or `'#'`. If a function factory ----has been registered for the type, it will be called to get the function. ----@param idx integer -- argument index ----@param f function|table|userdata -- a function, operator string, or callable object ----@param msg? string -- optional error message ----@return function -- a callable ---- ----Raises: if `idx` is not a number or if `f` is not callable ---- -function utils.function_arg(idx, f, msg) end - ----@param idx integer ----@param f pl.OpString ----@param msg? string ----@return function -function utils.function_arg(idx, f, msg) end - ----assert the common case that the argument is a string. ----@param n integer -- argument index ----@param val string -- a value that must be a string ----@return string val -- the validated value ---- ----Raises: `val` must be a string ---- ----Usage: ---- ----```lua ----local val = 42 ----local param2 = utils.assert_string(2, val) --> error: argument 2 expected a 'string', got a 'number' ----``` -function utils.assert_string(n, val) end - ----control the error strategy used by Penlight. This is a global setting that ----controls how `utils.raise` behaves: ---- ---- * `'default'`: return `nil + error` (this is the default) ---- * `'error'`: throw a Lua error ---- * `'exit'`: exit the program ---- ----@param mode "default"|"quit"|"error" -- either `'default'`, `'quit'` or `'error'` -function utils.on_error(mode) end - ----used by Penlight functions to return errors. Its global behaviour is ----controlled by `utils.on_error`. To use this function you MUST use it in ----conjunction with `return`, since it might return `nil + error`. ----@param err string -- the error string. ----@return nil, string ----@nodiscard ---- ----Usage: ---- ----```lua ----if some_condition then ---- return utils.raise("some condition was not met") -- MUST use 'return'! ----end ----``` -function utils.raise(err) end - ----return the contents of a file as a string ----@param filename string -- The file path ----@param is_bin? boolean -- open in binary mode (default `false`) ----@return string file_contents ----@nodiscard -function utils.readfile(filename, is_bin) end - ----write a string to a file ----@param filename string -- The file path ----@param str string -- The string ----@param is_bin boolean? -- open in binary mode ----@return boolean? ok -- `true` or `nil` ----@return string? err_msg -- error message ---- ----Raises: error if `filename` or `str` aren't strings -function utils.writefile(filename, str, is_bin) end - ----return the contents of a file as a list of lines ----@param filename string -- The file path ----@return string[] -- file contents as a table ----@nodiscard ---- ----Raises: error if `filename` is not a string -function utils.readlines(filename) end - ----execute a shell command and return the output. This function redirects the ----output to tempfiles and returns the content of those files. ----@param cmd string -- a shell command ----@param bin? boolean -- if `true`, read output as binary file ----@return boolean? ok -- `true` if successful ----@return integer return_code -- actual return code ----@return string stdout -- stdout output ----@return string stderr -- stderr output -function utils.executeex(cmd, bin) end - ----Quote and escape an argument of a command. Quotes a single (or list of) ----argument(s) of a command to be passed to [`os.execute`](https://www.lua.org/manual/5.1/manual.html#pdf-os.execute), ----`pl.utils.execute` or `pl.utils.executeex`. ----@param argument string|string[] -- the argument to quote. If a list then all arguments in the list will be returned as a single string quoted. ----@return string -- quoted and escaped argument. ----@nodiscard ---- ----Usage: ---- ----```lua ----local options = utils.quote_arg { ---- "-lluacov", ---- "-e", ---- "utils = print(require('pl.utils')._VERSION", ----} ------ returns: -lluacov -e 'utils = print(require('\''pl.utils'\'')._VERSION' ----``` -function utils.quote_arg(argument) end - ----error out of this program gracefully. ----@param code integer -- The exit code, defaults to `-1` if omitted ----@param msg string -- The exit message will be sent to `stderr` (will be formatted with extra parameters) ----@param ... any -- extra arguments for message's format ---- ----Usage: ---- ----```lua ----utils.quit(-1, "Error '%s' happened", "42") ------ is equivalent to ----utils.quit("Error '%s' happened", "42") --> Error '42' happened ----``` -function utils.quit(code, msg, ...) end - ----escape any Lua 'magic' characters in a string ----@param s string -- The input string ----@return string ----@nodiscard -function utils.escape(s) end - ----split a string into a list of strings separated by a delimiter. ----@param s string -- The input string ----@param re? string -- optional A Lua string pattern; defaults to '%s+' ----@param plain? boolean -- optional If truthy don't use Lua patterns ----@param n? integer -- optional maximum number of elements (if there are more, the last will remain un-split) ----@return string[] -- a list-like table ----@nodiscard ---- ----Raises: error if `s` is not a string -function utils.split(s, re, plain, n) end - ----split a string into a number of return values. Identical to `utils.split` ----but returns multiple sub-strings instead of a single list of sub-strings. ----@param s string -- the string ----@param re? string -- A Lua string pattern; defaults to '%s+' ----@param plain? boolean -- don't use Lua patterns ----@param n? integer -- optional maximum number of splits ----@return string ... -- `n` values ----@nodiscard ---- ----Usage: ---- ----```lua ----first, next = splitv('user=jane=doe', '=', false, 2) ----assert(first == "user") ----assert(next == "jane=doe") ----``` -function utils.splitv(s, re, plain, n) end - ----'memoize' a function (cache returned value for next call). This is useful if ----you have a function which is relatively expensive, but you don't know in ----advance what values will be required, so building a table upfront is ----wasteful/impossible. ----@generic K, R ----@param func fun(val: K): R -- a function of at least one argument ----@return fun(val: K): R -- a function with at least one argument, which is used as the key. ----@nodiscard -function utils.memoize(func) end - ----associate a function factory with a type. A function factory takes an object ----of the given type and returns a function for evaluating it ----@param mt table -- metatable ----@param fun function -- a callable that returns a function -function utils.add_function_factory(mt, fun) end - ----an anonymous function as a string. This string is either of the form ----`'|args| expression'` or is a function of one argument, `'_'` ----@param lf string -- function as a string ----@return function -- a function ----@nodiscard ---- ----Usage: ---- ----```lua ----string_lambda '|x|x+1' (2) == 3 ----string_lambda '_+1' (2) == 3 ----``` -function utils.string_lambda(lf) end - ----@generic P, X ----@param fn fun(p: P, x: X, ...: any) ----@param p P ----@return fun(x: X, ...: any) f ----@nodiscard -function utils.bind1(fn, p) end - ----bind the first argument of the function to a value. ----@param fn pl.BinOpString -- a function of at least two values (may be an operator string) ----@param p any -- a value ----@return fun(x: any, ...: any) f -- a function such that `f(x) == fn(p, x)` ----@nodiscard ---- ----Raises: if `f` is not callable ---- ----Usage: ---- ----```lua ----local function f(msg, name) ---- print(msg .. " " .. name) ----end ---- ----local hello = utils.bind1(f, "Hello") ---- ----print(hello("world")) --> "Hello world" ----print(hello("sunshine")) --> "Hello sunshine" ----``` -function utils.bind1(fn, p) end - ----@generic P, X ----@param fn fun(x: X, p: P, ...: any) ----@param p P ----@return fun(x: X, ...: any) f ----@nodiscard -function utils.bind2(fn, p) end - ----bind the second argument of the function to a value. ----@param fn pl.BinOpString -- a function of at least two values (may be an operator string) ----@param p any -- a value ----@return fun(x: any, ...: any) f ----@nodiscard ---- ----Raises: if `f` is not callable -function utils.bind2(fn, p) end - ----Sets a deprecation warning function. An application can override this ----function to support proper output of deprecation warnings. The warnings can ----be generated from libraries or functions by calling ----`utils.raise_deprecation`. The default function will write to the 'warn' ----system (introduced in Lua 5.4, or the compatibility function from the ----compat module for earlier versions). ---- ----Note: only applications should set/change this function, libraries should not. ----@param func? fun(msg: string, trace?: string) -- a callback with signature: `function(msg, trace)` both arguments are strings, the latter being optional. ---- ----Usage: ---- ----```lua ------ write to the Nginx logs with OpenResty ----utils.set_deprecation_func(function(msg, trace) ---- ngx.log(ngx.WARN, msg, (trace and (" " .. trace) or nil)) ----end) ---- ------ disable deprecation warnings ----utils.set_deprecation_func() ----``` -function utils.set_deprecation_func(func) end - ----@class pl.DeprecationOptions : table ----@field source? string ----@field message string ----@field version_removed? string ----@field deprecated_after? string ----@field no_trace? boolean - ----raises a deprecation warning. For options see the usage example below. ---- ----Note: the `opts.deprecated_after` field is the last version in which a ----feature or option was NOT YET deprecated! Because when writing the code it ----is quite often not known in what version the code will land. But the last ----released version is usually known. ----@param opts pl.DeprecationOptions -- options table ---- ----Usage: ---- ----```lua ----warn("@on") -- enable Lua warnings, they are usually off by default ---- ----function stringx.islower(str) ---- raise_deprecation { ---- source = "Penlight " .. utils._VERSION, -- optional ---- message = "function 'islower' was renamed to 'is_lower'", -- required ---- version_removed = "2.0.0", -- optional ---- deprecated_after = "1.2.3", -- optional ---- no_trace = true, -- optional ---- } ---- return stringx.is_lower(str) ----end ------ output: "[Penlight 1.9.2] function 'islower' was renamed to 'is_lower' (deprecated after 1.2.3, scheduled for removal in 2.0.0)" ----``` -function utils.raise_deprecation(opts) end - -return utils diff --git a/.luacats/pl/xml.lua b/.luacats/pl/xml.lua deleted file mode 100644 index f470576..0000000 --- a/.luacats/pl/xml.lua +++ /dev/null @@ -1,362 +0,0 @@ ----@meta ----# Module [`pl.xml`](https://lunarmodules.github.io/Penlight/libraries/pl.xml.html) ---- ----XML LOM Utilities. ---- ----This implements some useful things on [LOM](http://matthewwild.co.uk/projects/luaexpat/lom.html) ----documents, such as returned by lxp.lom.parse. In particular, it can convert ----LOM back into XML text, with optional pretty-printing control. It is based ----on `stanza.lua` from [Prosody](http://hg.prosody.im/trunk/file/4621c92d2368/util/stanza.lua) ---- ----```lua ----> d = xml.parse "alice" ----> = d ------> alice ----> = xml.tostring(d,'',' ') ------> ------> alice ------> ----``` ---- ----Can be used as a lightweight one-stop-shop for simple XML processing; a ----simple XML parser is included but the default is to use `lxp.lom` if it can ----be found. ---- ----```plain ----Prosody IM ----Copyright (C) 2008-2010 Matthew Wild ----Copyright (C) 2008-2010 Waqas Hussain-- ----classic Lua XML parser by Roberto Ierusalimschy. ----modified to output LOM format. ----http://lua-users.org/wiki/LuaXml ----``` ---- ----See [the Guide](https://lunarmodules.github.io/Penlight/manual/06-data.md.html#XML) ---- ----Soft Dependencies: ---- `lxp.lom` (fallback is to use basic Lua parser) ----@deprecated -local xml = {} - ----create a new document node. ----@param tag string -- the tag name ----@param attr? { [string]: string } -- attributes (table of name-value pairs) (default `{}`) ----@return pl.XMLNode -- the Node object ----@nodiscard ---- ----Usage: ---- ----```lua ----local doc = xml.new("main", { hello = "world", answer = "42" }) ----print(doc) -->
----``` -function xml.new(tag, attr) end - ----parse an XML document. By default, this uses `lxp.lom.parse`, but falls back ----to basic_parse, or if `use_basic` is truthy ----@param text_or_filename string -- file or string representation ----@param is_file? boolean -- whether `text_or_filename` is a file name or not (default `false`) ----@param use_basic? boolean -- do a basic parse (default `false`) ----@return pl.XMLNode? -- a parsed LOM document with the document metatatables set, `nil` on error ----@return string? error -- the error can either be a file error or a parse error ----@nodiscard -function xml.parse(text_or_filename, is_file, use_basic) end - ----Create a Node with a set of children (text or Nodes) and attributes. ----@param tag string -- a tag name ----@param items? pl.XMLNode|string|{ [string]: string, [integer]: pl.XMLNode|string} -- either a single child (text or Node), or a table where the hash part is the attributes and the list part is the children (text or Nodes). ----@return pl.XMLNode -- the new Node ----@nodiscard ---- ----Usage: ---- ----```lua ----local doc = xml.elem("top", "hello world") -- hello world ----local doc = xml.elem("main", xml.new("child")) --
----local doc = xml.elem("main", { "this ", "is ", "nice" }) --
this is nice
----local doc = xml.elem("main", { xml.new "this", ---- xml.new "is", ---- xml.new "nice" }) --
----local doc = xml.elem("main", { hello = "world" }) --
----local doc = xml.elem("main", { ---- "prefix", ---- xml.elem("child", { "this ", "is ", "nice"}), ---- "postfix", ---- attrib = "value" ----}) --
prefixthis is nicepostfix
" ----``` -function xml.elem(tag, items) end - ----given a list of names, return a number of element constructors. If passing a ----comma-separated string, then whitespace surrounding the values will be ----stripped. ---- ----The returned constructor functions are a shortcut to `xml.elem` where you no ----longer provide the tag-name, but only the items table. ----@param list string|string[] -- a list of names, or a comma-separated string. ----@return (fun(items: pl.XMLNode|string|{ [string]: string, [integer]: pl.XMLNode|string}): pl.XMLNode) ... -- (multiple) constructor functions; `function(items)`. For the `items` parameter see `xml.elem`. ----@nodiscard ---- ----Usage: ---- ----```lua ----local new_parent, new_child = xml.tags 'mom, kid' ----doc = new_parent {new_child 'Bob', new_child 'Annie'} ------ BobAnnie ----``` -function xml.tags(list) end - ----@class pl.XMLNode -local XMLNode = {} - ----Adds a document Node, at current position. This updates the last inserted ----position to the new Node. ----@param tag string -- the tag name ----@param attrs? { [string]: string } -- attributes (table of name-value pairs) (default `{}`) ---- ----Usage: ---- ----```lua ----local doc = xml.new("main") ----doc:addtag("penlight", { hello = "world"}) ----doc:addtag("expat") -- added to 'penlight' since position moved ----print(doc) -->
----``` -function XMLNode:addtag(tag, attrs) end - ----Adds a text node, at current position. ----@param text string -- a string ----@return pl.XMLNode self -- the current node (`self`) ---- ----Usage: ---- ----```lua ----local doc = xml.new("main") ----doc:text("penlight") ----doc:text("expat") ----print(doc) -->
----``` -function XMLNode:text(text) end - ----Moves current position up one level. ----@return pl.XMLNode self -- the current node (`self`) -function XMLNode:up() end - ----Resets current position to top level. Resets to the `self` node. ----@return pl.XMLNode self -- the current node (`self`) -function XMLNode:reset() end - ----Append a child to the currrent Node (ignoring current position). ----@param child string|pl.XMLNode -- a child node (either text or a document) ----@return pl.XMLNode self -- the current node (`self`) -function XMLNode:add_direct_child(child) end - ----Append a child at the current position (without changing position). ----@param child string|pl.XMLNode -- a child node (either text or a document) ----@return pl.XMLNode self -- the current node (`self`) ---- ----Usage: ---- ----```lua ----local doc = xml.new("main") ----doc:addtag("one") ----doc:add_child(xml.new("item1")) ----doc:add_child(xml.new("item2")) ----doc:add_child(xml.new("item3")) ----print(doc) -->
----``` -function XMLNode:add_child(child) end - ----Set attributes of a document node. Will add/overwite values, but will not ----remove existing ones. Operates on the Node itself, will not take position ----into account. ----@param t { [string]: string } -- a table containing attribute/value pairs ----@return pl.XMLNode self -- the current node (`self`) -function XMLNode:set_attribs(t) end - ----Set a single attribute of a document node. Operates on the Node itself, will ----not take position into account. ----@param a string -- attribute ----@param v? string -- its value, pass in `nil` to delete the attribute ----@return pl.XMLNode self -- the current node (`self`) -function XMLNode:set_attrib(a, v) end - ----Gets the attributes of a document node. Operates on the Node itself, will ----not take position into account. ----@return { [string]: string } -- table with attributes (attribute/value pairs) ----@nodiscard -function XMLNode:get_attribs() end - ----create a substituted copy of a document ----@param data table -- a table of name-value pairs or a list of such tables ----@return pl.XMLNode -- an XML document ----@nodiscard -function XMLNode:subst(data) end - ----Return the first child with a given tag name (non-recursive). ----@param tag string -- the tag name ----@return pl.XMLNode? child -- the child Node found or `nil` if not found ----@nodiscard -function XMLNode:child_with_name(tag) end - ----Returns all elements in a document that have a given tag. ----@param tag string -- a tag name ----@param dont_recurse? boolean -- optionally only return the immediate children with this tag name (default `false`) ----@return pl.XMLNode[] elements -- a list of elements found, list will be empty if none was found. ----@nodiscard -function XMLNode:get_elements_with_name(tag, dont_recurse) end - ----Iterator over all children of a document node, including text nodes. This ----function is not recursive, so returns only direct child nodes. ----@return fun(): pl.XMLNode -- iterator that returns a single Node per iteration. ----@nodiscard -function XMLNode:children() end - ----Return the first child element of a node, if it exists. This will skip text ----nodes. ----@return pl.XMLNode child -- first child Node or `nil` if there is none. ----@nodiscard -function XMLNode:first_childtag() end - ----Iterator that matches tag names, and a namespace (non-recursive). ----@param tag? string -- tag names to return. Returns all tags if not provided. ----@param xmlns? string -- the namespace value ('xmlns' attribute) to return. If not provided will match all namespaces. ----@return fun(): pl.XMLNode -- iterator that returns a single Node per iteration. ----@nodiscard -function XMLNode:matching_tags(tag, xmlns) end - ----Iterator over all child tags of a document node. This will skip over text nodes. ----@return fun(): pl.XMLNode -- iterator that returns a single Node per iteration. ----@nodiscard -function XMLNode:childtags() end - ----Visit child Nodes of a node and call a function, possibly modifying the ----document. Text elements will be skipped. This is not recursive, so only ----direct children will be passed. ----@param callback fun(node: pl.XMLNode) -- a function with signature function(node), passed the node. The element will be updated with the returned value, or deleted if it returns nil. -function XMLNode:maptags(callback) end - ----Escapes a string for safe use in xml. Handles quotes(single+double), ----less-than, greater-than, and ampersand. ----@param str string -- string value to escape ----@return string -- escaped string ----@nodiscard ---- ----Usage: ---- ----```lua ----local esc = xml.xml_escape([["'<>&]]) --> ""'<>&" ----``` -function xml.xml_escape(str) end - ----Unescapes a string from xml. Handles quotes(single+double), less-than, ----greater-than, and ampersand. ----@param str string -- string value to unescape ----@return string -- unescaped string ----@nodiscard ---- ----Usage: ---- ----```lua ----local unesc = xml.xml_escape(""'<>&") --> [["'<>&]] ----``` -function xml.xml_unescape(str) end - ----Function to pretty-print an XML document. ----@param doc pl.XMLNode -- an XML document ----@param b_ind string|integer? -- an initial block-indent (required when `t_ind` is set) ----@param t_ind string|integer? -- an tag-indent for each level (required when `a_ind` is set) ----@param a_ind string|integer? -- if given, indent each attribute pair and put on a separate line ----@param xml_preface string|boolean? -- force prefacing with default or custom , if truthy then `<?xml version='1.0'?>` will be used as default. ----@return string -- a string representation ----@nodiscard -function xml.tostring(doc, b_ind, t_ind, a_ind, xml_preface) end - ----Method to pretty-print an XML document. Invokes `xml.tostring`. ----@param b_ind string|integer? -- an initial indent (required when `t_ind` is set) ----@param t_ind string|integer? -- an indent for each level (required when `a_ind` is set) ----@param a_ind string|integer? -- if given, indent each attribute pair and put on a separate line ----@param xml_preface string -- force prefacing with default or custom (default `""`) ----@return string -- a string representation ----@nodiscard -function XMLNode:tostring(b_ind, t_ind, a_ind, xml_preface) end - ----get the full text value of an element. ----@return string -- a single string with all text elements concatenated ---- ----Usage: ---- ----```lua ----local doc = xml.new("main") ----doc:text("one") ----doc:add_child(xml.elem "two") ----doc:text("three") ---- ----local t = doc:get_text() --> "onethree" ----``` ----@nodiscard -function XMLNode:get_text() end - ----Returns a copy of a document. The `strsubst` parameter is a callback with ----signature `function(object, kind, parent)`. ---- ----Param `kind` has the following values, and parameters: ---- ---- * `"*TAG"`: object is the tag-name, `parent` is the Node object. Returns the new tag name. ---- * `"*TEXT"`: object is the text-element, `parent` is the Node object. Returns the new text value. ---- * other strings not prefixed with `*`: `kind` is the attribute name, `object` is the attribute value, `parent` is the Node object. Returns the new attribute value. ---- ----@param doc pl.XMLNode|string -- a Node object or string (text node) ----@param strsubst? fun(object: string, kind: string, parent: pl.XMLNode): string -- an optional function for handling string copying which could do substitution, etc. ----@return pl.XMLNode -- copy of the document ----@nodiscard -function XMLNode:clone(doc, strsubst) end - ----Returns a copy of a document. This is the method version of `xml.clone`. ----@param strsubst? fun(object: string, kind: string, parent: pl.XMLNode): string -- an optional function for handling string copying ----@nodiscard -function XMLNode:filter(strsubst) end - ----Compare two documents or elements. Equality is based on tag, child nodes ----(text and tags), attributes and order of those (order only fails if both are ----given, and not equal). ----@param t1 pl.XMLNode|string -- a Node object or string (text node) ----@param t2 pl.XMLNode|string -- a Node object or string (text node) ----@return boolean -- `true` when the Nodes are equal. ----@nodiscard -function xml.compare(t1, t2) end - ----is this value a document element? ----@param d any -- any value ----@return boolean -- `true` if it is a table with property `tag` being a string value. ----@nodiscard -function xml.is_tag(d) end - ----Calls a function recursively over Nodes in the document. Will only call on ----tags, it will skip text nodes. The function signature for `operation` is ----`function(tag_name, Node)`. ----@param doc pl.XMLNode|string -- a Node object or string (text node) ----@param depth_first boolean -- visit child nodes first, then the current node ----@param operation fun(tag_name: string, Node: pl.XMLNode) -- a function which will receive the current tag name and current node. -function xml.walk(doc, depth_first, operation) end - ----Parse a well-formed HTML file as a string. Tags are case-insenstive, DOCTYPE ----is ignored, and empty elements can be empty. ----@param s string -- the HTML ----@return pl.XMLNode ----@nodiscard -function xml.parsehtml(s) end - ----Parse a simple XML document using a pure Lua parser based on Robero ----Ierusalimschy's original version. ----@param s string -- the XML document to be parsed ----@param all_text boolean -- if `true`, preserves all whitespace. Otherwise only text containing non-whitespace is included. ----@param html boolean -- if `true`, uses relaxed HTML rules for parsing ----@return pl.XMLNode ----@nodiscard -function xml.basic_parse(s, all_text, html) end - ----does something... -function XMLNode:match(pat) end - -return xml diff --git a/.selene/dota2-custom-game.yml b/.selene/dota2-custom-game.yml index eb6632c..1266015 100644 --- a/.selene/dota2-custom-game.yml +++ b/.selene/dota2-custom-game.yml @@ -1,9 +1,32 @@ --- name: invokation +base: lua53 globals: + # string.format(fmt: string, ...) + F: + args: + - type: string + - type: ... + required: false + # tostring(value: any) + S: + args: + - type: any + # assertf(expr: any, fmt: string, ...) + assertf: + args: + - type: any + - type: string + - type: ... + required: false + # errorf(fmt: string, ...) + errorf: + args: + - type: string + - type: ... + required: false GameRules.Invokation: property: override-fields any: true - GameMode: - property: new-fields + EntityFramework: any: true diff --git a/.selene/dota2.yml b/.selene/dota2.yml index 44fc7cc..31e54b0 100644 --- a/.selene/dota2.yml +++ b/.selene/dota2.yml @@ -295,8 +295,6 @@ globals: property: read-only ACT_DOTA_ANCESTRAL_SPIRIT: property: read-only - ACT_DOTA_ARCANA_VOTE: - property: read-only ACT_DOTA_ARCTIC_BURN_END: property: read-only ACT_DOTA_AREA_DENY: @@ -351,10 +349,6 @@ globals: property: read-only ACT_DOTA_CAST2_STATUE: property: read-only - ACT_DOTA_CAST3_STATUE: - property: read-only - ACT_DOTA_CAST4_STATUE: - property: read-only ACT_DOTA_CAST_ABILITY_1: property: read-only ACT_DOTA_CAST_ABILITY_1_END: @@ -433,8 +427,6 @@ globals: property: read-only ACT_DOTA_CAST_REFRACTION: property: read-only - ACT_DOTA_CAST_STATUE: - property: read-only ACT_DOTA_CAST_SUN_STRIKE: property: read-only ACT_DOTA_CAST_SUN_STRIKE_ORB: @@ -575,8 +567,6 @@ globals: property: read-only ACT_DOTA_IDLE_SLEEPING_END: property: read-only - ACT_DOTA_IDLE_STATUE: - property: read-only ACT_DOTA_IMPALE: property: read-only ACT_DOTA_INTRO: @@ -593,6 +583,18 @@ globals: property: read-only ACT_DOTA_JAKIRO_LIQUIDFIRE_START: property: read-only + ACT_DOTA_KEZ_KATANA_IMPALE: + property: read-only + ACT_DOTA_KEZ_KATANA_IMPALE_FAST: + property: read-only + ACT_DOTA_KEZ_KATANA_ULT_CHAIN_A: + property: read-only + ACT_DOTA_KEZ_KATANA_ULT_CHAIN_B: + property: read-only + ACT_DOTA_KEZ_KATANA_ULT_END: + property: read-only + ACT_DOTA_KEZ_KATANA_ULT_START: + property: read-only ACT_DOTA_KILLTAUNT: property: read-only ACT_DOTA_KINETIC_FIELD: @@ -647,6 +649,8 @@ globals: property: read-only ACT_DOTA_MK_TREE_SOAR: property: read-only + ACT_DOTA_MVP_SCREEN: + property: read-only ACT_DOTA_NECRO_GHOST_SHROUD: property: read-only ACT_DOTA_NIAN_INTRO_LEAP: @@ -687,8 +691,6 @@ globals: property: read-only ACT_DOTA_PRESENT_ITEM: property: read-only - ACT_DOTA_PUNCH: - property: read-only ACT_DOTA_RADIANT_CREEP_HAMMER: property: read-only ACT_DOTA_RATTLETRAP_BATTERYASSAULT: @@ -735,6 +737,8 @@ globals: property: read-only ACT_DOTA_SAND_KING_BURROW_OUT: property: read-only + ACT_DOTA_SHADOW_VAULT: + property: read-only ACT_DOTA_SHAKE: property: read-only ACT_DOTA_SHALLOW_GRAVE: @@ -767,14 +771,12 @@ globals: property: read-only ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE: property: read-only - ACT_DOTA_SPIRIT_BREAKER_ULT_RUN: + ACT_DOTA_SPWN: property: read-only ACT_DOTA_STARTLE: property: read-only ACT_DOTA_STATIC_STORM: property: read-only - ACT_DOTA_STATUE_SEQUENCE: - property: read-only ACT_DOTA_STUN_STATUE: property: read-only ACT_DOTA_SWIM: @@ -837,6 +839,10 @@ globals: property: read-only ACT_DOTA_UNDYING_TOMBSTONE: property: read-only + ACT_DOTA_UNICYCLE: + property: read-only + ACT_DOTA_UNICYCLE_END: + property: read-only ACT_DOTA_VERSUS: property: read-only ACT_DOTA_VICTORY: @@ -2663,9 +2669,9 @@ globals: property: read-only ACT_ZOMBIE_TRIP: property: read-only - AE_CL_ADD_PARTICLE_EFFECT_CP: + AE_BODYGROUP_SET_VALUE: property: read-only - AE_CL_BODYGROUP_SET_VALUE: + AE_CL_ADD_PARTICLE_EFFECT_CP: property: read-only AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN: property: read-only @@ -2719,6 +2725,10 @@ globals: property: read-only AE_CL_SUPPRESS_EVENTS_WITH_TAG: property: read-only + AE_DESTRUCTIBLE_PART_DESTROY: + property: read-only + AE_DISABLE_PLATFORM: + property: read-only AE_DOTA_CREATE_CLINKZ_ATTACK: property: read-only AE_DOTA_DIE_PHANTOM_DEATH_PARTICLES: @@ -2743,23 +2753,33 @@ globals: property: read-only AE_EMPTY: property: read-only + AE_ENABLE_PLATFORM_PLAYER_FOLLOWS_YAW: + property: read-only + AE_ENABLE_PLATFORM_PLAYER_IGNORES_YAW: + property: read-only AE_FIRE_INPUT: property: read-only AE_FOOTSTEP: property: read-only - AE_RAGDOLL: + AE_PULSE_GRAPH: + property: read-only + AE_PULSE_GRAPH_AIMAT: property: read-only - AE_SV_BODYGROUP_SET_VALUE: + AE_PULSE_GRAPH_IKLOCKLEFTARM: + property: read-only + AE_PULSE_GRAPH_IKLOCKRIGHTARM: + property: read-only + AE_PULSE_GRAPH_LOOKAT: property: read-only AE_SV_CREATE_PARTICLE_EFFECT_CFG: property: read-only + AE_SV_IKLOCK: + property: read-only AE_SV_PLAYSOUND: property: read-only AE_SV_STOP_PARTICLE_EFFECT: property: read-only - AE_WPN_PRIMARYATTACK: - property: read-only - AE_WPN_SECONDARYATTACK: + AE_WEAPON_PERFORM_ATTACK: property: read-only Activate: args: [] @@ -3005,7 +3025,7 @@ globals: observes: read - required: false type: - display: CDOTAPlayerController + display: CDOTA_BaseNPC_Hero observes: read CreateItemOnPositionForLaunch: args: @@ -3296,10 +3316,6 @@ globals: property: read-only DMG_PARALYZE: property: read-only - DMG_PHYSGUN: - property: read-only - DMG_PLASMA: - property: read-only DMG_POISON: property: read-only DMG_PREVENT_PHYSICS_FORCE: @@ -3348,6 +3364,8 @@ globals: - type: number observes: read method: true + DOTA_ABILITY_BEHAVIOR_AFFECTED_BY_MUTE: + property: read-only DOTA_ABILITY_BEHAVIOR_ALT_CASTABLE: property: read-only DOTA_ABILITY_BEHAVIOR_AOE: @@ -3358,8 +3376,6 @@ globals: property: read-only DOTA_ABILITY_BEHAVIOR_AUTOCAST: property: read-only - DOTA_ABILITY_BEHAVIOR_BREAK_DISABLES: - property: read-only DOTA_ABILITY_BEHAVIOR_CAN_SELF_CAST: property: read-only DOTA_ABILITY_BEHAVIOR_CHANNELLED: @@ -3372,6 +3388,8 @@ globals: property: read-only DOTA_ABILITY_BEHAVIOR_DONT_CANCEL_MOVEMENT: property: read-only + DOTA_ABILITY_BEHAVIOR_DONT_PROC_OTHER_ABILITIES: + property: read-only DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK: property: read-only DOTA_ABILITY_BEHAVIOR_DONT_RESUME_MOVEMENT: @@ -3384,6 +3402,8 @@ globals: property: read-only DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL: property: read-only + DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE: + property: read-only DOTA_ABILITY_BEHAVIOR_IGNORE_MUTED: property: read-only DOTA_ABILITY_BEHAVIOR_IGNORE_PSEUDO_QUEUE: @@ -3392,6 +3412,10 @@ globals: property: read-only DOTA_ABILITY_BEHAVIOR_IMMEDIATE: property: read-only + DOTA_ABILITY_BEHAVIOR_INNATE_UI: + property: read-only + DOTA_ABILITY_BEHAVIOR_IS_FAKE_ITEM: + property: read-only DOTA_ABILITY_BEHAVIOR_ITEM: property: read-only DOTA_ABILITY_BEHAVIOR_LAST_RESORT_POINT: @@ -3422,6 +3446,8 @@ globals: property: read-only DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES: property: read-only + DOTA_ABILITY_BEHAVIOR_SKIP_FOR_KEYBINDS: + property: read-only DOTA_ABILITY_BEHAVIOR_SUPPRESS_ASSOCIATED_CONSUMABLE: property: read-only DOTA_ABILITY_BEHAVIOR_TOGGLE: @@ -3432,6 +3458,8 @@ globals: property: read-only DOTA_ABILITY_BEHAVIOR_UNRESTRICTED: property: read-only + DOTA_ABILITY_BEHAVIOR_UNSWAPPABLE: + property: read-only DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING: property: read-only DOTA_ABILITY_SPEAK_CAST: @@ -3536,14 +3564,18 @@ globals: property: read-only DOTA_DAMAGE_CATEGORY_ATTACK: property: read-only + DOTA_DAMAGE_CATEGORY_BARRIER: + property: read-only DOTA_DAMAGE_CATEGORY_SPELL: property: read-only DOTA_DAMAGE_FLAG_ATTACK_MODIFIER: property: read-only - DOTA_DAMAGE_FLAG_BYPASSES_BLOCK: + DOTA_DAMAGE_FLAG_BYPASSES_ALL_BLOCK: property: read-only DOTA_DAMAGE_FLAG_BYPASSES_INVULNERABILITY: property: read-only + DOTA_DAMAGE_FLAG_BYPASSES_PHYSICAL_BLOCK: + property: read-only DOTA_DAMAGE_FLAG_DONT_DISPLAY_DAMAGE_IF_SOURCE_HIDDEN: property: read-only DOTA_DAMAGE_FLAG_FORCE_SPELL_AMPLIFICATION: @@ -3566,6 +3598,8 @@ globals: property: read-only DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT: property: read-only + DOTA_DAMAGE_FLAG_NO_REFLECTION: + property: read-only DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION: property: read-only DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL: @@ -3944,6 +3978,10 @@ globals: property: read-only DOTA_INVALID_ORDER_CANT_ACCEPT_ATTACK_TARGET: property: read-only + DOTA_INVALID_ORDER_CANT_ATTACK_BUILDINGS: + property: read-only + DOTA_INVALID_ORDER_CANT_BUYBACK_CEASELESS_DIRGE: + property: read-only DOTA_INVALID_ORDER_CANT_BUYBACK_DISABLED_BY_GAME_MODE: property: read-only DOTA_INVALID_ORDER_CANT_BUYBACK_IN_COOLDOWN: @@ -4036,6 +4074,8 @@ globals: property: read-only DOTA_INVALID_ORDER_ITEM_ALREADY_PURCHASED: property: read-only + DOTA_INVALID_ORDER_ITEM_CANNOT_BE_CONSUMED: + property: read-only DOTA_INVALID_ORDER_ITEM_CANT_BE_DROPPED: property: read-only DOTA_INVALID_ORDER_ITEM_CANT_BE_MOVED_TO_SLOT: @@ -4156,7 +4196,9 @@ globals: property: read-only DOTA_ITEM_MAX: property: read-only - DOTA_ITEM_NEUTRAL_SLOT: + DOTA_ITEM_NEUTRAL_ACTIVE_SLOT: + property: read-only + DOTA_ITEM_NEUTRAL_PASSIVE_SLOT: property: read-only DOTA_ITEM_SLOT_1: property: read-only @@ -4240,6 +4282,8 @@ globals: property: read-only DOTA_LOADOUT_TYPE_AMBIENT_EFFECTS_PERSONA_1: property: read-only + DOTA_LOADOUT_TYPE_ANCIENT: + property: read-only DOTA_LOADOUT_TYPE_ANNOUNCER: property: read-only DOTA_LOADOUT_TYPE_ARMOR: @@ -4296,6 +4340,12 @@ globals: property: read-only DOTA_LOADOUT_TYPE_HEROIC_STATUE: property: read-only + DOTA_LOADOUT_TYPE_HERO_BASE: + property: read-only + DOTA_LOADOUT_TYPE_HERO_EFFIGY: + property: read-only + DOTA_LOADOUT_TYPE_HERO_EFFIGY_PERSONA_1: + property: read-only DOTA_LOADOUT_TYPE_HUD_SKIN: property: read-only DOTA_LOADOUT_TYPE_INVALID: @@ -4504,8 +4554,12 @@ globals: property: read-only DOTA_ModifyGold_WardKill: property: read-only + DOTA_ModifyXP_CatchUp: + property: read-only DOTA_ModifyXP_CreepKill: property: read-only + DOTA_ModifyXP_HeroAbility: + property: read-only DOTA_ModifyXP_HeroKill: property: read-only DOTA_ModifyXP_MAX: @@ -4566,8 +4620,6 @@ globals: property: read-only DOTA_PROJECTILE_ATTACHMENT_NONE: property: read-only - DOTA_PSEUDO_RANDOM_ANTIMAGE_SILENT: - property: read-only DOTA_PSEUDO_RANDOM_ARMADILLO_HEARTPIERCER: property: read-only DOTA_PSEUDO_RANDOM_ATOS: @@ -4584,6 +4636,8 @@ globals: property: read-only DOTA_PSEUDO_RANDOM_CHAOS_DOUBLE_CRIT: property: read-only + DOTA_PSEUDO_RANDOM_CHAOS_KNIGHT_INNATE_REFUND: + property: read-only DOTA_PSEUDO_RANDOM_CHAOS_TRIPLE_CRIT: property: read-only DOTA_PSEUDO_RANDOM_CM_FREEZING_FIELD: @@ -4630,6 +4684,8 @@ globals: property: read-only DOTA_PSEUDO_RANDOM_GENERIC_MISS: property: read-only + DOTA_PSEUDO_RANDOM_HOODWINK_REDIRECT: + property: read-only DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL: property: read-only DOTA_PSEUDO_RANDOM_ITEM_ABYSSAL_BLOCK: @@ -4678,6 +4734,8 @@ globals: property: read-only DOTA_PSEUDO_RANDOM_JUGG_CRIT: property: read-only + DOTA_PSEUDO_RANDOM_KEZ_SAI: + property: read-only DOTA_PSEUDO_RANDOM_LEGION_MOMENT: property: read-only DOTA_PSEUDO_RANDOM_LONE_DRUID_ENTANGLE: @@ -4710,6 +4768,8 @@ globals: property: read-only DOTA_PSEUDO_RANDOM_OGRE_MAGI_FIREBLAST: property: read-only + DOTA_PSEUDO_RANDOM_PANGOLIER_PARRY: + property: read-only DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_CRIT: property: read-only DOTA_PSEUDO_RANDOM_PHANTOMASSASSIN_DAGGER: @@ -4724,6 +4784,8 @@ globals: property: read-only DOTA_PSEUDO_RANDOM_SLARDAR_BASH: property: read-only + DOTA_PSEUDO_RANDOM_SNAPFIRE_GLANCING: + property: read-only DOTA_PSEUDO_RANDOM_SNIPER_HEADSHOT: property: read-only DOTA_PSEUDO_RANDOM_SPIRITBREAKER_GREATERBASH: @@ -4910,6 +4972,8 @@ globals: property: read-only DOTA_UNIT_ORDER_CAST_TOGGLE_AUTO: property: read-only + DOTA_UNIT_ORDER_CONSUME_ITEM: + property: read-only DOTA_UNIT_ORDER_CONTINUE: property: read-only DOTA_UNIT_ORDER_DISASSEMBLE_ITEM: @@ -4956,6 +5020,8 @@ globals: property: read-only DOTA_UNIT_ORDER_SET_ITEM_COMBINE_LOCK: property: read-only + DOTA_UNIT_ORDER_SET_ITEM_MARK_FOR_SELL: + property: read-only DOTA_UNIT_ORDER_STOP: property: read-only DOTA_UNIT_ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH: @@ -4980,6 +5046,8 @@ globals: property: read-only DOTA_UNIT_TARGET_CUSTOM: property: read-only + DOTA_UNIT_TARGET_FLAG_CAN_BE_SEEN: + property: read-only DOTA_UNIT_TARGET_FLAG_CHECK_DISABLE_HELP: property: read-only DOTA_UNIT_TARGET_FLAG_DEAD: @@ -5026,6 +5094,8 @@ globals: property: read-only DOTA_UNIT_TARGET_HERO: property: read-only + DOTA_UNIT_TARGET_HEROES_AND_CREEPS: + property: read-only DOTA_UNIT_TARGET_NONE: property: read-only DOTA_UNIT_TARGET_OTHER: @@ -5048,6 +5118,20 @@ globals: property: read-only DebugBreak: args: [] + DebugCreateHeroWithVariant: + args: + - type: any + observes: read + - type: string + observes: read + - type: number + observes: read + - type: number + observes: read + - type: bool + observes: read + - type: any + observes: read DebugCreateUnit: args: - type: @@ -7076,6 +7160,10 @@ globals: property: read-only MODIFIER_ATTRIBUTE_PERMANENT: property: read-only + MODIFIER_EVENT_NEUTRAL_ENHANCEMENT_OPTIONS: + property: read-only + MODIFIER_EVENT_NEUTRAL_TRINKET_OPTIONS: + property: read-only MODIFIER_EVENT_ON_ABILITY_END_CHANNEL: property: read-only MODIFIER_EVENT_ON_ABILITY_EXECUTED: @@ -7084,6 +7172,8 @@ globals: property: read-only MODIFIER_EVENT_ON_ABILITY_START: property: read-only + MODIFIER_EVENT_ON_ABILITY_TOGGLED: + property: read-only MODIFIER_EVENT_ON_ASSIST: property: read-only MODIFIER_EVENT_ON_ATTACK: @@ -7112,10 +7202,14 @@ globals: property: read-only MODIFIER_EVENT_ON_BUILDING_KILLED: property: read-only + MODIFIER_EVENT_ON_CLEAVE_ATTACK_LANDED: + property: read-only MODIFIER_EVENT_ON_DAMAGE_CALCULATED: property: read-only MODIFIER_EVENT_ON_DAMAGE_HPLOSS: property: read-only + MODIFIER_EVENT_ON_DAY_STARTED: + property: read-only MODIFIER_EVENT_ON_DEATH: property: read-only MODIFIER_EVENT_ON_DEATH_COMPLETED: @@ -7126,10 +7220,14 @@ globals: property: read-only MODIFIER_EVENT_ON_FORCE_PROC_MAGIC_STICK: property: read-only + MODIFIER_EVENT_ON_FOW_TEAM_CHANGED: + property: read-only MODIFIER_EVENT_ON_HEALTH_GAINED: property: read-only MODIFIER_EVENT_ON_HEAL_RECEIVED: property: read-only + MODIFIER_EVENT_ON_HERO_BEGIN_DYING: + property: read-only MODIFIER_EVENT_ON_HERO_KILLED: property: read-only MODIFIER_EVENT_ON_KILL: @@ -7142,6 +7240,12 @@ globals: property: read-only MODIFIER_EVENT_ON_MODIFIER_ADDED: property: read-only + MODIFIER_EVENT_ON_MODIFIER_REMOVED: + property: read-only + MODIFIER_EVENT_ON_MUTE_DAMAGE_ABILITIES: + property: read-only + MODIFIER_EVENT_ON_NIGHT_STARTED: + property: read-only MODIFIER_EVENT_ON_ORB_EFFECT: property: read-only MODIFIER_EVENT_ON_ORDER: @@ -7156,10 +7260,14 @@ globals: property: read-only MODIFIER_EVENT_ON_PROJECTILE_OBSTRUCTION_HIT: property: read-only + MODIFIER_EVENT_ON_PURE_DAMAGE_CALCULATED: + property: read-only MODIFIER_EVENT_ON_REFRESH: property: read-only MODIFIER_EVENT_ON_RESPAWN: property: read-only + MODIFIER_EVENT_ON_RUNE_SPAWN: + property: read-only MODIFIER_EVENT_ON_SET_LOCATION: property: read-only MODIFIER_EVENT_ON_SPELL_TARGET_READY: @@ -7174,10 +7282,16 @@ globals: property: read-only MODIFIER_EVENT_ON_TAKEDAMAGE_KILLCREDIT: property: read-only + MODIFIER_EVENT_ON_TAKEDAMAGE_POST_UNAVOIDABLE_BLOCK: + property: read-only MODIFIER_EVENT_ON_TELEPORTED: property: read-only MODIFIER_EVENT_ON_TELEPORTING: property: read-only + MODIFIER_EVENT_ON_TIER_TOKEN_REROLLED: + property: read-only + MODIFIER_EVENT_ON_TREE_CUT_DOWN: + property: read-only MODIFIER_EVENT_ON_UNIT_MOVED: property: read-only MODIFIER_EVENT_SPELL_APPLIED_SUCCESSFULLY: @@ -7198,6 +7312,8 @@ globals: property: read-only MODIFIER_PROPERTY_ABILITY_LAYOUT: property: read-only + MODIFIER_PROPERTY_ABILITY_POINTS: + property: read-only MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_MAGICAL: property: read-only MODIFIER_PROPERTY_ABSOLUTE_NO_DAMAGE_PHYSICAL: @@ -7206,6 +7322,8 @@ globals: property: read-only MODIFIER_PROPERTY_ABSORB_SPELL: property: read-only + MODIFIER_PROPERTY_ADDITIONAL_NEUTRAL_ITEM_DROPS: + property: read-only MODIFIER_PROPERTY_ALWAYS_ALLOW_ATTACK: property: read-only MODIFIER_PROPERTY_ALWAYS_AUTOATTACK_WHILE_HOLD_POSITION: @@ -7214,8 +7332,12 @@ globals: property: read-only MODIFIER_PROPERTY_AOE_BONUS_CONSTANT: property: read-only + MODIFIER_PROPERTY_AOE_BONUS_CONSTANT_STACKING: + property: read-only MODIFIER_PROPERTY_AOE_BONUS_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_ATTACKSPEED_ABSOLUTE_MAX: + property: read-only MODIFIER_PROPERTY_ATTACKSPEED_BASE_OVERRIDE: property: read-only MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT: @@ -7226,6 +7348,8 @@ globals: property: read-only MODIFIER_PROPERTY_ATTACK_ANIM_TIME_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_ATTACK_HEIGHT_BONUS: + property: read-only MODIFIER_PROPERTY_ATTACK_POINT_CONSTANT: property: read-only MODIFIER_PROPERTY_ATTACK_RANGE_BASE_OVERRIDE: @@ -7238,6 +7362,8 @@ globals: property: read-only MODIFIER_PROPERTY_ATTACK_WHILE_MOVING_TARGET: property: read-only + MODIFIER_PROPERTY_AVOID_ATTACK_PROCS: + property: read-only MODIFIER_PROPERTY_AVOID_DAMAGE: property: read-only MODIFIER_PROPERTY_AVOID_DAMAGE_AFTER_REDUCTIONS: @@ -7246,18 +7372,34 @@ globals: property: read-only MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE: property: read-only + MODIFIER_PROPERTY_BASEATTACK_POSTBONUS: + property: read-only MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE: property: read-only MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE_UNIQUE: property: read-only + MODIFIER_PROPERTY_BASE_ARMOR_PER_AGI_BONUS_PERCENTAGE: + property: read-only MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT: property: read-only MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT_ADJUST: property: read-only MODIFIER_PROPERTY_BASE_ATTACK_TIME_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_BASE_HP_REGEN_PER_STR_BONUS_PERCENTAGE: + property: read-only MODIFIER_PROPERTY_BASE_MANA_REGEN: property: read-only + MODIFIER_PROPERTY_BASE_MP_REGEN_PER_INT_BONUS_PERCENTAGE: + property: read-only + MODIFIER_PROPERTY_BASE_MRES_PER_INT_BONUS_PERCENTAGE: + property: read-only + MODIFIER_PROPERTY_BECOME_AGILITY: + property: read-only + MODIFIER_PROPERTY_BECOME_INTELLIGENCE: + property: read-only + MODIFIER_PROPERTY_BECOME_STRENGTH: + property: read-only MODIFIER_PROPERTY_BECOME_UNIVERSAL: property: read-only MODIFIER_PROPERTY_BONUSDAMAGEOUTGOING_PERCENTAGE: @@ -7266,10 +7408,14 @@ globals: property: read-only MODIFIER_PROPERTY_BONUS_DAY_VISION_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_BONUS_LOTUS_HEAL: + property: read-only MODIFIER_PROPERTY_BONUS_NIGHT_VISION: property: read-only MODIFIER_PROPERTY_BONUS_NIGHT_VISION_UNIQUE: property: read-only + MODIFIER_PROPERTY_BONUS_UPHILL_MISS_CHANCE: + property: read-only MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE: property: read-only MODIFIER_PROPERTY_BOT_ATTACK_SCORE_BONUS: @@ -7278,6 +7424,8 @@ globals: property: read-only MODIFIER_PROPERTY_BOUNTY_OTHER_MULTIPLIER: property: read-only + MODIFIER_PROPERTY_BUYBACK_PENALTY_PERCENT: + property: read-only MODIFIER_PROPERTY_CAN_ATTACK_TREES: property: read-only MODIFIER_PROPERTY_CASTTIME_PERCENTAGE: @@ -7292,6 +7440,12 @@ globals: property: read-only MODIFIER_PROPERTY_CHANGE_ABILITY_VALUE: property: read-only + MODIFIER_PROPERTY_CONSUMABLE_USE_SPEED: + property: read-only + MODIFIER_PROPERTY_CONVERT_ATTACK_PHYSICAL_TO_PURE: + property: read-only + MODIFIER_PROPERTY_CONVERT_MANA_COST_TO_HEALTH_COST: + property: read-only MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE: property: read-only MODIFIER_PROPERTY_COOLDOWN_PERCENTAGE_ONGOING: @@ -7300,6 +7454,14 @@ globals: property: read-only MODIFIER_PROPERTY_COOLDOWN_REDUCTION_CONSTANT: property: read-only + MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_CHANCE: + property: read-only + MODIFIER_PROPERTY_CREATE_BONUS_ILLUSION_COUNT: + property: read-only + MODIFIER_PROPERTY_CREEP_DENY_PERCENT: + property: read-only + MODIFIER_PROPERTY_CRITICAL_STRIKE_BONUS: + property: read-only MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE: property: read-only MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE_ILLUSION: @@ -7314,14 +7476,16 @@ globals: property: read-only MODIFIER_PROPERTY_DISABLE_HEALING: property: read-only + MODIFIER_PROPERTY_DISABLE_MANA_GAIN: + property: read-only MODIFIER_PROPERTY_DISABLE_TURNING: property: read-only + MODIFIER_PROPERTY_DISASSEMBLE_ANYTHING: + property: read-only MODIFIER_PROPERTY_DODGE_PROJECTILE: property: read-only MODIFIER_PROPERTY_DONT_GIVE_VISION_OF_ATTACKER: property: read-only - MODIFIER_PROPERTY_DO_NOT_SINK_AFTER_DEATH: - property: read-only MODIFIER_PROPERTY_EVASION_CONSTANT: property: read-only MODIFIER_PROPERTY_EXP_RATE_BOOST: @@ -7344,14 +7508,26 @@ globals: property: read-only MODIFIER_PROPERTY_FIXED_DAY_VISION: property: read-only + MODIFIER_PROPERTY_FIXED_MANA_REGEN: + property: read-only MODIFIER_PROPERTY_FIXED_NIGHT_VISION: property: read-only + MODIFIER_PROPERTY_FORBID_ILLUSIONS: + property: read-only MODIFIER_PROPERTY_FORCE_DRAW_MINIMAP: property: read-only MODIFIER_PROPERTY_FORCE_MAX_HEALTH: property: read-only + MODIFIER_PROPERTY_FORCE_MAX_MANA: + property: read-only + MODIFIER_PROPERTY_FORCE_NETWORK_TRANSMIT: + property: read-only + MODIFIER_PROPERTY_FOW_TEAM: + property: read-only MODIFIER_PROPERTY_GOLD_RATE_BOOST: property: read-only + MODIFIER_PROPERTY_HAS_BONUS_NEUTRAL_ITEM_CHOICE: + property: read-only MODIFIER_PROPERTY_HEALTHBAR_PIPS: property: read-only MODIFIER_PROPERTY_HEALTHCOST_PERCENTAGE: @@ -7370,12 +7546,18 @@ globals: property: read-only MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE: property: read-only + MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_SOURCE_UNIQUE: + property: read-only MODIFIER_PROPERTY_HEAL_AMPLIFY_PERCENTAGE_TARGET: property: read-only + MODIFIER_PROPERTY_HEROFACET_OVERRIDE: + property: read-only MODIFIER_PROPERTY_HP_REGEN_AMPLIFY_PERCENTAGE: property: read-only MODIFIER_PROPERTY_HP_REGEN_CAN_BE_NEGATIVE: property: read-only + MODIFIER_PROPERTY_HP_REGEN_MULTIPLIER_PRE_AMPLIFICATION: + property: read-only MODIFIER_PROPERTY_IGNORE_ATTACKSPEED_LIMIT: property: read-only MODIFIER_PROPERTY_IGNORE_CAST_ANGLE: @@ -7402,6 +7584,10 @@ globals: property: read-only MODIFIER_PROPERTY_INCOMING_SPELL_DAMAGE_CONSTANT: property: read-only + MODIFIER_PROPERTY_INNATE_DAMAGE_BLOCK_PCT_OVERRIDE: + property: read-only + MODIFIER_PROPERTY_INVENTORY_SLOT_RESTRICTED: + property: read-only MODIFIER_PROPERTY_INVISIBILITY_ATTACK_BEHAVIOR_EXCEPTION: property: read-only MODIFIER_PROPERTY_INVISIBILITY_LEVEL: @@ -7412,14 +7598,22 @@ globals: property: read-only MODIFIER_PROPERTY_IS_SHARD: property: read-only + MODIFIER_PROPERTY_ITEM_SELLBACK_COST: + property: read-only + MODIFIER_PROPERTY_KILL_STREAK_BONUS_GOLD_PERCENTAGE: + property: read-only MODIFIER_PROPERTY_KNOCKBACK_AMPLIFICATION_PERCENTAGE: property: read-only MODIFIER_PROPERTY_LIFESTEAL_AMPLIFY_PERCENTAGE: property: read-only MODIFIER_PROPERTY_LIFETIME_FRACTION: property: read-only + MODIFIER_PROPERTY_MAGICAL_ARMOR_PIERCING_PERCENTAGE_TARGET: + property: read-only MODIFIER_PROPERTY_MAGICAL_CONSTANT_BLOCK: property: read-only + MODIFIER_PROPERTY_MAGICAL_LIFESTEAL: + property: read-only MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BASE_REDUCTION: property: read-only MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS: @@ -7432,6 +7626,8 @@ globals: property: read-only MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DIRECT_MODIFICATION: property: read-only + MODIFIER_PROPERTY_MANACOST_OVERRIDE: + property: read-only MODIFIER_PROPERTY_MANACOST_PERCENTAGE: property: read-only MODIFIER_PROPERTY_MANACOST_PERCENTAGE_STACKING: @@ -7452,12 +7648,18 @@ globals: property: read-only MODIFIER_PROPERTY_MAX_DEBUFF_DURATION: property: read-only + MODIFIER_PROPERTY_MIN_ATTRIBUTE_LEVEL: + property: read-only MODIFIER_PROPERTY_MIN_HEALTH: property: read-only + MODIFIER_PROPERTY_MIN_MANA: + property: read-only MODIFIER_PROPERTY_MIN_PHYSICAL_ARMOR: property: read-only MODIFIER_PROPERTY_MISS_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_MISS_PERCENTAGE_TARGET: + property: read-only MODIFIER_PROPERTY_MODEL_CHANGE: property: read-only MODIFIER_PROPERTY_MODEL_SCALE: @@ -7492,14 +7694,26 @@ globals: property: read-only MODIFIER_PROPERTY_MOVESPEED_LIMIT: property: read-only + MODIFIER_PROPERTY_MOVESPEED_MAX_BONUS_CONSTANT: + property: read-only + MODIFIER_PROPERTY_MOVESPEED_MAX_OVERRIDE: + property: read-only + MODIFIER_PROPERTY_MOVESPEED_MIN_OVERRIDE: + property: read-only + MODIFIER_PROPERTY_MOVESPEED_POST_MULTIPLIER_BONUS_CONSTANT: + property: read-only MODIFIER_PROPERTY_MOVESPEED_REDUCTION_PERCENTAGE: property: read-only MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_MP_REGEN_AMPLIFY_PERCENTAGE_UNIQUE: + property: read-only MODIFIER_PROPERTY_MP_RESTORE_AMPLIFY_PERCENTAGE: property: read-only MODIFIER_PROPERTY_NEGATIVE_EVASION_CONSTANT: property: read-only + MODIFIER_PROPERTY_NO_FREE_TP_SCROLL_ON_DEATH: + property: read-only MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL: property: read-only MODIFIER_PROPERTY_OVERRIDE_ABILITY_SPECIAL_VALUE: @@ -7508,12 +7722,14 @@ globals: property: read-only MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE: property: read-only - MODIFIER_PROPERTY_OVERRIDE_ANIMATION_WEIGHT: - property: read-only MODIFIER_PROPERTY_OVERRIDE_ATTACK_DAMAGE: property: read-only MODIFIER_PROPERTY_OVERRIDE_ATTACK_MAGICAL: property: read-only + MODIFIER_PROPERTY_PACK_RAT: + property: read-only + MODIFIER_PROPERTY_PERCENTAGE_DEATHGOLDCOST: + property: read-only MODIFIER_PROPERTY_PERSISTENT_INVISIBILITY: property: read-only MODIFIER_PROPERTY_PHYSICALDAMAGEOUTGOING_PERCENTAGE: @@ -7528,12 +7744,16 @@ globals: property: read-only MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS_UNIQUE_ACTIVE: property: read-only + MODIFIER_PROPERTY_PHYSICAL_ARMOR_PIERCING_PERCENTAGE_TARGET: + property: read-only MODIFIER_PROPERTY_PHYSICAL_ARMOR_TOTAL_PERCENTAGE: property: read-only MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK: property: read-only MODIFIER_PROPERTY_PHYSICAL_CONSTANT_BLOCK_SPECIAL: property: read-only + MODIFIER_PROPERTY_PHYSICAL_LIFESTEAL: + property: read-only MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE: property: read-only MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE_POST_CRIT: @@ -7550,6 +7770,8 @@ globals: property: read-only MODIFIER_PROPERTY_PREREDUCE_INCOMING_DAMAGE_MULT: property: read-only + MODIFIER_PROPERTY_PRESERVE_NEUTRAL_ITEM_PASSIVES: + property: read-only MODIFIER_PROPERTY_PRESERVE_PARTICLES_ON_MODEL_CHANGE: property: read-only MODIFIER_PROPERTY_PRE_ATTACK: @@ -7576,11 +7798,15 @@ globals: property: read-only MODIFIER_PROPERTY_PROJECTILE_SPEED_BONUS_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_PROJECTILE_SPEED_TARGET: + property: read-only MODIFIER_PROPERTY_PROVIDES_FOW_POSITION: property: read-only + MODIFIER_PROPERTY_PSEUDORANDOM_BONUS: + property: read-only MODIFIER_PROPERTY_RADAR_COOLDOWN_REDUCTION: property: read-only - MODIFIER_PROPERTY_RAT_PACK: + MODIFIER_PROPERTY_REDIRECT_SPELL: property: read-only MODIFIER_PROPERTY_REFLECT_SPELL: property: read-only @@ -7594,7 +7820,19 @@ globals: property: read-only MODIFIER_PROPERTY_RESPAWNTIME_STACKING: property: read-only - MODIFIER_PROPERTY_SLOW_RESISTANCE: + MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION: + property: read-only + MODIFIER_PROPERTY_RESTORATION_AMPLIFICATION_UNIQUE: + property: read-only + MODIFIER_PROPERTY_SHARE_XPRUNE: + property: read-only + MODIFIER_PROPERTY_SKIP_ATTACK_REGULATOR: + property: read-only + MODIFIER_PROPERTY_SLOW_RESISTANCE_APPLIES_TO_ATTACKS: + property: read-only + MODIFIER_PROPERTY_SLOW_RESISTANCE_STACKING: + property: read-only + MODIFIER_PROPERTY_SLOW_RESISTANCE_UNIQUE: property: read-only MODIFIER_PROPERTY_SPELLS_REQUIRE_HP: property: read-only @@ -7602,10 +7840,14 @@ globals: property: read-only MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_CREEP: property: read-only + MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_TARGET: + property: read-only MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE_UNIQUE: property: read-only MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE: property: read-only + MODIFIER_PROPERTY_SPELL_LIFESTEAL_AMPLIFY_PERCENTAGE_UNIQUE: + property: read-only MODIFIER_PROPERTY_SPELL_REDIRECT_TARGET: property: read-only MODIFIER_PROPERTY_STATS_AGILITY_BONUS: @@ -7632,16 +7874,24 @@ globals: property: read-only MODIFIER_PROPERTY_SUPER_ILLUSION_WITH_ULTIMATE: property: read-only + MODIFIER_PROPERTY_SUPPRESS_ATTACK_PROCS: + property: read-only MODIFIER_PROPERTY_SUPPRESS_CLEAVE: property: read-only + MODIFIER_PROPERTY_SUPPRESS_CRIT: + property: read-only MODIFIER_PROPERTY_SUPPRESS_FULLSCREEN_DEATH_FX: property: read-only + MODIFIER_PROPERTY_SUPPRESS_INCOMING_CRIT: + property: read-only MODIFIER_PROPERTY_SUPPRESS_TELEPORT: property: read-only MODIFIER_PROPERTY_TEMPEST_DOUBLE: property: read-only MODIFIER_PROPERTY_TICK_GOLD_MULTIPLIER: property: read-only + MODIFIER_PROPERTY_TIER_TOKEN_REROLL: + property: read-only MODIFIER_PROPERTY_TOOLTIP: property: read-only MODIFIER_PROPERTY_TOOLTIP2: @@ -7650,6 +7900,8 @@ globals: property: read-only MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK: property: read-only + MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_STACKING: + property: read-only MODIFIER_PROPERTY_TOTAL_CONSTANT_BLOCK_UNAVOIDABLE_PRE_ARMOR: property: read-only MODIFIER_PROPERTY_TRANSLATE_ACTIVITY_MODIFIERS: @@ -7668,12 +7920,18 @@ globals: property: read-only MODIFIER_PROPERTY_UNIT_STATS_NEEDS_REFRESH: property: read-only + MODIFIER_PROPERTY_UPGRADE_NEUTRAL_ARTIFACTS: + property: read-only + MODIFIER_PROPERTY_VISION_DEGREES_RESTRICTION: + property: read-only MODIFIER_PROPERTY_VISUAL_Z_DELTA: property: read-only MODIFIER_PROPERTY_VISUAL_Z_SPEED_BASE_OVERRIDE: property: read-only MODIFIER_PROPERTY_XP_DURING_DEATH: property: read-only + MODIFIER_PROPERTY_XP_FOUNTAIN_COUNTDOWN_TIME_OVERRIDE: + property: read-only MODIFIER_STATE_ALLOW_PATHING_THROUGH_BASE_BLOCKER: property: read-only MODIFIER_STATE_ALLOW_PATHING_THROUGH_CLIFFS: @@ -7684,6 +7942,10 @@ globals: property: read-only MODIFIER_STATE_ALLOW_PATHING_THROUGH_TREES: property: read-only + MODIFIER_STATE_ATTACKS_ARE_MELEE: + property: read-only + MODIFIER_STATE_ATTACKS_DONT_REVEAL: + property: read-only MODIFIER_STATE_ATTACK_ALLIES: property: read-only MODIFIER_STATE_ATTACK_IMMUNE: @@ -7700,6 +7962,10 @@ globals: property: read-only MODIFIER_STATE_CANNOT_TARGET_ENEMIES: property: read-only + MODIFIER_STATE_CAN_USE_BACKPACK_ITEMS: + property: read-only + MODIFIER_STATE_CASTS_IGNORE_CHANNELING: + property: read-only MODIFIER_STATE_COMMAND_RESTRICTED: property: read-only MODIFIER_STATE_DEBUFF_IMMUNE: @@ -7742,6 +8008,8 @@ globals: property: read-only MODIFIER_STATE_MUTED: property: read-only + MODIFIER_STATE_NEUTRALS_DONT_ATTACK: + property: read-only MODIFIER_STATE_NIGHTMARED: property: read-only MODIFIER_STATE_NOT_ON_MINIMAP: @@ -7754,8 +8022,6 @@ globals: property: read-only MODIFIER_STATE_NO_HEALTH_BAR_FOR_OTHER_PLAYERS: property: read-only - MODIFIER_STATE_NO_INVISIBILITY_VISUALS: - property: read-only MODIFIER_STATE_NO_TEAM_MOVE_TO: property: read-only MODIFIER_STATE_NO_TEAM_SELECT: @@ -7852,6 +8118,8 @@ globals: property: read-only OVERHEAD_ALERT_EVADE: property: read-only + OVERHEAD_ALERT_FORCE_MISS: + property: read-only OVERHEAD_ALERT_GOLD: property: read-only OVERHEAD_ALERT_HEAL: @@ -7860,12 +8128,6 @@ globals: property: read-only OVERHEAD_ALERT_ITEM_RECEIVED: property: read-only - OVERHEAD_ALERT_LAST_HIT_CLOSE: - property: read-only - OVERHEAD_ALERT_LAST_HIT_EARLY: - property: read-only - OVERHEAD_ALERT_LAST_HIT_MISS: - property: read-only OVERHEAD_ALERT_MAGICAL_BLOCK: property: read-only OVERHEAD_ALERT_MANA_ADD: @@ -9365,8 +9627,6 @@ globals: property: read-only QUEST_TEXT_REPLACE_VALUE_TARGET_VALUE: property: read-only - RELOAD: - property: read-only Rad2Deg: args: - type: number @@ -10918,6 +11178,32 @@ globals: property: read-only json.version: property: read-only + k_ECustomCameraEventFlags_FadeIn: + property: read-only + k_ECustomCameraEventFlags_FadeOut: + property: read-only + k_ECustomCameraEventFlags_LetterboxOff: + property: read-only + k_ECustomCameraEventFlags_LetterboxOn: + property: read-only + k_ECustomCameraEventFlags_Lock: + property: read-only + k_ECustomCameraEventFlags_Pitch: + property: read-only + k_ECustomCameraEventFlags_Position: + property: read-only + k_ECustomCameraEventFlags_PositionPlayerHero: + property: read-only + k_ECustomCameraEventFlags_ResetDefault: + property: read-only + k_ECustomCameraEventFlags_SpecificPlayer: + property: read-only + k_ECustomCameraEventFlags_Unlock: + property: read-only + k_ECustomCameraEventFlags_Yaw: + property: read-only + k_ECustomCameraEventFlags_Zoom: + property: read-only max: args: - type: number @@ -10994,3 +11280,5 @@ globals: args: - type: table - type: table +lua_versions: +- luajit From b72e8d255b3dc720fa2cb0ab95933a1dbdc952c7 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 08:51:25 -0300 Subject: [PATCH 04/29] feat(vscripts)!: major refactoring: Yes, this is one of those refactor-everything, impossible-to-review, just-trust-me-bro commits. Luckily the test suite holds (mostly) everything together. * add `compat53` * remove `penlight` and `moses` - add `middleclass` for classes - add `inspect` for value formatting - manually implement table/function/string utils * reorganization - rename top-level module `invokation` to `invk` - extract and reorganize a lot of code - remove a lot of unused code - rewrite/refactor tests support code * types - replace ldoc tags with emmylua_ls tags (LuaCATS) * code style - use snake_case * probably a hell of a lot of other things --- .busted | 2 + game/scripts/vscripts/addon_game_mode.lua | 13 +- game/scripts/vscripts/compat53/file_mt.lua | 71 + game/scripts/vscripts/compat53/init.lua | 325 ++ game/scripts/vscripts/compat53/module.lua | 894 +++++ game/scripts/vscripts/inspect.lua | 371 ++ .../vscripts/invk/combo/base_combo.lua | 144 + game/scripts/vscripts/invk/combo/combo.lua | 87 + .../vscripts/invk/combo/combo_sequence.lua | 231 ++ .../vscripts/invk/combo/combo_step.lua | 45 + game/scripts/vscripts/invk/combo/combos.lua | 440 +++ .../vscripts/invk/combo/communication.lua | 113 + .../vscripts/invk/combo/freestyle_combo.lua | 76 + game/scripts/vscripts/invk/combo/hero.lua | 108 + game/scripts/vscripts/invk/combo/sound.lua | 70 + game/scripts/vscripts/invk/combo/spec.lua | 58 + game/scripts/vscripts/invk/combo/wait.lua | 73 + .../const/ability_list.lua | 8 +- game/scripts/vscripts/invk/const/combos.lua | 656 ++++ .../{invokation => invk}/const/commands.lua | 92 +- .../const/custom_events.lua | 99 +- .../{invokation => invk}/const/enums.lua | 121 +- .../scripts/vscripts/invk/const/inventory.lua | 63 + game/scripts/vscripts/invk/const/invoker.lua | 231 ++ .../{invokation => invk}/const/limits.lua | 2 +- game/scripts/vscripts/invk/const/metadata.lua | 25 + .../scripts/vscripts/invk/const/net_table.lua | 37 + .../{invokation => invk}/const/precache.lua | 6 +- .../{invokation => invk}/const/settings.lua | 540 +-- .../const/sound_events.lua | 17 +- .../{invokation => invk}/const/units.lua | 14 +- game/scripts/vscripts/invk/dota2/ability.lua | 53 + .../vscripts/invk/dota2/custom_events.lua | 56 + .../vscripts/invk/dota2/damage_instance.lua | 49 + .../vscripts/invk/dota2/dummy_target.lua | 91 + game/scripts/vscripts/invk/dota2/game.lua | 1 + game/scripts/vscripts/invk/dota2/invoker.lua | 199 ++ game/scripts/vscripts/invk/dota2/kv.lua | 42 + .../invk/dota2/kv/ability_key_values.lua | 20 + .../invk/dota2/kv/hero_key_values.lua | 88 + .../invk/dota2/kv/item_key_values.lua | 40 + .../invk/dota2/kv/items_key_values.lua | 53 + .../vscripts/invk/dota2/kv/key_values.lua | 126 + .../scripts/vscripts/invk/dota2/net_table.lua | 63 + game/scripts/vscripts/invk/dota2/player.lua | 80 + .../vscripts/invk/dota2/sound_events.lua | 69 + game/scripts/vscripts/invk/dota2/talents.lua | 103 + game/scripts/vscripts/invk/dota2/timers.lua | 272 ++ game/scripts/vscripts/invk/dota2/unit.lua | 355 ++ game/scripts/vscripts/invk/dota2/units.lua | 69 + game/scripts/vscripts/invk/game_mode.lua | 999 ++++++ .../invk/game_mode/commands/ability.lua | 23 + .../invk/game_mode/commands/combo.lua | 21 + .../invk/game_mode/commands/debug_misc.lua | 21 + .../game_mode/commands/debug_specials.lua | 66 +- .../game_mode/commands/dump_abilities.lua | 60 + .../invk/game_mode/commands/dump_specials.lua | 123 + .../invk/game_mode/commands/globals.lua | 48 + .../vscripts/invk/game_mode/commands/item.lua | 24 + .../invk/game_mode/commands/music.lua | 26 + game/scripts/vscripts/invk/game_mode/env.lua | 15 + game/scripts/vscripts/invk/lang/function.lua | 95 + game/scripts/vscripts/invk/lang/global.lua | 24 + game/scripts/vscripts/invk/lang/random.lua | 18 + game/scripts/vscripts/invk/lang/string.lua | 79 + .../{invokation => invk}/lang/stub.lua | 1 - game/scripts/vscripts/invk/lang/table.lua | 370 ++ game/scripts/vscripts/invk/lang/value.lua | 21 + game/scripts/vscripts/invk/logger.lua | 230 ++ game/scripts/vscripts/invokation/GameMode.lua | 135 - game/scripts/vscripts/invokation/Logger.lua | 283 -- .../vscripts/invokation/combos/BaseCombo.lua | 114 - .../vscripts/invokation/combos/Combo.lua | 128 - .../invokation/combos/ComboSequence.lua | 151 - .../vscripts/invokation/combos/ComboStep.lua | 47 - .../vscripts/invokation/combos/Combos.lua | 426 --- .../invokation/combos/FreestyleCombo.lua | 76 - .../invokation/combos/PlayerStates.lua | 25 - .../invokation/combos/communication.lua | 84 - .../vscripts/invokation/combos/hero.lua | 102 - .../vscripts/invokation/combos/sound.lua | 62 - .../vscripts/invokation/const/abilities.lua | 11 - .../vscripts/invokation/const/combos.lua | 519 --- .../vscripts/invokation/const/heroes.lua | 11 - .../vscripts/invokation/const/inventory.lua | 40 - .../vscripts/invokation/const/invoker.lua | 288 -- .../vscripts/invokation/const/items.lua | 11 - .../vscripts/invokation/const/metadata.lua | 36 - .../vscripts/invokation/const/net_table.lua | 25 - .../vscripts/invokation/dota2/Ability.lua | 39 - .../invokation/dota2/DamageInstance.lua | 44 - .../vscripts/invokation/dota2/DummyTarget.lua | 73 - .../vscripts/invokation/dota2/Invoker.lua | 162 - .../vscripts/invokation/dota2/NetTable.lua | 40 - .../vscripts/invokation/dota2/Player.lua | 81 - .../vscripts/invokation/dota2/Unit.lua | 346 -- .../vscripts/invokation/dota2/classes.lua | 7 - .../invokation/dota2/custom_events.lua | 55 - .../vscripts/invokation/dota2/hats.lua | 32 - game/scripts/vscripts/invokation/dota2/kv.lua | 221 -- .../invokation/dota2/kv/AbilityKeyValues.lua | 45 - .../invokation/dota2/kv/HeroKeyValues.lua | 69 - .../invokation/dota2/kv/ItemKeyValues.lua | 55 - .../invokation/dota2/kv/ItemsKeyValues.lua | 47 - .../invokation/dota2/sound_events.lua | 75 - .../vscripts/invokation/dota2/talents.lua | 96 - .../vscripts/invokation/dota2/timers.lua | 246 -- .../vscripts/invokation/dota2/units.lua | 72 - .../invokation/game_mode/commands.lua | 281 -- .../game_mode/commands/dump_specials.lua | 86 - .../vscripts/invokation/game_mode/convars.lua | 7 - .../vscripts/invokation/game_mode/env.lua | 29 - .../vscripts/invokation/game_mode/events.lua | 57 - .../game_mode/events/custom_events.lua | 94 - .../game_mode/events/game_events.lua | 174 - .../invokation/game_mode/events/internal.lua | 115 - .../invokation/game_mode/game_mode.lua | 83 - .../invokation/game_mode/game_rules.lua | 76 - .../invokation/game_mode/net_tables.lua | 43 - .../vscripts/invokation/lang/debug.lua | 28 - .../vscripts/invokation/lang/delegation.lua | 59 - .../vscripts/invokation/lang/function.lua | 34 - .../vscripts/invokation/lang/random.lua | 14 - game/scripts/vscripts/middleclass.lua | 193 + game/scripts/vscripts/moses.lua | 3114 ----------------- game/scripts/vscripts/pl/Date.lua | 675 ---- game/scripts/vscripts/pl/List.lua | 566 --- game/scripts/vscripts/pl/Map.lua | 120 - game/scripts/vscripts/pl/MultiMap.lua | 54 - game/scripts/vscripts/pl/OrderedMap.lua | 167 - game/scripts/vscripts/pl/Set.lua | 222 -- game/scripts/vscripts/pl/app.lua | 309 -- game/scripts/vscripts/pl/array2d.lua | 585 ---- game/scripts/vscripts/pl/class.lua | 265 -- game/scripts/vscripts/pl/compat.lua | 252 -- game/scripts/vscripts/pl/comprehension.lua | 285 -- game/scripts/vscripts/pl/config.lua | 207 -- game/scripts/vscripts/pl/data.lua | 654 ---- game/scripts/vscripts/pl/dir.lua | 527 --- game/scripts/vscripts/pl/file.lua | 55 - game/scripts/vscripts/pl/func.lua | 393 --- game/scripts/vscripts/pl/import_into.lua | 91 - game/scripts/vscripts/pl/init.lua | 11 - game/scripts/vscripts/pl/input.lua | 171 - game/scripts/vscripts/pl/lapp.lua | 458 --- game/scripts/vscripts/pl/lexer.lua | 515 --- game/scripts/vscripts/pl/luabalanced.lua | 264 -- game/scripts/vscripts/pl/operator.lua | 209 -- game/scripts/vscripts/pl/path.lua | 572 --- game/scripts/vscripts/pl/permute.lua | 196 -- game/scripts/vscripts/pl/pretty.lua | 438 --- game/scripts/vscripts/pl/seq.lua | 544 --- game/scripts/vscripts/pl/sip.lua | 337 -- game/scripts/vscripts/pl/strict.lua | 138 - game/scripts/vscripts/pl/stringio.lua | 158 - game/scripts/vscripts/pl/stringx.lua | 917 ----- game/scripts/vscripts/pl/tablex.lua | 999 ------ game/scripts/vscripts/pl/template.lua | 202 -- game/scripts/vscripts/pl/test.lua | 164 - game/scripts/vscripts/pl/text.lua | 26 - game/scripts/vscripts/pl/types.lua | 183 - game/scripts/vscripts/pl/url.lua | 51 - game/scripts/vscripts/pl/utils.lua | 947 ----- game/scripts/vscripts/pl/xml.lua | 1165 ------ spec/combo/base_combo_spec.lua | 131 + spec/combo/combo_sequence_spec.lua | 230 ++ spec/combo/combo_spec.lua | 369 ++ spec/combo/combo_step_spec.lua | 70 + spec/combo/combos_spec.lua | 733 ++++ spec/combo/communication_spec.lua | 194 + spec/combo/freestyle_combo_spec.lua | 200 ++ spec/combo/hero_spec.lua | 423 +++ spec/combo/sound_spec.lua | 90 + spec/combo/wait_spec.lua | 121 + spec/combos/BaseCombo_spec.lua | 108 - spec/combos/ComboSequence_spec.lua | 227 -- spec/combos/ComboStep_spec.lua | 61 - spec/combos/Combo_spec.lua | 392 --- spec/combos/Combos_spec.lua | 694 ---- spec/combos/FreestyleCombo_spec.lua | 203 -- spec/combos/PlayerStates_spec.lua | 87 - spec/combos/communication_spec.lua | 126 - spec/combos/hero_spec.lua | 376 -- spec/combos/sound_spec.lua | 91 - spec/dota2/Ability_spec.lua | 112 - spec/dota2/DamageInstance_spec.lua | 99 - spec/dota2/DummyTarget_spec.lua | 164 - spec/dota2/ability_spec.lua | 118 + spec/dota2/damage_instance_spec.lua | 100 + spec/dota2/dummy_target_spec.lua | 169 + spec/helper.lua | 6 +- spec/lang/delegation_spec.lua | 54 - spec/lang/function_spec.lua | 22 +- spec/lang/random_spec.lua | 24 +- spec/support/combo/helpers.lua | 13 + spec/support/dota2/CBaseAnimating.lua | 8 - spec/support/dota2/CBaseEntity.lua | 57 +- spec/support/dota2/CBaseFlex.lua | 8 - spec/support/dota2/CBasePlayer.lua | 8 - spec/support/dota2/CDOTABaseAbility.lua | 59 +- spec/support/dota2/CDOTABaseGameMode.lua | 12 +- spec/support/dota2/CDOTAPlayer.lua | 18 - spec/support/dota2/CDOTAPlayerController.lua | 36 + spec/support/dota2/CDOTA_BaseNPC.lua | 184 +- spec/support/dota2/CDOTA_BaseNPC_Hero.lua | 81 +- spec/support/dota2/CDOTA_Item.lua | 17 +- spec/support/dota2/CustomGameEventManager.lua | 1 - spec/support/dota2/Entities.lua | 1 - spec/support/dota2/EntityFramework.lua | 1 - spec/support/dota2/GameRules.lua | 9 +- spec/support/dota2/PlayerResource.lua | 11 +- spec/support/dota2/Vector.lua | 5 +- spec/support/dota2/clock.lua | 46 + spec/support/dota2/enum.lua | 3 +- spec/support/dota2/global.lua | 39 +- spec/support/dota2/helpers.lua | 12 + spec/support/dota2/init.lua | 20 - spec/support/factories/ability.lua | 6 - spec/support/factories/dota_ability.lua | 11 - spec/support/factories/dota_hero.lua | 58 - spec/support/factories/dota_item.lua | 8 - spec/support/factories/dota_player.lua | 5 - spec/support/factories/dota_unit.lua | 5 - spec/support/factories/entity.lua | 5 - spec/support/factories/hero.lua | 10 - spec/support/factories/init.lua | 12 - spec/support/factories/item.lua | 6 - spec/support/factories/player.lua | 6 - spec/support/factories/unit.lua | 6 - spec/support/factories/vector.lua | 14 - spec/support/factory.lua | 19 - spec/support/factory/ability.lua | 10 + spec/support/factory/dota_ability.lua | 22 + spec/support/factory/dota_entity.lua | 7 + spec/support/factory/dota_hero.lua | 44 + spec/support/factory/dota_hero_invoker.lua | 17 + spec/support/factory/dota_item.lua | 11 + spec/support/factory/dota_player.lua | 17 + spec/support/factory/dota_unit.lua | 7 + spec/support/factory/hero.lua | 10 + spec/support/factory/hero_invoker.lua | 10 + spec/support/factory/init.lua | 26 + spec/support/factory/item.lua | 9 + spec/support/factory/player.lua | 9 + spec/support/factory/unit.lua | 9 + spec/support/factory/vector.lua | 7 + .../{fixtures.lua => fixtures/init.lua} | 1 + .../npc/heroes/npc_dota_hero_axe_txt.lua | 1 + .../npc/heroes/npc_dota_hero_invoker_txt.lua | 1474 +++++--- .../fixtures/scripts/npc/npc_heroes_txt.lua | 110 +- spec/support/game_mode.lua | 2 + spec/support/mock.lua | 124 + 252 files changed, 13680 insertions(+), 26944 deletions(-) create mode 100644 game/scripts/vscripts/compat53/file_mt.lua create mode 100644 game/scripts/vscripts/compat53/init.lua create mode 100644 game/scripts/vscripts/compat53/module.lua create mode 100644 game/scripts/vscripts/inspect.lua create mode 100644 game/scripts/vscripts/invk/combo/base_combo.lua create mode 100644 game/scripts/vscripts/invk/combo/combo.lua create mode 100644 game/scripts/vscripts/invk/combo/combo_sequence.lua create mode 100644 game/scripts/vscripts/invk/combo/combo_step.lua create mode 100644 game/scripts/vscripts/invk/combo/combos.lua create mode 100644 game/scripts/vscripts/invk/combo/communication.lua create mode 100644 game/scripts/vscripts/invk/combo/freestyle_combo.lua create mode 100644 game/scripts/vscripts/invk/combo/hero.lua create mode 100644 game/scripts/vscripts/invk/combo/sound.lua create mode 100644 game/scripts/vscripts/invk/combo/spec.lua create mode 100644 game/scripts/vscripts/invk/combo/wait.lua rename game/scripts/vscripts/{invokation => invk}/const/ability_list.lua (67%) create mode 100644 game/scripts/vscripts/invk/const/combos.lua rename game/scripts/vscripts/{invokation => invk}/const/commands.lua (65%) rename game/scripts/vscripts/{invokation => invk}/const/custom_events.lua (54%) rename game/scripts/vscripts/{invokation => invk}/const/enums.lua (61%) create mode 100644 game/scripts/vscripts/invk/const/inventory.lua create mode 100644 game/scripts/vscripts/invk/const/invoker.lua rename game/scripts/vscripts/{invokation => invk}/const/limits.lua (66%) create mode 100644 game/scripts/vscripts/invk/const/metadata.lua create mode 100644 game/scripts/vscripts/invk/const/net_table.lua rename game/scripts/vscripts/{invokation => invk}/const/precache.lua (84%) rename game/scripts/vscripts/{invokation => invk}/const/settings.lua (54%) rename game/scripts/vscripts/{invokation => invk}/const/sound_events.lua (68%) rename game/scripts/vscripts/{invokation => invk}/const/units.lua (52%) create mode 100644 game/scripts/vscripts/invk/dota2/ability.lua create mode 100644 game/scripts/vscripts/invk/dota2/custom_events.lua create mode 100644 game/scripts/vscripts/invk/dota2/damage_instance.lua create mode 100644 game/scripts/vscripts/invk/dota2/dummy_target.lua create mode 100644 game/scripts/vscripts/invk/dota2/game.lua create mode 100644 game/scripts/vscripts/invk/dota2/invoker.lua create mode 100644 game/scripts/vscripts/invk/dota2/kv.lua create mode 100644 game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua create mode 100644 game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua create mode 100644 game/scripts/vscripts/invk/dota2/kv/item_key_values.lua create mode 100644 game/scripts/vscripts/invk/dota2/kv/items_key_values.lua create mode 100644 game/scripts/vscripts/invk/dota2/kv/key_values.lua create mode 100644 game/scripts/vscripts/invk/dota2/net_table.lua create mode 100644 game/scripts/vscripts/invk/dota2/player.lua create mode 100644 game/scripts/vscripts/invk/dota2/sound_events.lua create mode 100644 game/scripts/vscripts/invk/dota2/talents.lua create mode 100644 game/scripts/vscripts/invk/dota2/timers.lua create mode 100644 game/scripts/vscripts/invk/dota2/unit.lua create mode 100644 game/scripts/vscripts/invk/dota2/units.lua create mode 100644 game/scripts/vscripts/invk/game_mode.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/ability.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/combo.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/debug_misc.lua rename game/scripts/vscripts/{invokation => invk}/game_mode/commands/debug_specials.lua (62%) create mode 100644 game/scripts/vscripts/invk/game_mode/commands/dump_abilities.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/dump_specials.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/globals.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/item.lua create mode 100644 game/scripts/vscripts/invk/game_mode/commands/music.lua create mode 100644 game/scripts/vscripts/invk/game_mode/env.lua create mode 100644 game/scripts/vscripts/invk/lang/function.lua create mode 100644 game/scripts/vscripts/invk/lang/global.lua create mode 100644 game/scripts/vscripts/invk/lang/random.lua create mode 100644 game/scripts/vscripts/invk/lang/string.lua rename game/scripts/vscripts/{invokation => invk}/lang/stub.lua (86%) create mode 100644 game/scripts/vscripts/invk/lang/table.lua create mode 100644 game/scripts/vscripts/invk/lang/value.lua create mode 100644 game/scripts/vscripts/invk/logger.lua delete mode 100644 game/scripts/vscripts/invokation/GameMode.lua delete mode 100644 game/scripts/vscripts/invokation/Logger.lua delete mode 100644 game/scripts/vscripts/invokation/combos/BaseCombo.lua delete mode 100644 game/scripts/vscripts/invokation/combos/Combo.lua delete mode 100644 game/scripts/vscripts/invokation/combos/ComboSequence.lua delete mode 100644 game/scripts/vscripts/invokation/combos/ComboStep.lua delete mode 100644 game/scripts/vscripts/invokation/combos/Combos.lua delete mode 100644 game/scripts/vscripts/invokation/combos/FreestyleCombo.lua delete mode 100644 game/scripts/vscripts/invokation/combos/PlayerStates.lua delete mode 100644 game/scripts/vscripts/invokation/combos/communication.lua delete mode 100644 game/scripts/vscripts/invokation/combos/hero.lua delete mode 100644 game/scripts/vscripts/invokation/combos/sound.lua delete mode 100644 game/scripts/vscripts/invokation/const/abilities.lua delete mode 100644 game/scripts/vscripts/invokation/const/combos.lua delete mode 100644 game/scripts/vscripts/invokation/const/heroes.lua delete mode 100644 game/scripts/vscripts/invokation/const/inventory.lua delete mode 100644 game/scripts/vscripts/invokation/const/invoker.lua delete mode 100644 game/scripts/vscripts/invokation/const/items.lua delete mode 100644 game/scripts/vscripts/invokation/const/metadata.lua delete mode 100644 game/scripts/vscripts/invokation/const/net_table.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/Ability.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/DamageInstance.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/DummyTarget.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/Invoker.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/NetTable.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/Player.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/Unit.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/classes.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/custom_events.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/hats.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/kv.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/kv/AbilityKeyValues.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/kv/HeroKeyValues.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/kv/ItemKeyValues.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/kv/ItemsKeyValues.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/sound_events.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/talents.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/timers.lua delete mode 100644 game/scripts/vscripts/invokation/dota2/units.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/commands.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/commands/dump_specials.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/convars.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/env.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/events.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/events/custom_events.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/events/game_events.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/events/internal.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/game_mode.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/game_rules.lua delete mode 100644 game/scripts/vscripts/invokation/game_mode/net_tables.lua delete mode 100644 game/scripts/vscripts/invokation/lang/debug.lua delete mode 100644 game/scripts/vscripts/invokation/lang/delegation.lua delete mode 100644 game/scripts/vscripts/invokation/lang/function.lua delete mode 100644 game/scripts/vscripts/invokation/lang/random.lua create mode 100644 game/scripts/vscripts/middleclass.lua delete mode 100644 game/scripts/vscripts/moses.lua delete mode 100644 game/scripts/vscripts/pl/Date.lua delete mode 100644 game/scripts/vscripts/pl/List.lua delete mode 100644 game/scripts/vscripts/pl/Map.lua delete mode 100644 game/scripts/vscripts/pl/MultiMap.lua delete mode 100644 game/scripts/vscripts/pl/OrderedMap.lua delete mode 100644 game/scripts/vscripts/pl/Set.lua delete mode 100644 game/scripts/vscripts/pl/app.lua delete mode 100644 game/scripts/vscripts/pl/array2d.lua delete mode 100644 game/scripts/vscripts/pl/class.lua delete mode 100644 game/scripts/vscripts/pl/compat.lua delete mode 100644 game/scripts/vscripts/pl/comprehension.lua delete mode 100644 game/scripts/vscripts/pl/config.lua delete mode 100644 game/scripts/vscripts/pl/data.lua delete mode 100644 game/scripts/vscripts/pl/dir.lua delete mode 100644 game/scripts/vscripts/pl/file.lua delete mode 100644 game/scripts/vscripts/pl/func.lua delete mode 100644 game/scripts/vscripts/pl/import_into.lua delete mode 100644 game/scripts/vscripts/pl/init.lua delete mode 100644 game/scripts/vscripts/pl/input.lua delete mode 100644 game/scripts/vscripts/pl/lapp.lua delete mode 100644 game/scripts/vscripts/pl/lexer.lua delete mode 100644 game/scripts/vscripts/pl/luabalanced.lua delete mode 100644 game/scripts/vscripts/pl/operator.lua delete mode 100644 game/scripts/vscripts/pl/path.lua delete mode 100644 game/scripts/vscripts/pl/permute.lua delete mode 100644 game/scripts/vscripts/pl/pretty.lua delete mode 100644 game/scripts/vscripts/pl/seq.lua delete mode 100644 game/scripts/vscripts/pl/sip.lua delete mode 100644 game/scripts/vscripts/pl/strict.lua delete mode 100644 game/scripts/vscripts/pl/stringio.lua delete mode 100644 game/scripts/vscripts/pl/stringx.lua delete mode 100644 game/scripts/vscripts/pl/tablex.lua delete mode 100644 game/scripts/vscripts/pl/template.lua delete mode 100644 game/scripts/vscripts/pl/test.lua delete mode 100644 game/scripts/vscripts/pl/text.lua delete mode 100644 game/scripts/vscripts/pl/types.lua delete mode 100644 game/scripts/vscripts/pl/url.lua delete mode 100644 game/scripts/vscripts/pl/utils.lua delete mode 100644 game/scripts/vscripts/pl/xml.lua create mode 100644 spec/combo/base_combo_spec.lua create mode 100644 spec/combo/combo_sequence_spec.lua create mode 100644 spec/combo/combo_spec.lua create mode 100644 spec/combo/combo_step_spec.lua create mode 100644 spec/combo/combos_spec.lua create mode 100644 spec/combo/communication_spec.lua create mode 100644 spec/combo/freestyle_combo_spec.lua create mode 100644 spec/combo/hero_spec.lua create mode 100644 spec/combo/sound_spec.lua create mode 100644 spec/combo/wait_spec.lua delete mode 100644 spec/combos/BaseCombo_spec.lua delete mode 100644 spec/combos/ComboSequence_spec.lua delete mode 100644 spec/combos/ComboStep_spec.lua delete mode 100644 spec/combos/Combo_spec.lua delete mode 100644 spec/combos/Combos_spec.lua delete mode 100644 spec/combos/FreestyleCombo_spec.lua delete mode 100644 spec/combos/PlayerStates_spec.lua delete mode 100644 spec/combos/communication_spec.lua delete mode 100644 spec/combos/hero_spec.lua delete mode 100644 spec/combos/sound_spec.lua delete mode 100644 spec/dota2/Ability_spec.lua delete mode 100644 spec/dota2/DamageInstance_spec.lua delete mode 100644 spec/dota2/DummyTarget_spec.lua create mode 100644 spec/dota2/ability_spec.lua create mode 100644 spec/dota2/damage_instance_spec.lua create mode 100644 spec/dota2/dummy_target_spec.lua delete mode 100644 spec/lang/delegation_spec.lua create mode 100644 spec/support/combo/helpers.lua delete mode 100644 spec/support/dota2/CBaseAnimating.lua delete mode 100644 spec/support/dota2/CBaseFlex.lua delete mode 100644 spec/support/dota2/CBasePlayer.lua delete mode 100644 spec/support/dota2/CDOTAPlayer.lua create mode 100644 spec/support/dota2/CDOTAPlayerController.lua create mode 100644 spec/support/dota2/clock.lua create mode 100644 spec/support/dota2/helpers.lua delete mode 100644 spec/support/factories/ability.lua delete mode 100644 spec/support/factories/dota_ability.lua delete mode 100644 spec/support/factories/dota_hero.lua delete mode 100644 spec/support/factories/dota_item.lua delete mode 100644 spec/support/factories/dota_player.lua delete mode 100644 spec/support/factories/dota_unit.lua delete mode 100644 spec/support/factories/entity.lua delete mode 100644 spec/support/factories/hero.lua delete mode 100644 spec/support/factories/init.lua delete mode 100644 spec/support/factories/item.lua delete mode 100644 spec/support/factories/player.lua delete mode 100644 spec/support/factories/unit.lua delete mode 100644 spec/support/factories/vector.lua delete mode 100644 spec/support/factory.lua create mode 100644 spec/support/factory/ability.lua create mode 100644 spec/support/factory/dota_ability.lua create mode 100644 spec/support/factory/dota_entity.lua create mode 100644 spec/support/factory/dota_hero.lua create mode 100644 spec/support/factory/dota_hero_invoker.lua create mode 100644 spec/support/factory/dota_item.lua create mode 100644 spec/support/factory/dota_player.lua create mode 100644 spec/support/factory/dota_unit.lua create mode 100644 spec/support/factory/hero.lua create mode 100644 spec/support/factory/hero_invoker.lua create mode 100644 spec/support/factory/init.lua create mode 100644 spec/support/factory/item.lua create mode 100644 spec/support/factory/player.lua create mode 100644 spec/support/factory/unit.lua create mode 100644 spec/support/factory/vector.lua rename spec/support/{fixtures.lua => fixtures/init.lua} (99%) create mode 100644 spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_axe_txt.lua create mode 100644 spec/support/game_mode.lua create mode 100644 spec/support/mock.lua diff --git a/.busted b/.busted index 992ced8..58a5bf6 100644 --- a/.busted +++ b/.busted @@ -15,6 +15,8 @@ return { default = { ROOT = { "./spec" }, recursive = true, + verbose = true, + output = "htest", }, _all = { verbose = true, diff --git a/game/scripts/vscripts/addon_game_mode.lua b/game/scripts/vscripts/addon_game_mode.lua index 9620e8e..081cf0b 100644 --- a/game/scripts/vscripts/addon_game_mode.lua +++ b/game/scripts/vscripts/addon_game_mode.lua @@ -1,13 +1,14 @@ -require("invokation.lang.stub") -require("invokation.dota2.classes") +require("invk.lang.stub") +require("invk.lang.global") +require("compat53.init") -local GameMode = require("invokation.GameMode") +local GameMode = require("invk.game_mode") function Precache(context) - GameMode.Precache(context) + GameMode.precache(context) end function Activate() - GameRules.Invokation = GameMode() - GameRules.Invokation:Activate() + GameRules.Invokation = GameMode:new() + GameRules.Invokation:activate() end diff --git a/game/scripts/vscripts/compat53/file_mt.lua b/game/scripts/vscripts/compat53/file_mt.lua new file mode 100644 index 0000000..6433619 --- /dev/null +++ b/game/scripts/vscripts/compat53/file_mt.lua @@ -0,0 +1,71 @@ +local lua_version = _VERSION:sub(-3) + +local M = {} + +local unpack = lua_version == "5.1" and unpack or table.unpack + +local function addasterisk(fmt) + if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then + return "*"..fmt + else + return fmt + end +end + +function M.update_file_meta(file_meta, is_luajit52) + + -- make '*' optional for file:read and file:lines + + local file_lines = file_meta.__index.lines + file_meta.__index.lines = function(self, ...) + local n = select('#', ...) + for i = 1, n do + local a = select(i, ...) + local b = addasterisk(a) + -- as an optimization we only allocate a table for the + -- modified format arguments when we have a '*' somewhere + if a ~= b then + local args = { ... } + args[i] = b + for j = i+1, n do + args[j] = addasterisk(args[j]) + end + return file_lines(self, unpack(args, 1, n)) + end + end + return file_lines(self, ...) + end + + local file_read = file_meta.__index.read + file_meta.__index.read = function(self, ...) + local n = select('#', ...) + for i = 1, n do + local a = select(i, ...) + local b = addasterisk(a) + -- as an optimization we only allocate a table for the + -- modified format arguments when we have a '*' somewhere + if a ~= b then + local args = { ... } + args[i] = b + for j = i+1, n do + args[j] = addasterisk(args[j]) + end + return file_read(self, unpack(args, 1, n)) + end + end + return file_read(self, ...) + end + + if not is_luajit52 then + local file_write = file_meta.__index.write + file_meta.__index.write = function(self, ...) + local ret, err = file_write(self, ...) + if ret then + return self + end + return ret, err + end + end +end + +return M diff --git a/game/scripts/vscripts/compat53/init.lua b/game/scripts/vscripts/compat53/init.lua new file mode 100644 index 0000000..b507571 --- /dev/null +++ b/game/scripts/vscripts/compat53/init.lua @@ -0,0 +1,325 @@ +local lua_version = _VERSION:sub(-3) + + +if lua_version < "5.3" then + + local _G, pairs, require, select, type = + _G, pairs, require, select, type + local debug, io = debug, io + local unpack = lua_version == "5.1" and unpack or table.unpack + + local M = require("compat53.module") + + -- select the most powerful getmetatable function available + local gmt = type(debug) == "table" and debug.getmetatable or + getmetatable or function() return false end + -- metatable for file objects from Lua's standard io library + local file_meta = gmt(io.stdout) + + + -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) + local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" + local is_luajit52 = is_luajit and + #setmetatable({}, { __len = function() return 1 end }) == 1 + + + if type(file_meta) == "table" and type(file_meta.__index) == "table" then + local file_mt = require("compat53.file_mt") + file_mt.update_file_meta(file_meta, is_luajit52) + end -- got a valid metatable for file objects + + + -- changes for Lua 5.1 only + if lua_version == "5.1" then + + -- cache globals + local error, pcall, rawset, setmetatable, tostring, xpcall = + error, pcall, rawset, setmetatable, tostring, xpcall + local coroutine, package, string = coroutine, package, string + local coroutine_resume = coroutine.resume + local coroutine_running = coroutine.running + local coroutine_status = coroutine.status + local coroutine_yield = coroutine.yield + local io_type = io.type + + + -- make package.searchers available as an alias for package.loaders + local p_index = { searchers = package.loaders } + setmetatable(package, { + __index = p_index, + __newindex = function(p, k, v) + if k == "searchers" then + rawset(p, "loaders", v) + p_index.searchers = v + else + rawset(p, k, v) + end + end + }) + + + if type(file_meta) == "table" and type(file_meta.__index) == "table" then + if not is_luajit then + local function helper(_, var_1, ...) + if var_1 == nil then + if (...) ~= nil then + error((...), 2) + end + end + return var_1, ... + end + + local function lines_iterator(st) + return helper(st, st.f:read(unpack(st, 1, st.n))) + end + + local file_write = file_meta.__index.write + file_meta.__index.write = function(self, ...) + local res, msg, errno = file_write(self, ...) + if res then + return self + else + return nil, msg, errno + end + end + + file_meta.__index.lines = function(self, ...) + if io_type(self) == "closed file" then + error("attempt to use a closed file", 2) + end + local st = { f=self, n=select('#', ...), ... } + for i = 1, st.n do + local t = type(st[i]) + if t == "string" then + local fmt = st[i]:match("^*?([aln])") + if not fmt then + error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) + end + st[i] = "*"..fmt + elseif t ~= "number" then + error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) + end + end + return lines_iterator, st + end + end -- not luajit + end -- file_meta valid + + + -- the (x)pcall implementations start a new coroutine internally + -- to allow yielding even in Lua 5.1. to allow for accurate + -- stack traces we keep track of the nested coroutine activations + -- in the weak tables below: + local weak_meta = { __mode = "kv" } + -- maps the internal pcall coroutines to the user coroutine that + -- *should* be running if pcall didn't use coroutines internally + local pcall_mainOf = setmetatable({}, weak_meta) + -- table that maps each running coroutine started by pcall to + -- the coroutine that resumed it (user coroutine *or* pcall + -- coroutine!) + local pcall_previous = setmetatable({}, weak_meta) + -- reverse of `pcall_mainOf`. maps a user coroutine to the + -- currently active pcall coroutine started within it + local pcall_callOf = setmetatable({}, weak_meta) + -- similar to `pcall_mainOf` but is used only while executing + -- the error handler of xpcall (thus no nesting is necessary!) + local xpcall_running = setmetatable({}, weak_meta) + + -- handle debug functions + if type(debug) == "table" then + local debug_getinfo = debug.getinfo + local debug_traceback = debug.traceback + + if not is_luajit then + local function calculate_trace_level(co, level) + if level ~= nil then + for out = 1, 1/0 do + local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "") + if info == nil then + local max = out-1 + if level <= max then + return level + end + return nil, level-max + end + end + end + return 1 + end + + local stack_pattern = "\nstack traceback:" + local stack_replace = "" + function debug.traceback(co, msg, level) + local lvl + local nilmsg + if type(co) ~= "thread" then + co, msg, level = coroutine_running(), co, msg + end + if msg == nil then + msg = "" + nilmsg = true + elseif type(msg) ~= "string" then + return msg + end + if co == nil then + msg = debug_traceback(msg, level or 1) + else + local xpco = xpcall_running[co] + if xpco ~= nil then + lvl, level = calculate_trace_level(xpco, level) + if lvl then + msg = debug_traceback(xpco, msg, lvl) + else + msg = msg..stack_pattern + end + lvl, level = calculate_trace_level(co, level) + if lvl then + local trace = debug_traceback(co, "", lvl) + msg = msg..trace:gsub(stack_pattern, stack_replace) + end + else + co = pcall_callOf[co] or co + lvl, level = calculate_trace_level(co, level) + if lvl then + msg = debug_traceback(co, msg, lvl) + else + msg = msg..stack_pattern + end + end + co = pcall_previous[co] + while co ~= nil do + lvl, level = calculate_trace_level(co, level) + if lvl then + local trace = debug_traceback(co, "", lvl) + msg = msg..trace:gsub(stack_pattern, stack_replace) + end + co = pcall_previous[co] + end + end + if nilmsg then + msg = msg:gsub("^\n", "") + end + msg = msg:gsub("\n\t%(tail call%): %?", "\000") + msg = msg:gsub("\n\t%.%.%.\n", "\001\n") + msg = msg:gsub("\n\t%.%.%.$", "\001") + msg = msg:gsub("(%z+)\001(%z+)", function(some, other) + return "\n\t(..."..#some+#other.."+ tail call(s)...)" + end) + msg = msg:gsub("\001(%z+)", function(zeros) + return "\n\t(..."..#zeros.."+ tail call(s)...)" + end) + msg = msg:gsub("(%z+)\001", function(zeros) + return "\n\t(..."..#zeros.."+ tail call(s)...)" + end) + msg = msg:gsub("%z+", function(zeros) + return "\n\t(..."..#zeros.." tail call(s)...)" + end) + msg = msg:gsub("\001", function() + return "\n\t..." + end) + return msg + end + end -- is not luajit + end -- debug table available + + + if not is_luajit52 then + local coroutine_running52 = M.coroutine.running + function M.coroutine.running() + local co, ismain = coroutine_running52() + if ismain then + return co, true + else + return pcall_mainOf[co] or co, false + end + end + end + + if not is_luajit then + local function pcall_results(current, call, success, ...) + if coroutine_status(call) == "suspended" then + return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...))) + end + if pcall_previous then + pcall_previous[call] = nil + local main = pcall_mainOf[call] + if main == current then current = nil end + pcall_callOf[main] = current + end + pcall_mainOf[call] = nil + return success, ... + end + + local function pcall_exec(current, call, ...) + local main = pcall_mainOf[current] or current + pcall_mainOf[call] = main + if pcall_previous then + pcall_previous[call] = current + pcall_callOf[main] = call + end + return pcall_results(current, call, coroutine_resume(call, ...)) + end + + local coroutine_create52 = M.coroutine.create + + local function pcall_coroutine(func) + if type(func) ~= "function" then + local callable = func + func = function (...) return callable(...) end + end + return coroutine_create52(func) + end + + function M.pcall(func, ...) + local current = coroutine_running() + if not current then return pcall(func, ...) end + return pcall_exec(current, pcall_coroutine(func), ...) + end + + local function xpcall_catch(current, call, msgh, success, ...) + if not success then + xpcall_running[current] = call + local ok, result = pcall(msgh, ...) + xpcall_running[current] = nil + if not ok then + return false, "error in error handling ("..tostring(result)..")" + end + return false, result + end + return true, ... + end + + function M.xpcall(f, msgh, ...) + local current = coroutine_running() + if not current then + local args, n = { ... }, select('#', ...) + return xpcall(function() return f(unpack(args, 1, n)) end, msgh) + end + local call = pcall_coroutine(f) + return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) + end + end -- not luajit + + end -- lua 5.1 + + + -- handle exporting to global scope + local function extend_table(from, to) + if from ~= to then + for k,v in pairs(from) do + if type(v) == "table" and + type(to[k]) == "table" and + v ~= to[k] then + extend_table(v, to[k]) + else + to[k] = v + end + end + end + end + + extend_table(M, _G) + +end -- lua < 5.3 + +-- vi: set expandtab softtabstop=3 shiftwidth=3 : diff --git a/game/scripts/vscripts/compat53/module.lua b/game/scripts/vscripts/compat53/module.lua new file mode 100644 index 0000000..52b1dd6 --- /dev/null +++ b/game/scripts/vscripts/compat53/module.lua @@ -0,0 +1,894 @@ +local _G, _VERSION = _G, _VERSION +local lua_version = _VERSION:sub(-3) + + +local M = _G + +if lua_version < "5.3" then + + -- cache globals in upvalues + local error, ipairs, pairs, pcall, require, select, setmetatable, type = + error, ipairs, pairs, pcall, require, select, setmetatable, type + local debug, io, math, package, string, table = + debug, io, math, package, string, table + local io_lines = io.lines + local io_read = io.read + local io_open = io.open + local io_popen = io.popen + local io_tmpfile = io.tmpfile + local unpack = lua_version == "5.1" and unpack or table.unpack + local debug_setmetatable = type(debug) == "table" and debug.setmetatable + + -- create module table + M = {} + local M_meta = { + __index = _G, + -- __newindex is set at the end + } + setmetatable(M, M_meta) + + -- create subtables + M.io = setmetatable({}, { __index = io }) + M.math = setmetatable({}, { __index = math }) + M.string = setmetatable({}, { __index = string }) + M.table = setmetatable({}, { __index = table }) + M.utf8 = {} + + + -- select the most powerful getmetatable function available + local gmt = type(debug) == "table" and debug.getmetatable or + getmetatable or function() return false end + + -- type checking functions + local checkinteger -- forward declararation + + local function argcheck(cond, i, f, extra) + if not cond then + error("bad argument #"..i.." to '"..f.."' ("..extra..")", 0) + end + end + + + -- load utf8 library + local utf8_ok, utf8lib = pcall(require, "compat53.utf8") + if utf8_ok then + if lua_version == "5.1" then + utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*" + end + for k,v in pairs(utf8lib) do + M.utf8[k] = v + end + package.loaded["utf8"] = M.utf8 + end + + + -- load table library + local table_ok, tablib = pcall(require, "compat53.table") + if table_ok then + for k,v in pairs(tablib) do + M.table[k] = v + end + end + + + -- load io functions + local io_ok, iolib = pcall(require, "compat53.io") + if io_ok then + for k,v in pairs(iolib) do + M.io[k] = v + end + end + + + -- load string packing functions + local str_ok, strlib = pcall(require, "compat53.string") + if str_ok then + for k,v in pairs(strlib) do + M.string[k] = v + end + end + + + -- try Roberto's struct module for string packing/unpacking if + -- compat53.string is unavailable + if not str_ok then + local struct_ok, struct = pcall(require, "struct") + if struct_ok then + M.string.pack = struct.pack + M.string.packsize = struct.size + M.string.unpack = struct.unpack + end + end + + + -- update math library + do + local maxint, minint = 1 + + while maxint+1 > maxint and 2*maxint > maxint do + maxint = maxint * 2 + end + if 2*maxint <= maxint then + maxint = 2*maxint-1 + minint = -maxint-1 + else + maxint = maxint + minint = -maxint + end + M.math.maxinteger = maxint + M.math.mininteger = minint + + function M.math.tointeger(n) + n = tonumber(n) + if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then + return n + end + return nil + end + + function M.math.type(n) + if type(n) == "number" then + if n <= maxint and n >= minint and n % 1 == 0 then + return "integer" + else + return "float" + end + else + return nil + end + end + + function checkinteger(x, i, f) + local t = type(x) + if t ~= "number" then + error("bad argument #"..i.." to '"..f.. + "' (number expected, got "..t..")", 0) + elseif x > maxint or x < minint or x % 1 ~= 0 then + error("bad argument #"..i.." to '"..f.. + "' (number has no integer representation)", 0) + else + return x + end + end + + function M.math.ult(m, n) + m = checkinteger(m, "1", "math.ult") + n = checkinteger(n, "2", "math.ult") + if m >= 0 and n < 0 then + return true + elseif m < 0 and n >= 0 then + return false + else + return m < n + end + end + end + + + -- assert should allow non-string error objects + function M.assert(cond, ...) + if cond then + return cond, ... + elseif select('#', ...) > 0 then + error((...), 0) + else + error("assertion failed!", 0) + end + end + + + -- ipairs should respect __index metamethod + do + local function ipairs_iterator(st, var) + var = var + 1 + local val = st[var] + if val ~= nil then + return var, st[var] + end + end + function M.ipairs(t) + if gmt(t) ~= nil then -- t has metatable + return ipairs_iterator, t, 0 + else + return ipairs(t) + end + end + end + + + -- make '*' optional for io.read and io.lines + do + local function addasterisk(fmt) + if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then + return "*"..fmt + else + return fmt + end + end + + function M.io.read(...) + local n = select('#', ...) + for i = 1, n do + local a = select(i, ...) + local b = addasterisk(a) + -- as an optimization we only allocate a table for the + -- modified format arguments when we have a '*' somewhere. + if a ~= b then + local args = { ... } + args[i] = b + for j = i+1, n do + args[j] = addasterisk(args[j]) + end + return io_read(unpack(args, 1, n)) + end + end + return io_read(...) + end + + -- PUC-Rio Lua 5.1 uses a different implementation for io.lines! + function M.io.lines(...) + local n = select('#', ...) + for i = 2, n do + local a = select(i, ...) + local b = addasterisk(a) + -- as an optimization we only allocate a table for the + -- modified format arguments when we have a '*' somewhere. + if a ~= b then + local args = { ... } + args[i] = b + for j = i+1, n do + args[j] = addasterisk(args[j]) + end + return io_lines(unpack(args, 1, n)) + end + end + return io_lines(...) + end + end + + + -- update table library (if C module not available) + if not table_ok then + local table_concat = table.concat + local table_insert = table.insert + local table_remove = table.remove + local table_sort = table.sort + + function M.table.concat(list, sep, i, j) + local mt = gmt(list) + if type(mt) == "table" and type(mt.__len) == "function" then + local src = list + list, i, j = {}, i or 1, j or mt.__len(src) + for k = i, j do + list[k] = src[k] + end + end + return table_concat(list, sep, i, j) + end + + function M.table.insert(list, ...) + local mt = gmt(list) + local has_mt = type(mt) == "table" + local has_len = has_mt and type(mt.__len) == "function" + if has_mt and (has_len or mt.__index or mt.__newindex) then + local e = (has_len and mt.__len(list) or #list)+1 + local nargs, pos, value = select('#', ...), ... + if nargs == 1 then + pos, value = e, pos + elseif nargs == 2 then + pos = checkinteger(pos, "2", "table.insert") + argcheck(1 <= pos and pos <= e, "2", "table.insert", + "position out of bounds" ) + else + error("wrong number of arguments to 'insert'", 0) + end + for i = e-1, pos, -1 do + list[i+1] = list[i] + end + list[pos] = value + else + return table_insert(list, ...) + end + end + + function M.table.move(a1, f, e, t, a2) + a2 = a2 or a1 + f = checkinteger(f, "2", "table.move") + argcheck(f > 0, "2", "table.move", + "initial position must be positive") + e = checkinteger(e, "3", "table.move") + t = checkinteger(t, "4", "table.move") + if e >= f then + local m, n, d = 0, e-f, 1 + if t > f then m, n, d = n, m, -1 end + for i = m, n, d do + a2[t+i] = a1[f+i] + end + end + return a2 + end + + function M.table.remove(list, pos) + local mt = gmt(list) + local has_mt = type(mt) == "table" + local has_len = has_mt and type(mt.__len) == "function" + if has_mt and (has_len or mt.__index or mt.__newindex) then + local e = (has_len and mt.__len(list) or #list) + pos = pos ~= nil and checkinteger(pos, "2", "table.remove") or e + if pos ~= e then + argcheck(1 <= pos and pos <= e+1, "2", "table.remove", + "position out of bounds" ) + end + local result = list[pos] + while pos < e do + list[pos] = list[pos+1] + pos = pos + 1 + end + list[pos] = nil + return result + else + return table_remove(list, pos) + end + end + + do + local function pivot(list, cmp, a, b) + local m = b - a + if m > 2 then + local c = a + (m-m%2)/2 + local x, y, z = list[a], list[b], list[c] + if not cmp(x, y) then + x, y, a, b = y, x, b, a + end + if not cmp(y, z) then + y, b = z, c + end + if not cmp(x, y) then + y, b = x, a + end + return b, y + else + return b, list[b] + end + end + + local function lt_cmp(a, b) + return a < b + end + + local function qsort(list, cmp, b, e) + if b < e then + local i, j, k, val = b, e, pivot(list, cmp, b, e) + while i < j do + while i < j and cmp(list[i], val) do + i = i + 1 + end + while i < j and not cmp(list[j], val) do + j = j - 1 + end + if i < j then + list[i], list[j] = list[j], list[i] + if i == k then k = j end -- update pivot position + i, j = i+1, j-1 + end + end + if i ~= k and not cmp(list[i], val) then + list[i], list[k] = val, list[i] + k = i -- update pivot position + end + qsort(list, cmp, b, i == k and i-1 or i) + return qsort(list, cmp, i+1, e) + end + end + + function M.table.sort(list, cmp) + local mt = gmt(list) + local has_mt = type(mt) == "table" + local has_len = has_mt and type(mt.__len) == "function" + if has_len then + cmp = cmp or lt_cmp + local len = mt.__len(list) + return qsort(list, cmp, 1, len) + else + return table_sort(list, cmp) + end + end + end + + local function unpack_helper(list, i, j, ...) + if j < i then + return ... + else + return unpack_helper(list, i, j-1, list[j], ...) + end + end + function M.table.unpack(list, i, j) + local mt = gmt(list) + local has_mt = type(mt) == "table" + local has_len = has_mt and type(mt.__len) == "function" + if has_mt and (has_len or mt.__index) then + i, j = i or 1, j or (has_len and mt.__len(list)) or #list + return unpack_helper(list, i, j) + else + return unpack(list, i, j) + end + end + end -- update table library + + + -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2 + if lua_version == "5.1" then + -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) + local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" + local is_luajit52 = is_luajit and + #setmetatable({}, { __len = function() return 1 end }) == 1 + + -- cache globals in upvalues + local load, loadfile, loadstring, setfenv, xpcall = + load, loadfile, loadstring, setfenv, xpcall + local coroutine, os = coroutine, os + local coroutine_create = coroutine.create + local coroutine_resume = coroutine.resume + local coroutine_running = coroutine.running + local coroutine_status = coroutine.status + local coroutine_yield = coroutine.yield + local io_input = io.input + local io_open = io.open + local io_output = io.output + local io_write = io.write + local math_log = math.log + local os_execute = os.execute + local string_find = string.find + local string_format = string.format + local string_gmatch = string.gmatch + local string_gsub = string.gsub + local string_match = string.match + local string_rep = string.rep + local table_concat = table.concat + + -- create subtables + M.coroutine = setmetatable({}, { __index = coroutine }) + M.os = setmetatable({}, { __index = os }) + M.package = setmetatable({}, { __index = package }) + + -- handle debug functions + if type(debug) == "table" then + local debug_setfenv = debug.setfenv + local debug_getfenv = debug.getfenv + + M.debug = setmetatable({}, { __index = debug }) + + if not is_luajit52 then + function M.debug.setuservalue(obj, value) + if type(obj) ~= "userdata" then + error("bad argument #1 to 'setuservalue' (userdata expected, got ".. + type(obj)..")", 2) + end + if value == nil then value = _G end + if type(value) ~= "table" then + error("bad argument #2 to 'setuservalue' (table expected, got ".. + type(value)..")", 2) + end + return debug_setfenv(obj, value) + end + + function M.debug.getuservalue(obj) + if type(obj) ~= "userdata" then + return nil + else + local v = debug_getfenv(obj) + if v == _G or v == package then + return nil + end + return v + end + end + + function M.debug.setmetatable(value, tab) + debug_setmetatable(value, tab) + return value + end + end -- not luajit with compat52 enabled + end -- debug table available + + + if not is_luajit52 then + function M.pairs(t) + local mt = gmt(t) + if type(mt) == "table" and type(mt.__pairs) == "function" then + return mt.__pairs(t) + else + return pairs(t) + end + end + end + + + if not is_luajit then + local function check_mode(mode, prefix) + local has = { text = false, binary = false } + for i = 1,#mode do + local c = mode:sub(i, i) + if c == "t" then has.text = true end + if c == "b" then has.binary = true end + end + local t = prefix:sub(1, 1) == "\27" and "binary" or "text" + if not has[t] then + return "attempt to load a "..t.." chunk (mode is '"..mode.."')" + end + end + + function M.load(ld, source, mode, env) + mode = mode or "bt" + local chunk, msg + if type( ld ) == "string" then + if mode ~= "bt" then + local merr = check_mode(mode, ld) + if merr then return nil, merr end + end + chunk, msg = loadstring(ld, source) + else + local ld_type = type(ld) + if ld_type ~= "function" then + error("bad argument #1 to 'load' (function expected, got ".. + ld_type..")", 2) + end + if mode ~= "bt" then + local checked, merr = false, nil + local function checked_ld() + if checked then + return ld() + else + checked = true + local v = ld() + merr = check_mode(mode, v or "") + if merr then return nil end + return v + end + end + chunk, msg = load(checked_ld, source) + if merr then return nil, merr end + else + chunk, msg = load(ld, source) + end + end + if not chunk then + return chunk, msg + end + if env ~= nil then + setfenv(chunk, env) + end + return chunk + end + + M.loadstring = M.load + + function M.loadfile(file, mode, env) + mode = mode or "bt" + if mode ~= "bt" then + local f = io_open(file, "rb") + if f then + local prefix = f:read(1) + f:close() + if prefix then + local merr = check_mode(mode, prefix) + if merr then return nil, merr end + end + end + end + local chunk, msg = loadfile(file) + if not chunk then + return chunk, msg + end + if env ~= nil then + setfenv(chunk, env) + end + return chunk + end + end -- not luajit + + + if not is_luajit52 then + function M.rawlen(v) + local t = type(v) + if t ~= "string" and t ~= "table" then + error("bad argument #1 to 'rawlen' (table or string expected)", 2) + end + return #v + end + end + + + if not is_luajit then + function M.xpcall(f, msgh, ...) + local args, n = { ... }, select('#', ...) + return xpcall(function() return f(unpack(args, 1, n)) end, msgh) + end + end + + + if not is_luajit52 then + function M.os.execute(cmd) + local code = os_execute(cmd) + -- Lua 5.1 does not report exit by signal. + if code == 0 then + return true, "exit", code + else + if package.config:sub(1, 1) == '/' then + code = code/256 -- only correct on Linux! + end + return nil, "exit", code + end + end + end + + + if not table_ok and not is_luajit52 then + M.table.pack = function(...) + return { n = select('#', ...), ... } + end + end + + + local main_coroutine = coroutine_create(function() end) + + function M.coroutine.create(func) + local success, result = pcall(coroutine_create, func) + if not success then + if type(func) ~= "function" then + error("bad argument #1 (function expected)", 0) + end + result = coroutine_create(function(...) return func(...) end) + end + return result + end + + if not is_luajit52 then + function M.coroutine.running() + local co = coroutine_running() + if co then + return co, false + else + return main_coroutine, true + end + end + end + + function M.coroutine.yield(...) + local co, flag = coroutine_running() + if co and not flag then + return coroutine_yield(...) + else + error("attempt to yield from outside a coroutine", 0) + end + end + + if not is_luajit then + function M.coroutine.resume(co, ...) + if co == main_coroutine then + return false, "cannot resume non-suspended coroutine" + else + return coroutine_resume(co, ...) + end + end + + function M.coroutine.status(co) + local notmain = coroutine_running() + if co == main_coroutine then + return notmain and "normal" or "running" + else + return coroutine_status(co) + end + end + end -- not luajit + + + if not is_luajit then + M.math.log = function(x, base) + if base ~= nil then + return math_log(x)/math_log(base) + else + return math_log(x) + end + end + end + + + if not is_luajit then + function M.package.searchpath(name, path, sep, rep) + sep = (sep or "."):gsub("(%p)", "%%%1") + rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1") + local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1") + local msg = {} + for subpath in path:gmatch("[^;]+") do + local fpath = subpath:gsub("%?", pname) + local f = io_open(fpath, "r") + if f then + f:close() + return fpath + end + msg[#msg+1] = "\n\tno file '" .. fpath .. "'" + end + return nil, table_concat(msg) + end + end + + + local function fix_pattern(pattern) + return (string_gsub(pattern, "%z", "%%z")) + end + + function M.string.find(s, pattern, ...) + return string_find(s, fix_pattern(pattern), ...) + end + + function M.string.gmatch(s, pattern) + return string_gmatch(s, fix_pattern(pattern)) + end + + function M.string.gsub(s, pattern, ...) + return string_gsub(s, fix_pattern(pattern), ...) + end + + function M.string.match(s, pattern, ...) + return string_match(s, fix_pattern(pattern), ...) + end + + if not is_luajit then + function M.string.rep(s, n, sep) + if sep ~= nil and sep ~= "" and n >= 2 then + return s .. string_rep(sep..s, n-1) + else + return string_rep(s, n) + end + end + end + + if not is_luajit then + do + local addqt = { + ["\n"] = "\\\n", + ["\\"] = "\\\\", + ["\""] = "\\\"" + } + + local function addquoted(c, d) + return (addqt[c] or string_format(d~="" and "\\%03d" or "\\%d", c:byte()))..d + end + + function M.string.format(fmt, ...) + local args, n = { ... }, select('#', ...) + local i = 0 + local function adjust_fmt(lead, mods, kind) + if #lead % 2 == 0 then + i = i + 1 + if kind == "s" then + args[i] = _G.tostring(args[i]) + elseif kind == "q" then + args[i] = '"'..string_gsub(args[i], "([%z%c\\\"\n])(%d?)", addquoted)..'"' + return lead.."%"..mods.."s" + end + end + end + fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt) + return string_format(fmt, unpack(args, 1, n)) + end + end + end + + + function M.io.write(...) + local res, msg, errno = io_write(...) + if res then + return io_output() + else + return nil, msg, errno + end + end + + if not is_luajit then + local function helper(st, var_1, ...) + if var_1 == nil then + if st.doclose then st.f:close() end + if (...) ~= nil then + error((...), 2) + end + end + return var_1, ... + end + + local function lines_iterator(st) + return helper(st, st.f:read(unpack(st, 1, st.n))) + end + + function M.io.lines(fname, ...) + local doclose, file, msg + if fname ~= nil then + doclose, file, msg = true, io_open(fname, "r") + if not file then error(msg, 2) end + else + doclose, file = false, io_input() + end + local st = { f=file, doclose=doclose, n=select('#', ...), ... } + for i = 1, st.n do + local t = type(st[i]) + if t == "string" then + local fmt = st[i]:match("^%*?([aln])") + if not fmt then + error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) + end + st[i] = "*"..fmt + elseif t ~= "number" then + error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) + end + end + return lines_iterator, st + end + end -- not luajit + + if is_luajit then + local compat_file_meta = {} + local compat_file_meta_loaded = 0 + + local function load_compat_file_meta(file_meta) + -- fill compat_file_meta with original entries + for k, v in pairs(file_meta) do + compat_file_meta[k] = v + end + compat_file_meta.__index = {} + for k, v in pairs(file_meta.__index) do + compat_file_meta.__index[k] = v + end + + compat_file_meta_loaded = 1 + + -- update it with compatibility functions + local file_mt_ok, file_mt = pcall(require, "compat53.file_mt") + if file_mt_ok then + file_mt.update_file_meta(compat_file_meta, is_luajit52) + + compat_file_meta_loaded = 2 + end + end + + local function return_fd(fd, err, code) + if not fd then + return fd, err, code + end + if fd and debug_setmetatable then + if compat_file_meta_loaded == 0 then + local file_meta = gmt(fd) + load_compat_file_meta(file_meta) + end + if compat_file_meta_loaded == 2 then + debug_setmetatable(fd, compat_file_meta) + end + end + return fd + end + + function M.io.open(...) + return return_fd(io_open(...)) + end + + function M.io.popen(...) + return return_fd(io_popen(...)) + end + + function M.io.tmpfile(...) + return return_fd(io_tmpfile(...)) + end + end + + end -- lua 5.1 + + -- further write should be forwarded to _G + M_meta.__newindex = _G + +end -- lua < 5.3 + + +-- return module table +return M + +-- vi: set expandtab softtabstop=3 shiftwidth=3 : diff --git a/game/scripts/vscripts/inspect.lua b/game/scripts/vscripts/inspect.lua new file mode 100644 index 0000000..9900a0b --- /dev/null +++ b/game/scripts/vscripts/inspect.lua @@ -0,0 +1,371 @@ +local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table +local inspect = {Options = {}, } + + + + + + + + + + + + + + + + + +inspect._VERSION = 'inspect.lua 3.1.0' +inspect._URL = 'http://github.com/kikito/inspect.lua' +inspect._DESCRIPTION = 'human-readable representations of tables' +inspect._LICENSE = [[ + MIT LICENSE + + Copyright (c) 2022 Enrique García Cota + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] +inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end }) +inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end }) + +local tostring = tostring +local rep = string.rep +local match = string.match +local char = string.char +local gsub = string.gsub +local fmt = string.format + +local _rawget +if rawget then + _rawget = rawget +else + _rawget = function(t, k) return t[k] end +end + +local function rawpairs(t) + return next, t, nil +end + + + +local function smartQuote(str) + if match(str, '"') and not match(str, "'") then + return "'" .. str .. "'" + end + return '"' .. gsub(str, '"', '\\"') .. '"' +end + + +local shortControlCharEscapes = { + ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", + ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127", +} +local longControlCharEscapes = { ["\127"] = "\127" } +for i = 0, 31 do + local ch = char(i) + if not shortControlCharEscapes[ch] then + shortControlCharEscapes[ch] = "\\" .. i + longControlCharEscapes[ch] = fmt("\\%03d", i) + end +end + +local function escape(str) + return (gsub(gsub(gsub(str, "\\", "\\\\"), + "(%c)%f[0-9]", longControlCharEscapes), + "%c", shortControlCharEscapes)) +end + +local luaKeywords = { + ['and'] = true, + ['break'] = true, + ['do'] = true, + ['else'] = true, + ['elseif'] = true, + ['end'] = true, + ['false'] = true, + ['for'] = true, + ['function'] = true, + ['goto'] = true, + ['if'] = true, + ['in'] = true, + ['local'] = true, + ['nil'] = true, + ['not'] = true, + ['or'] = true, + ['repeat'] = true, + ['return'] = true, + ['then'] = true, + ['true'] = true, + ['until'] = true, + ['while'] = true, +} + +local function isIdentifier(str) + return type(str) == "string" and + not not str:match("^[_%a][_%a%d]*$") and + not luaKeywords[str] +end + +local flr = math.floor +local function isSequenceKey(k, sequenceLength) + return type(k) == "number" and + flr(k) == k and + 1 <= (k) and + k <= sequenceLength +end + +local defaultTypeOrders = { + ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, + ['function'] = 5, ['userdata'] = 6, ['thread'] = 7, +} + +local function sortKeys(a, b) + local ta, tb = type(a), type(b) + + + if ta == tb and (ta == 'string' or ta == 'number') then + return (a) < (b) + end + + local dta = defaultTypeOrders[ta] or 100 + local dtb = defaultTypeOrders[tb] or 100 + + + return dta == dtb and ta < tb or dta < dtb +end + +local function getKeys(t) + + local seqLen = 1 + while _rawget(t, seqLen) ~= nil do + seqLen = seqLen + 1 + end + seqLen = seqLen - 1 + + local keys, keysLen = {}, 0 + for k in rawpairs(t) do + if not isSequenceKey(k, seqLen) then + keysLen = keysLen + 1 + keys[keysLen] = k + end + end + table.sort(keys, sortKeys) + return keys, keysLen, seqLen +end + +local function countCycles(x, cycles) + if type(x) == "table" then + if cycles[x] then + cycles[x] = cycles[x] + 1 + else + cycles[x] = 1 + for k, v in rawpairs(x) do + countCycles(k, cycles) + countCycles(v, cycles) + end + countCycles(getmetatable(x), cycles) + end + end +end + +local function makePath(path, a, b) + local newPath = {} + local len = #path + for i = 1, len do newPath[i] = path[i] end + + newPath[len + 1] = a + newPath[len + 2] = b + + return newPath +end + + +local function processRecursive(process, + item, + path, + visited) + if item == nil then return nil end + if visited[item] then return visited[item] end + + local processed = process(item, path) + if type(processed) == "table" then + local processedCopy = {} + visited[item] = processedCopy + local processedKey + + for k, v in rawpairs(processed) do + processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) + if processedKey ~= nil then + processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) + end + end + + local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) + if type(mt) ~= 'table' then mt = nil end + setmetatable(processedCopy, mt) + processed = processedCopy + end + return processed +end + +local function puts(buf, str) + buf.n = buf.n + 1 + buf[buf.n] = str +end + + + +local Inspector = {} + + + + + + + + + + +local Inspector_mt = { __index = Inspector } + +local function tabify(inspector) + puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level)) +end + +function Inspector:getId(v) + local id = self.ids[v] + local ids = self.ids + if not id then + local tv = type(v) + id = (ids[tv] or 0) + 1 + ids[v], ids[tv] = id, id + end + return tostring(id) +end + +function Inspector:putValue(v) + local buf = self.buf + local tv = type(v) + if tv == 'string' then + puts(buf, smartQuote(escape(v))) + elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or + tv == 'cdata' or tv == 'ctype' then + puts(buf, tostring(v)) + elseif tv == 'table' and not self.ids[v] then + local t = v + + if t == inspect.KEY or t == inspect.METATABLE then + puts(buf, tostring(t)) + elseif self.level >= self.depth then + puts(buf, '{...}') + else + if self.cycles[t] > 1 then puts(buf, fmt('<%d>', self:getId(t))) end + + local keys, keysLen, seqLen = getKeys(t) + + puts(buf, '{') + self.level = self.level + 1 + + for i = 1, seqLen + keysLen do + if i > 1 then puts(buf, ',') end + if i <= seqLen then + puts(buf, ' ') + self:putValue(t[i]) + else + local k = keys[i - seqLen] + tabify(self) + if isIdentifier(k) then + puts(buf, k) + else + puts(buf, "[") + self:putValue(k) + puts(buf, "]") + end + puts(buf, ' = ') + self:putValue(t[k]) + end + end + + local mt = getmetatable(t) + if type(mt) == 'table' then + if seqLen + keysLen > 0 then puts(buf, ',') end + tabify(self) + puts(buf, ' = ') + self:putValue(mt) + end + + self.level = self.level - 1 + + if keysLen > 0 or type(mt) == 'table' then + tabify(self) + elseif seqLen > 0 then + puts(buf, ' ') + end + + puts(buf, '}') + end + + else + puts(buf, fmt('<%s %d>', tv, self:getId(v))) + end +end + + + + +function inspect.inspect(root, options) + options = options or {} + + local depth = options.depth or (math.huge) + local newline = options.newline or '\n' + local indent = options.indent or ' ' + local process = options.process + + if process then + root = processRecursive(process, root, {}, {}) + end + + local cycles = {} + countCycles(root, cycles) + + local inspector = setmetatable({ + buf = { n = 0 }, + ids = {}, + cycles = cycles, + depth = depth, + level = 0, + newline = newline, + indent = indent, + }, Inspector_mt) + + inspector:putValue(root) + + return table.concat(inspector.buf) +end + +setmetatable(inspect, { + __call = function(_, root, options) + return inspect.inspect(root, options) + end, +}) + +return inspect diff --git a/game/scripts/vscripts/invk/combo/base_combo.lua b/game/scripts/vscripts/invk/combo/base_combo.lua new file mode 100644 index 0000000..9d06f8d --- /dev/null +++ b/game/scripts/vscripts/invk/combo/base_combo.lua @@ -0,0 +1,144 @@ +local class = require("middleclass") + +local Logger = require("invk.logger") +local tbl = require("invk.lang.table") + +local LOGNAME = "combo" +local ERR_NOT_IMPLEMENTED = "Not implemented" + +--- @alias invk.combo.ComboId integer | string + +--- @class invk.combo.Metrics +--- @field count integer # Abilities count since start +--- @field damage number # Accumulated damage since start +--- @field duration number # Duration since start + +--- BaseCombo is a base class for combos. +--- @class invk.combo.BaseCombo : middleclass.Class, invk.log.Mixin, invk.combo.ComboSpec +--- @field state invk.combo.State +--- @field metrics invk.combo.Metrics +--- @field logger? invk.Logger +local M = class("invk.combo.BaseCombo") + +M:include(Logger.Mixin) + +--- Hard-coded freestyle combo id. +--- @type invk.combo.ComboId +M.FREESTYLE_COMBO_ID = "freestyle" + +--- @enum invk.combo.State +M.State = { + Initial = "initial", + Started = "started", + Failed = "failed", + PreFinished = "pre_finished", + Finished = "finished", +} + +--- @class invk.combo.BaseComboOptions +--- @field logger? invk.Logger # Logger instance + +--- Constructor. +--- @param spec invk.combo.ComboSpec # Combo data +--- @param options? invk.combo.BaseComboOptions # Options +function M:initialize(spec, options) + local opts = options or {} + + tbl.extend(self, spec) + + self.state = M.State.Initial + self.metrics = { + count = 0, + damage = 0, + duration = 0, + } + + if opts.logger then + self.logger = opts.logger:child(LOGNAME) + end +end + +function M:is_freestyle() + return self.id == M.FREESTYLE_COMBO_ID +end + +function M:is_progressing_abilities() + return self.state ~= M.State.Failed + and self.state ~= M.State.PreFinished + and self.state ~= M.State.Finished +end + +function M:is_progressing_damage() + return self.state == M.State.Started or self.state == M.State.PreFinished +end + +--- Increments the total amount of damage dealt during this combo session. +--- @param amount number # Damage amount +--- @return number # Accumulated damage amount +function M:increment_damage(amount) + self.metrics.damage = self.metrics.damage + amount + + return self.metrics.damage +end + +--- Returns the current step. +--- @abstract Subclasses must override it. +--- @return invk.combo.ComboStep? # The current step or `nil` +--- @diagnostic disable-next-line: unused +function M:current_step() + error(ERR_NOT_IMPLEMENTED) +end + +--- @return integer? +function M:current_step_id() + local step = self:current_step() + + return step and step.id +end + +--- Returns the current next steps. +--- @abstract Subclasses must override it. +--- @return invk.combo.ComboStep[] # Array of next steps +--- @diagnostic disable-next-line: unused +function M:next_steps() + error(ERR_NOT_IMPLEMENTED) +end + +--- @return integer[] +function M:next_steps_ids() + return tbl.map(self:next_steps(), function(step) + return step.id + end) +end + +--- Progresses the combo with the given ability if possible. +--- @abstract Subclasses must override it. +--- @param _ability invk.dota2.Ability # Ability instance +--- @return boolean # `true` if succeeded, `false` otherwise +--- @diagnostic disable-next-line: unused +function M:progress(_ability) + error(ERR_NOT_IMPLEMENTED) +end + +--- Marks the combo as failed. +function M:fail() + self.state = M.State.Failed +end + +--- Progresses combo to pre finish if possible. +--- @abstract Subclasses must override it. +--- @return boolean # `true` if succeeded, `false` otherwise +--- @diagnostic disable-next-line: unused +function M:pre_finish() + error(ERR_NOT_IMPLEMENTED) +end + +--- Finishes the combo if possible. +--- @abstract Subclasses must override it. +--- @return boolean # `true` if succeeded, `false` otherwise +--- @diagnostic disable-next-line: unused +function M:finish() + error(ERR_NOT_IMPLEMENTED) +end + +return M diff --git a/game/scripts/vscripts/invk/combo/combo.lua b/game/scripts/vscripts/invk/combo/combo.lua new file mode 100644 index 0000000..79f3dec --- /dev/null +++ b/game/scripts/vscripts/invk/combo/combo.lua @@ -0,0 +1,87 @@ +local class = require("middleclass") + +local BaseCombo = require("invk.combo.base_combo") +local ComboSequence = require("invk.combo.combo_sequence") +local Wait = require("invk.combo.wait") + +local STATES = ComboSequence.STATES + +--- Combo class. +--- @class invk.combo.Combo : invk.combo.BaseCombo +--- @field clock invk.dota2.ClockFn +--- @field sequence invk.combo.ComboSequence +--- @field wait invk.combo.Wait +local M = class("invk.combo.Combo", BaseCombo) + +--- @class invk.combo.ComboOptions : invk.combo.BaseComboOptions +--- @field clock? invk.dota2.ClockFn # Clock function that returns the current time + +--- Constructor. +--- @param spec invk.combo.ComboSpec # Combo data +--- @param options? invk.combo.ComboOptions # Options +function M:initialize(spec, options) + BaseCombo.initialize(self, spec, options) + + local opts = options or {} + + self.clock = opts.clock or Time + self.sequence = ComboSequence:new(self.id, self.sequence, { clock = self.clock }) + self.wait = Wait:new(self.clock) +end + +--- Generates a DOT formatted string from the combo's FSM. +--- @return string # DOT string +function M:todot() + return self.sequence:todot() +end + +--- Returns the current step. +function M:current_step() + return self.sequence.current +end + +--- Returns the current next steps. +function M:next_steps() + return self.sequence.next +end + +--- Progresses the combo with the given ability if possible. +function M:progress(ability) + local progressed = self.sequence:progress(ability.name) + + if progressed then + self.state = BaseCombo.State.Started + self.metrics.count = self.metrics.count + 1 + self.wait:enqueue(ability) + end + + return progressed +end + +--- Progresses combo to pre finish if possible. +function M:pre_finish() + local pre_finish = self.sequence:pre_finish() + + if pre_finish then + local enter_time = self.sequence:enter_time(STATES.PRE_FINISH) or 0 + + self.state = BaseCombo.State.PreFinished + self.wait:finish(enter_time) + end + + return pre_finish +end + +--- Finishes combo if possible. +function M:finish() + local finished = self.sequence:finish() + + if finished then + self.state = BaseCombo.State.Finished + self.metrics.duration = self.sequence.duration + end + + return finished +end + +return M diff --git a/game/scripts/vscripts/invk/combo/combo_sequence.lua b/game/scripts/vscripts/invk/combo/combo_sequence.lua new file mode 100644 index 0000000..3088a1c --- /dev/null +++ b/game/scripts/vscripts/invk/combo/combo_sequence.lua @@ -0,0 +1,231 @@ +local class = require("middleclass") +local fsm = require("fsm") + +local ComboStep = require("invk.combo.combo_step") +local Logger = require("invk.logger") +local func = require("invk.lang.function") +local tbl = require("invk.lang.table") + +--- @todo Use an LRU cache +local CACHE = {} + +--- ComboSequence class. +--- @class invk.combo.ComboSequence : middleclass.Class, invk.log.Mixin +--- @field id integer +--- @field clock invk.dota2.ClockFn +--- @field sequence invk.combo.ComboStep[] +--- @field current_id integer? +--- @field current invk.combo.ComboStep? +--- @field next_ids integer[] +--- @field next invk.combo.ComboStep[] +--- @field enter_times { [invk.combo.StateName]: number? } +--- @field leave_times { [invk.combo.StateName]: number? } +--- @field fsm any +--- @field logger? invk.Logger +local M = class("invk.combo.ComboSequence") + +M:include(Logger.Mixin) + +--- @alias invk.combo.StateName (invk.combo.MetaStateName | string) + +--- Sequence state. +--- @enum invk.combo.MetaStateName +M.STATES = { + INITIAL = "start", + PRE_FINISH = "pre_finish", + FINISH = "finish", +} + +--- @alias invk.combo.EventName (invk.combo.MetaEventName | string) + +--- @enum invk.combo.MetaEventName +M.EVENTS = { + PRE_FINISH = "pre_finish", + FINISH = "finish", +} + +--- @class invk.combo.Event +--- @field name invk.combo.EventName +--- @field from invk.combo.StateName +--- @field to invk.combo.StateName + +--- @param steps invk.combo.ComboStep[] +--- @param step invk.combo.ComboStep +--- @return invk.combo.Event[] +local function step_events(steps, step) + local next_ids = step.next or {} + + return tbl.map(next_ids, function(next_id) + local next_step = assertf(steps[next_id], "invalid next_id %d", next_id) + + --- @type invk.combo.Event + local event = { + name = next_step.event, + from = step.state, + to = next_step.state, + } + + return event + end) +end + +--- @param steps invk.combo.ComboStep[] +local function fsm_def(steps) + local first_step = assert(steps[1], "received empty steps sequence") + local last_step = assert(steps[#steps], "received empty steps sequence") + + --- @type invk.combo.Event + local ev_init = { + name = first_step.event, + from = M.STATES.INITIAL, + to = first_step.state, + } + + --- @type invk.combo.Event + local ev_prefinish = { + name = M.EVENTS.PRE_FINISH, + from = last_step.state, + to = M.STATES.PRE_FINISH, + } + + --- @type invk.combo.Event + local ev_finish = { + name = M.EVENTS.FINISH, + from = M.STATES.PRE_FINISH, + to = M.STATES.FINISH, + } + + --- @type invk.combo.Event[] + local events = { ev_init } + + for _, step in ipairs(steps) do + events = tbl.append(events, step_events(steps, step)) + end + + events[#events + 1] = ev_prefinish + events[#events + 1] = ev_finish + + return { initial = M.STATES.INITIAL, events = events } +end + +--- @class invk.combo.ComboSequenceOptions +--- @field logger? invk.Logger # Logger instance +--- @field clock invk.dota2.ClockFn # Clock function that returns the current time + +--- Constructor. +--- @param id integer # Combo id +--- @param specs invk.combo.ComboStepSpec[] # Sequence of steps +--- @param options? invk.combo.ComboSequenceOptions # Options +function M:initialize(id, specs, options) + local opts = options or {} + + self.id = id + self.logger = opts.logger + self.clock = opts.clock + self.sequence = tbl.map(specs, func.ctor(ComboStep)) + + local first_step = assert(self.sequence[1], "received empty sequence") + + self.current_id = nil + self.current = nil + self.next_ids = { first_step.id } + self.next = { first_step } + self.enter_times = {} + self.leave_times = {} + + self:create_fsm() +end + +function M:create_fsm() + if CACHE[self.id] == nil then + CACHE[self.id] = fsm_def(self.sequence) + end + + self.fsm = fsm.create(CACHE[self.id]) + + --- @param from invk.combo.StateName + --- @param to invk.combo.StateName + self.fsm.onstatechange = function(_, _, from, to) + local now = self.clock() + + self.leave_times[from] = now + self.enter_times[to] = now + self.current_id = ComboStep.extract_step_id(to) + self.current = self.sequence[self.current_id or 0] + self.next_ids = (self.current and self.current.next) or {} + --- @diagnostic disable-next-line: param-type-not-match + self.next = tbl.at(self.sequence, table.unpack(self.next_ids)) + + self:debug_state("state_change") + end + + self:debug_state("start") +end + +--- Generates a DOT formatted string from the sequence's FSM. +--- @return string # DOT string +function M:todot() + return self.fsm:todot() +end + +function M:debug_state(message) + local state = { + state = self.fsm.current, + current = self.current_id or "", + next = self.next_ids, + } + + self:d(message, state) +end + +--- Returns the time when the sequence entered the given state. +--- @param state invk.combo.StateName # State name +--- @return number? # Time or `nil` if state is invalid +function M:enter_time(state) + return self.enter_times[state] +end + +--- Returns the time when the sequence left the given state. +--- @param state invk.combo.StateName # State name +--- @return number? # Time or `nil` if state is invalid +function M:leave_time(state) + return self.leave_times[state] +end + +--- Progresses the sequence with the given event if possible. +--- @param event invk.combo.EventName # Event +--- @return boolean # `true` if succeeded, `false` otherwise +function M:progress(event) + local event_fn = self.fsm[event] + + if event_fn == nil then + return false + end + + return event_fn(self.fsm) +end + +--- Progresses the sequence to pre finish if possible. +--- @return boolean # `true` if succeeded, `false` otherwise +function M:pre_finish() + return self.fsm[M.EVENTS.PRE_FINISH](self.fsm) +end + +--- Finishes the sequence if possible. +--- @return boolean # `true` if succeeded, `false` otherwise +function M:finish() + local finished = self.fsm[M.EVENTS.FINISH](self.fsm) + + if finished then + local started_at = self:leave_time(M.STATES.INITIAL) + local finished_at = self:enter_time(M.STATES.FINISH) + + if started_at ~= nil and finished_at ~= nil then + self.duration = finished_at - started_at + end + end + + return finished +end + +return M diff --git a/game/scripts/vscripts/invk/combo/combo_step.lua b/game/scripts/vscripts/invk/combo/combo_step.lua new file mode 100644 index 0000000..7e4f267 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/combo_step.lua @@ -0,0 +1,45 @@ +local class = require("middleclass") + +local tbl = require("invk.lang.table") + +--- ComboStep class. +--- @class invk.combo.ComboStep : middleclass.Class, invk.combo.ComboStepSpec +--- @field state invk.combo.StateName +--- @field event invk.combo.EventName +local M = class("invk.combo.ComboStep") + +--- Constructor. +--- @param data invk.combo.ComboStepSpec # Step data +function M:initialize(data) + tbl.extend(self, data) + + self.state = M.gen_state_name(self) + self.event = M.gen_event_name(self) +end + +--- Generates a state name from a given step. +--- @param step invk.combo.ComboStep # Step instance +--- @return invk.combo.StateName # State name +function M.gen_state_name(step) + return F("%d:%s", step.id, step.name) +end + +--- Extracts a step id from a given state name. +--- @param state invk.combo.StateName # State name +--- @return integer? # Step id if state name is valid, `nil` otherwise +function M.extract_step_id(state) + local id = state:match("^(%d+):") + + return id and ( + tonumber(id) --[[@as integer]] + ) +end + +--- Generates an event name from a given step. +--- @param step invk.combo.ComboStep # Step instance +--- @return invk.combo.EventName # Event name +function M.gen_event_name(step) + return step.name +end + +return M diff --git a/game/scripts/vscripts/invk/combo/combos.lua b/game/scripts/vscripts/invk/combo/combos.lua new file mode 100644 index 0000000..cec2432 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/combos.lua @@ -0,0 +1,440 @@ +local class = require("middleclass") + +local ABILITY_LIST = require("invk.const.ability_list") +local BaseCombo = require("invk.combo.base_combo") +local Combo = require("invk.combo.combo") +local DummyTarget = require("invk.dota2.dummy_target") +local FreestyleCombo = require("invk.combo.freestyle_combo") +local Logger = require("invk.logger") +local Timers = require("invk.dota2.timers") +local combo_comms = require("invk.combo.communication") +local combo_hero = require("invk.combo.hero") +local combo_sound = require("invk.combo.sound") + +local LOGNAME = "combos" + +local ERRF_COMBO_NOT_FOUND = "Combo %q not found" +local ERRF_COMBO_NOT_ACTIVE = "Player %d has no active combo" +local WARNF_COMBO_NOT_FINISHED = "Combo %q can't be finished for player %d" + +--- @class invk.combo.PlayerState +--- @field combo? invk.combo.BaseCombo +--- @field dummy? invk.dota2.DummyTarget +--- @field capturing? boolean + +--- Combos manager. +--- @class invk.combo.Combos : middleclass.Class, invk.log.Mixin +--- @field specs { [invk.combo.ComboId]: invk.combo.ComboSpec } +--- @field state { [PlayerID]: invk.combo.PlayerState } +--- @field net_table invk.dota2.NetTable +--- @field logger? invk.Logger +local M = class("invk.combo.Combos") + +M:include(Logger.Mixin) + +--- @return { [invk.combo.ComboId]: invk.combo.ComboSpec } +local function load_specs() + local raw_specs = require("invk.const.combos") + local specs = {} + + for _, spec in ipairs(raw_specs) do + specs[spec.id] = spec + end + + return specs +end + +local function game_time() + return GameRules:GetGameTime() +end + +--- @class invk.combo.CombosOptions +--- @field logger? invk.Logger # Logger instance + +--- Constructor. +--- @param net_table invk.dota2.NetTable # NetTable instance +--- @param options? invk.combo.CombosOptions # Options table +function M:initialize(net_table, options) + local opts = options or {} + + self.net_table = net_table + self.state = {} + + if opts.logger then + self.logger = opts.logger:child(LOGNAME) + end + + self:load() +end + +function M:load() + self:d("Loading") + + self.specs = load_specs() + + self.net_table:set(self.net_table.keys.COMBOS, self.specs) +end + +--- @param id invk.combo.ComboId +--- @return invk.combo.BaseCombo +function M:create(id) + if id == BaseCombo.FREESTYLE_COMBO_ID then + return FreestyleCombo:new({ logger = self.logger }) + end + + local spec = self.specs[id] + + if spec == nil then + errorf(ERRF_COMBO_NOT_FOUND, id) + end + + return Combo:new(spec, { logger = self.logger, clock = game_time }) +end + +--- @private +--- @param player CDOTAPlayerController +--- @return invk.combo.PlayerState +function M:player_state(player) + local id = player:GetPlayerID() + + if self.state[id] == nil then + self.state[id] = {} + end + + return self.state[id] +end + +--- @private +--- @param player CDOTAPlayerController +--- @return invk.combo.BaseCombo +function M:require_combo(player) + local combo = self:player_state(player).combo + + if combo == nil then + errorf(ERRF_COMBO_NOT_ACTIVE, player:GetPlayerID()) + end + + return combo +end + +--- @private +--- @param player CDOTAPlayerController +--- @param combo invk.combo.BaseCombo +function M:setup(player, combo) + local state = self:player_state(player) + + state.combo = combo + + combo_hero.setup(player, combo) + + if state.dummy == nil then + state.dummy = DummyTarget:new() + + combo_sound.on_dummy_create(state.dummy) + end + + state.dummy:spawn() +end + +--- @private +--- @param player CDOTAPlayerController +--- @param options? invk.combo.hero.TeardownOptions +function M:teardown(player, options) + local state = self:player_state(player) + + state.combo = nil + + combo_hero.teardown(player, options) + + if state.dummy ~= nil then + state.dummy:kill() + end +end + +--- @private +--- @param player CDOTAPlayerController +--- @param combo invk.combo.Combo +function M:start(player, combo) + self:setup(player, combo) + + combo_sound.on_combo_start(player) + combo_comms.send_started(player, combo) +end + +--- @private +--- @param player CDOTAPlayerController +--- @param combo invk.combo.Combo +function M:stop(player, combo) + self:teardown(player, { hard_reset = true }) + + combo_sound.on_combo_stop(player) + combo_comms.send_stopped(player, combo) +end + +--- Handles ability usage. +--- @param player CDOTAPlayerController # Player instance +--- @param unit invk.dota2.Unit # Unit instance +--- @param ability invk.dota2.Ability # Ability instance +function M:on_ability_used(player, unit, ability) + if ABILITY_LIST:is_ignored(ability) then + return + end + + self:d("on_ability_used", { + player = player:GetPlayerID(), + unit = unit.name, + ability = ability.name, + }) + + self:capture_ability(player, ability) + self:on_progress(player, ability) +end + +--- Handles damage instances being dealt to entities. +--- @param damage invk.dota2.DamageInstance # DamageInstance instance +function M:on_entity_hurt(damage) + local player = damage:attacker_player_owner() + + if player == nil then + return + end + + self:d("on_entity_hurt", { + category = damage.category, + amount = damage.amount, + victim = damage:victim_name(), + attacker = damage:attacker_name(), + inflictor = damage:inflictor_name(), + }) + + self:on_progress_damage(player, damage) +end + +--- Handles item purchases. +--- @param player CDOTAPlayerController # Player instance +--- @param purchase invk.combo.ItemPurchase # Purchase information +function M:on_item_purchased(player, purchase) + local state = self:player_state(player) + + if not state.combo or not state.combo:is_freestyle() then + return + end + + self:d("on_item_purchased", { + player = player:GetPlayerID(), + purchase = purchase, + }) + + combo_hero.refund_purchase(player, purchase) +end + +--- Starts a combo for the given player. +--- @param player CDOTAPlayerController # Player instance +--- @param combo invk.combo.Combo # Combo +function M:on_start(player, combo) + self:d("on_start", { + player = player:GetPlayerID(), + id = combo.id, + }) + + local state = self:player_state(player) + local current = state.combo + + if current ~= nil and current.id ~= combo.id then + self:stop(player, current) + else + self:teardown(player, { hard_reset = current == nil }) + end + + self:start(player, combo) +end + +--- Stops currently active combo for the given player. +--- @param player CDOTAPlayerController # Player instance +function M:on_stop(player) + self:d("on_stop", { player = player:GetPlayerID() }) + + local combo = self:require_combo(player) + + self:stop(player, combo) +end + +--- Restarts a combo for the given player. +--- @param player CDOTAPlayerController # Player instance +--- @param options? invk.combo.hero.TeardownOptions # Options table +function M:on_restart(player, options) + self:d("on_restart", { + player = player:GetPlayerID(), + options = options, + }) + + local combo = self:require_combo(player) + + self:teardown(player, options) + + combo = self:create(combo.id) + + self:start(player, combo) +end + +--- Progresses the currently active combo for the given player. +--- @param player CDOTAPlayerController # Player instance +--- @param ability invk.dota2.Ability # Ability instance +function M:on_progress(player, ability) + local combo = self:player_state(player).combo + + if not combo then + return + end + + if not combo:is_progressing_abilities() then + return + end + + self:d("on_progress", { + player = player:GetPlayerID(), + ability = ability.name, + }) + + if combo:progress(ability) then + if combo.metrics.count == 1 then + combo_comms.send_in_progress(player, combo) + end + + combo_comms.send_progress(player, combo) + + if combo:pre_finish() then + self:on_pre_finish(player) + end + elseif not ability:is_invocation_ability() then + self:on_fail(player, ability) + end +end + +--- Increments the damage amount of the currently active combo for the given player. +--- @param player CDOTAPlayerController # Player instance +--- @param damage invk.dota2.DamageInstance # DamageInstance instance +function M:on_progress_damage(player, damage) + local combo = self:player_state(player).combo + + if not combo then + return + end + + if not combo:is_progressing_damage() then + return + end + + self:d("on_progress_damage", { + player = player:GetPlayerID(), + category = damage.category, + amount = damage.amount, + victim = damage:victim_name(), + attacker = damage:attacker_name(), + inflictor = damage:inflictor_name(), + }) + + --- @fixme Only increment damage coming from currently active spells (including forged spirits) + --- or autoattacks + combo:increment_damage(damage.amount) + combo_comms.send_progress(player, combo) +end + +--- Fails and stops currently active combo for the given player. +--- @param player CDOTAPlayerController # Player instance +--- @param ability invk.dota2.Ability # Ability instance +function M:on_fail(player, ability) + self:d("on_fail", { player = player:GetPlayerID() }) + + local combo = self:require_combo(player) + + combo:fail() + + combo_sound.on_combo_step_error(player) + combo_comms.send_step_error(player, combo, ability) +end + +--- Preemptively finishes a combo for the given player. +--- @param player CDOTAPlayerController # Player instance +function M:on_pre_finish(player) + self:d("on_pre_finish", { player = player:GetPlayerID() }) + + --- @type invk.combo.Combo + local combo = self:require_combo(player) + + combo_comms.send_pre_finish(player, combo) + + Timers:create({ + delay = combo.wait.duration, + callback = self.on_finish, + args = { self, player }, + }) +end + +--- Finishes a combo for the given player. +--- @param player CDOTAPlayerController # Player instance +function M:on_finish(player) + self:d("on_finish", { player = player:GetPlayerID() }) + + local combo = self:require_combo(player) + + if not combo:finish() then + self:warnf(WARNF_COMBO_NOT_FINISHED, combo.id, player:GetPlayerID()) + return + end + + self:d("finished", { + id = combo.id, + now = game_time(), + }) + + combo_sound.on_combo_finished(player) + combo_comms.send_finished(player, combo) +end + +--- Starts capturing ability usage for the given player. +--- @param player CDOTAPlayerController # Player instance +function M:start_capturing_abilities(player) + self:d("start_capturing_abilities", { player = player:GetPlayerID() }) + self:player_state(player).capturing = true +end + +--- Stops capturing ability usage for the given player. +--- @param player CDOTAPlayerController # Player instance +function M:stop_capturing_abilities(player) + self:d("stop_capturing_abilities", { player = player:GetPlayerID() }) + self:player_state(player).capturing = nil +end + +--- Captures an instance of ability usage for the given player. +--- @param player CDOTAPlayerController # Player instance +--- @param ability invk.dota2.Ability # Ability instance +function M:capture_ability(player, ability) + if self:player_state(player).capturing then + combo_comms.send_ability_used(player, ability) + end +end + +--- Handles freestyle hero level up. +--- @param player CDOTAPlayerController # Player instance +--- @param options? invk.combo.LevelUpOptions +function M:freestyle_hero_level_up(player, options) + local combo = self:player_state(player).combo + + if not combo then + return + end + + if not combo:is_freestyle() then + return + end + + self:d("freestyle_hero_level_up", { + player = player:GetPlayerID(), + options = options, + }) + + combo_hero.level_up(player, options) +end + +return M diff --git a/game/scripts/vscripts/invk/combo/communication.lua b/game/scripts/vscripts/invk/combo/communication.lua new file mode 100644 index 0000000..16f68e3 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/communication.lua @@ -0,0 +1,113 @@ +local CUSTOM_EVENTS = require("invk.const.custom_events") +local CustomEvents = require("invk.dota2.custom_events") + +--- Internal combos communication helpers. +--- @class invk.combos.communication +local M = {} + +--- Sends a custom event notifying that an ability was used. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param ability invk.dota2.Ability # Ability +function M.send_ability_used(player, ability) + --- @type invk.custom_events.CombatLogAbilityUsedPayload + local payload = { + ability = ability.name, + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBAT_LOG_ABILITY_USED, player, payload) +end + +--- Sends a custom event notifying that a combo started. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.BaseCombo # Combo +function M.send_started(player, combo) + --- @type invk.custom_events.ComboStartedPayload + local payload = { + id = combo.id, + next = combo:next_steps_ids(), + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_STARTED, player, payload) +end + +--- Sends a custom event notifying that a combo stopped. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.BaseCombo # Combo +function M.send_stopped(player, combo) + --- @type invk.custom_events.ComboStoppedPayload + local payload = { + id = combo.id, + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_STOPPED, player, payload) +end + +--- Sends a custom event notifying that a combo is in progress. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.BaseCombo # Combo +function M.send_in_progress(player, combo) + --- @type invk.custom_events.ComboInProgressPayload + local payload = { + id = combo.id, + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_IN_PROGRESS, player, payload) +end + +--- Sends a custom event notifying that a combo progressed. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.BaseCombo # Combo +function M.send_progress(player, combo) + --- @type invk.custom_events.ComboProgressPayload + local payload = { + id = combo.id, + metrics = combo.metrics, + next = combo:next_steps_ids(), + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_PROGRESS, player, payload) +end + +--- Sends a custom event notifying about a combo step error. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.Combo # Combo +--- @param ability invk.dota2.Ability # Ability used that caused the error +function M.send_step_error(player, combo, ability) + --- @type invk.custom_events.ComboStepErrorPayload + local payload = { + id = combo.id, + expected = combo:next_steps_ids(), + ability = ability.name, + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_STEP_ERROR, player, payload) +end + +--- Sends a custom event notifying that a combo entered pre-finish state. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.Combo # Combo +function M.send_pre_finish(player, combo) + --- @type invk.custom_events.ComboPreFinishPayload + local payload = { + id = combo.id, + metrics = combo.metrics, + wait = combo.wait.duration, + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_PRE_FINISH, player, payload) +end + +--- Sends a custom event notifying that a combo finished. +--- @param player CDOTAPlayerController # Player to send the event to +--- @param combo invk.combo.Combo # Combo +function M.send_finished(player, combo) + --- @type invk.custom_events.ComboFinishedPayload + local payload = { + id = combo.id, + metrics = combo.metrics, + } + + return CustomEvents.send_player(CUSTOM_EVENTS.EVENT_COMBO_FINISHED, player, payload) +end + +return M diff --git a/game/scripts/vscripts/invk/combo/freestyle_combo.lua b/game/scripts/vscripts/invk/combo/freestyle_combo.lua new file mode 100644 index 0000000..3fb700a --- /dev/null +++ b/game/scripts/vscripts/invk/combo/freestyle_combo.lua @@ -0,0 +1,76 @@ +local class = require("middleclass") + +local BaseCombo = require("invk.combo.base_combo") +local S = require("invk.combo.spec") +local talents = require("invk.dota2.talents") + +--- FreestyleCombo is a Combo class that implements a freestyle sequence. +--- @class invk.combo.FreestyleCombo : invk.combo.BaseCombo +local M = class("invk.combo.FreestyleCombo", BaseCombo) + +--- @type invk.combo.ComboSpec +local SPEC = { + id = BaseCombo.FREESTYLE_COMBO_ID, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Brutal, + difficulty_rating = S.DifficultyRating.LiterallyUnplayable, + hero_level = 30, + orbs = { 1, 1, 1 }, + talents = talents.Talents.NONE, + gold = 99999, + items = {}, + tags = { "freestyle" }, + sequence = {}, +} + +--- @class invk.combo.FreestyleComboOptions : invk.combo.BaseComboOptions + +--- Constructor. +--- @param options? invk.combo.FreestyleComboOptions +function M:initialize(options) + BaseCombo.initialize(self, SPEC, options) + + self.state = BaseCombo.State.Started +end + +--- Freestyle combos have no steps. +--- @diagnostic disable-next-line: unused +function M:current_step() + return nil +end + +--- Freestyle combos have no steps. +--- @diagnostic disable-next-line: unused +function M:next_steps() + return {} +end + +--- Always progresses the combo with the given ability. +function M:progress(ability) + if ability:is_invocation_ability() then + return false + end + + self.metrics.count = self.metrics.count + 1 + + return true +end + +--- Freestyle combos never fail. +--- @diagnostic disable-next-line: unused +function M:fail() end + +--- Freestyle combos never pre finish. +--- @diagnostic disable-next-line: unused +function M:pre_finish() + return false +end + +--- Freestyle combos never finish. +--- @diagnostic disable-next-line: unused +function M:finish() + return false +end + +return M diff --git a/game/scripts/vscripts/invk/combo/hero.lua b/game/scripts/vscripts/invk/combo/hero.lua new file mode 100644 index 0000000..33affa2 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/hero.lua @@ -0,0 +1,108 @@ +local Invoker = require("invk.dota2.invoker") +local LIMITS = require("invk.const.limits") +local Player = require("invk.dota2.player") +local SOUND_EVENTS = require("invk.const.sound_events") +local UNITS = require("invk.const.units") +local Unit = require("invk.dota2.unit") + +--- Internal combos hero helpers. +--- @class invk.combos.hero +local M = {} + +--- Runs the setup phase of a combo. +--- @param base_player CDOTAPlayerController # Player playing the combo +--- @param combo invk.combo.BaseCombo # Combo +function M.setup(base_player, combo) + local player = Player:new(base_player) + local unit = Unit:new(player.hero) + + unit:hero_level_up_to(combo.hero_level) + unit:add_items_by_name(combo.items, { only_missing = true }) + + if combo.gold ~= nil and combo.gold > 0 then + unit:give_gold(combo.gold) + end + + unit:hold() +end + +--- @class invk.combo.hero.TeardownOptions +--- @field hard_reset boolean # Perform a full reset + +--- Runs the teardown phase of a combo. +--- @param base_player CDOTAPlayerController # Player playing the combo +--- @param options? invk.combo.hero.TeardownOptions # Options table +function M.teardown(base_player, options) + local opts = options or {} + local player = Player:new(base_player) + local unit = Unit:new(player.hero) + + unit:stop_sound(SOUND_EVENTS.SNDEVT_INVOKER_METEOR_LOOP) + unit:end_item_cooldowns() + unit:end_ability_cooldowns() + unit:remove_dropped_items() + + for _, unit_name in pairs(UNITS.INVOKER_SPAWNED) do + player:remove_owned_units_by_name(unit_name) + end + + if opts.hard_reset then + local invoker = Invoker:new(player.hero) + + unit:remove_items() + -- Orbs reset must come before hero replacement + invoker:reset_abilities() + unit:set_ability_points(1) + player:replace_hero(player.hero:GetUnitName()) + else + unit:purge() + unit:give_max_health() + unit:give_max_mana() + end +end + +--- Purchase specification. +--- @class invk.combo.ItemPurchase +--- @field item string # Item name +--- @field cost integer # Purchase cost + +--- Refunds a purchase made by a player's hero. +--- @param base_player CDOTAPlayerController # Player that made the purchase +--- @param purchase invk.combo.ItemPurchase # Purchase information +function M.refund_purchase(base_player, purchase) + local player = Player:new(base_player) + + Unit:new(player.hero):give_gold(purchase.cost) +end + +--- If no options are given, levels hero up one level. +--- @class invk.combo.LevelUpOptions +--- @field level? integer # Level up to specified level +--- @field max_level? boolean # Level up to max level (default: `false`) + +--- Levels a player's hero up. +--- @param base_player CDOTAPlayerController # Player +--- @param options? invk.combo.LevelUpOptions +function M.level_up(base_player, options) + local opts = options or {} + local player = Player:new(base_player) + local unit = Unit:new(player.hero) + --- @type integer + local target_level + + if opts.level ~= nil then + target_level = opts.level + elseif opts.max_level then + target_level = LIMITS.MAX_HERO_LEVEL + else + target_level = unit:get_level() + 1 + end + + if target_level == LIMITS.MAX_HERO_LEVEL then + HeroMaxLevel(player.hero) + else + unit:hero_level_up_to(target_level, { play_effects = true }) + end +end + +return M diff --git a/game/scripts/vscripts/invk/combo/sound.lua b/game/scripts/vscripts/invk/combo/sound.lua new file mode 100644 index 0000000..0536a15 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/sound.lua @@ -0,0 +1,70 @@ +local SOUND_EVENTS = require("invk.const.sound_events") +local SoundEvents = require("invk.dota2.sound_events") + +--- Internal combos sound helpers. +--- @class invk.combos.sound +local M = {} + +local MUSIC = { + IDLE = { STATUS = DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION, INTENSITY = 1.0 }, + BATTLE = { STATUS = DOTA_MUSIC_STATUS_BATTLE, INTENSITY = 5.0 }, + VICTORY = { STATUS = DOTA_MUSIC_STATUS_EXPLORATION, INTENSITY = 10.0 }, + DEFEAT = { STATUS = DOTA_MUSIC_STATUS_DEAD, INTENSITY = 10.0 }, +} + +--- @param events string[] # Array of event names from which to get a random sample +--- @return string +local function random_sound_event(events) + local event = assert(events[RandomInt(1, #events)], "RandomInt() returned invalid value") + + return event +end + +--- Emits a random event on entity. +--- @param entity CBaseEntity # Entity +--- @param events string[] # Array of event names from which to get a random sample +function M.emit_random_event_on_entity(entity, events) + SoundEvents.emit_on_entity(random_sound_event(events), entity) +end + +--- Emits a random event on player. +--- @param player CDOTAPlayerController # Player +--- @param events string[] # Array of event names from which to get a random sample +function M.emit_random_event_on_player(player, events) + SoundEvents.emit_on_player(random_sound_event(events), player) +end + +--- Sets up sound for when a dummy target unit is created. +--- @param dummy invk.dota2.DummyTarget +function M.on_dummy_create(dummy) + M.emit_random_event_on_entity( + dummy.entity --[[@as CBaseEntity]], + SOUND_EVENTS.SNDEVTS_DUMMY_CREATE + ) +end + +--- Sets up sound for when a player starts a combo. +--- @param player CDOTAPlayerController +function M.on_combo_start(player) + player:SetMusicStatus(MUSIC.BATTLE.STATUS, MUSIC.BATTLE.INTENSITY) +end + +--- Sets up sound for when a player stops a combo. +--- @param player CDOTAPlayerController +function M.on_combo_stop(player) + player:SetMusicStatus(MUSIC.IDLE.STATUS, MUSIC.IDLE.INTENSITY) +end + +--- Sets up sound for when a player commits an error in a combo. +--- @param player CDOTAPlayerController +function M.on_combo_step_error(player) + player:SetMusicStatus(MUSIC.DEFEAT.STATUS, MUSIC.DEFEAT.INTENSITY) +end + +--- Sets up sound for when a player finishes a combo. +--- @param player CDOTAPlayerController +function M.on_combo_finished(player) + player:SetMusicStatus(MUSIC.VICTORY.STATUS, MUSIC.VICTORY.INTENSITY) +end + +return M diff --git a/game/scripts/vscripts/invk/combo/spec.lua b/game/scripts/vscripts/invk/combo/spec.lua new file mode 100644 index 0000000..b39e362 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/spec.lua @@ -0,0 +1,58 @@ +--- @class invk.combo.spec +local M = {} + +--- Combo specification. +--- @class invk.combo.ComboSpec +--- @field id invk.combo.ComboId # Combo id +--- @field specialty invk.combo.Specialty # Specialty +--- @field stance invk.combo.Stance # Stance +--- @field damage_rating invk.combo.DamageRating # Damage rating +--- @field difficulty_rating invk.combo.DifficultyRating # Difficulty rating +--- @field hero_level integer # Hero level +--- @field orbs [integer, integer, integer] # Array of recommended orb abilities levels (`{quas, wex, exort}`) +--- @field talents integer # Bitmap of recommended talent abilities +--- @field gold integer # Hero starting gold +--- @field items string[] # Array of required items names +--- @field tags string[] # Tags +--- @field sequence invk.combo.ComboStepSpec[] # Array of steps data + +--- ComboStep specification. +--- @class invk.combo.ComboStepSpec +--- @field id integer # Step id +--- @field name string # Step name (ability or item name) +--- @field required? boolean # Is step required or optional? (default: `false`) +--- @field next? integer[] # Next steps ids (`nil` if it's the last step in the sequence) + +--- @enum invk.combo.Specialty +M.Specialty = { + QuasExort = "qe", + QuasWex = "qw", +} + +--- @enum invk.combo.Stance +M.Stance = { + Defensive = "defensive", + Offensive = "offensive", +} + +--- @enum invk.combo.DamageRating +M.DamageRating = { + None = 0, + Light = 1, + Considerable = 2, + Lethal = 3, + Exceptional = 4, + Brutal = 5, +} + +--- @enum invk.combo.DifficultyRating +M.DifficultyRating = { + VeryEasy = 0, + Easy = 1, + Normal = 2, + Hard = 3, + VeryHard = 4, + LiterallyUnplayable = 5, +} + +return M diff --git a/game/scripts/vscripts/invk/combo/wait.lua b/game/scripts/vscripts/invk/combo/wait.lua new file mode 100644 index 0000000..d342c18 --- /dev/null +++ b/game/scripts/vscripts/invk/combo/wait.lua @@ -0,0 +1,73 @@ +local class = require("middleclass") + +local INVOKER = require("invk.const.invoker") +local func = require("invk.lang.function") +local tbl = require("invk.lang.table") + +local AbilityName = INVOKER.AbilityName + +--- @type { [string]: string[] } +local WAIT_ABILITY_SPECIALS = { + [AbilityName.ALACRITY] = { "duration" }, + [AbilityName.CHAOS_METEOR] = { "land_time", "burn_duration" }, + [AbilityName.COLD_SNAP] = { "duration" }, + [AbilityName.DEAFENING_BLAST] = { "disarm_duration" }, + [AbilityName.EMP] = { "delay" }, + [AbilityName.ICE_WALL] = { "duration" }, + [AbilityName.SUN_STRIKE] = { "delay" }, + [AbilityName.TORNADO] = { "lift_duration" }, + item_black_king_bar = { "duration" }, + item_cyclone = { "cyclone_duration" }, + item_sheepstick = { "sheep_duration" }, + item_shivas_guard = { "blast_debuff_duration" }, +} + +--- @class invk.combo.Wait : middleclass.Class +--- @field clock invk.dota2.ClockFn +--- @field queue number[] +--- @field duration number +local M = class("invk.combo.Wait") + +--- @param clock invk.dota2.ClockFn +function M:initialize(clock) + self.clock = clock + self.queue = {} + self.duration = 0 +end + +--- @param ability invk.dota2.Ability +--- @return number +function M.ability_wait(ability) + local wait = ability:duration() or 0 + local special_keys = WAIT_ABILITY_SPECIALS[ability.name] + + if special_keys == nil then + return wait + end + + local special_waits = tbl.map(special_keys, function(special_key) + return ability:get_special_value_for(special_key) or 0 + end) + + return tbl.reduce(special_waits, func.sum(), wait) +end + +--- @param ability invk.dota2.Ability +function M:enqueue(ability) + self.queue[#self.queue + 1] = self.clock() + M.ability_wait(ability) +end + +--- @param base_time number +function M:finish(base_time) + self.duration = self:max_time() - base_time + self.queue = {} +end + +--- @private +--- @return number +function M:max_time() + --- @diagnostic disable-next-line: param-type-not-match + return math.max(table.unpack(self.queue)) +end + +return M diff --git a/game/scripts/vscripts/invokation/const/ability_list.lua b/game/scripts/vscripts/invk/const/ability_list.lua similarity index 67% rename from game/scripts/vscripts/invokation/const/ability_list.lua rename to game/scripts/vscripts/invk/const/ability_list.lua index fe00f4b..e68d090 100644 --- a/game/scripts/vscripts/invokation/const/ability_list.lua +++ b/game/scripts/vscripts/invk/const/ability_list.lua @@ -1,5 +1,5 @@ --- Table of enabled/disabled abilities. --- @module invokation.const.ability_list +--- @class invk.const.ability_list local M = { item_tome_of_knowledge = false, item_courier = false, @@ -13,4 +13,10 @@ local M = { item_moon_shard = false, } +--- @param ability invk.dota2.Ability +--- @return boolean +function M:is_ignored(ability) + return self[ability.name] == false +end + return M diff --git a/game/scripts/vscripts/invk/const/combos.lua b/game/scripts/vscripts/invk/const/combos.lua new file mode 100644 index 0000000..192aede --- /dev/null +++ b/game/scripts/vscripts/invk/const/combos.lua @@ -0,0 +1,656 @@ +local S = require("invk.combo.spec") +local talents = require("invk.dota2.talents") + +local T = talents.Talents + +--- Combo specifications. +--- @type invk.combo.ComboSpec[] +local M = {} + +M[#M + 1] = { + id = 1, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = S.DamageRating.None, + difficulty_rating = S.DifficultyRating.Easy, + hero_level = 2, + orbs = { 1, 1, 0 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + }, + tags = { "laning-phase" }, + sequence = { + { id = 1, name = "invoker_cold_snap", required = true, next = { 2 } }, + { id = 2, name = "invoker_tornado", required = true }, + }, +} + +M[#M + 1] = { + id = 2, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = S.DamageRating.None, + difficulty_rating = S.DifficultyRating.Easy, + hero_level = 2, + orbs = { 1, 1, 0 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + }, + tags = { "laning-phase" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_quas", required = true, next = { 3 } }, + { id = 3, name = "invoker_quas", required = true, next = { 4 } }, + { id = 4, name = "invoker_wex", required = true, next = { 5 } }, + { id = 5, name = "invoker_invoke", required = true, next = { 6, 9 } }, + { id = 6, name = "invoker_wex", required = false, next = { 7 } }, + { id = 7, name = "invoker_wex", required = false, next = { 8 } }, + { id = 8, name = "invoker_wex", required = false, next = { 9 } }, + { id = 9, name = "invoker_ghost_walk", required = true }, + }, +} + +M[#M + 1] = { + id = 3, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Light, + difficulty_rating = S.DifficultyRating.Easy, + hero_level = 2, + orbs = { 1, 1, 0 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + }, + tags = { "laning-phase" }, + sequence = { + { id = 1, name = "invoker_emp", required = true, next = { 2 } }, + { id = 2, name = "invoker_tornado", required = true }, + }, +} + +M[#M + 1] = { + id = 4, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Light, + difficulty_rating = S.DifficultyRating.Easy, + hero_level = 2, + orbs = { 1, 0, 1 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + }, + tags = { "laning-phase" }, + sequence = { + { id = 1, name = "invoker_forge_spirit", required = true, next = { 2 } }, + { id = 2, name = "invoker_cold_snap", required = true }, + }, +} + +M[#M + 1] = { + id = 5, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Light, + difficulty_rating = S.DifficultyRating.Easy, + hero_level = 3, + orbs = { 1, 1, 1 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + }, + tags = { "laning-phase" }, + sequence = { + { id = 1, name = "invoker_forge_spirit", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true }, + }, +} + +M[#M + 1] = { + id = 6, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true }, + }, +} + +M[#M + 1] = { + id = 7, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Lethal, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_sun_strike", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true }, + }, +} + +M[#M + 1] = { + id = 8, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_deafening_blast", required = true, next = { 2 } }, + { id = 2, name = "invoker_cold_snap", required = true, next = { 3 } }, + { id = 3, name = "invoker_chaos_meteor", required = true }, + }, +} + +M[#M + 1] = { + id = 9, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_cold_snap", required = true }, + }, +} + +M[#M + 1] = { + id = 10, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true }, + }, +} + +M[#M + 1] = { + id = 11, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Lethal, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_sun_strike", required = true }, + }, +} + +M[#M + 1] = { + id = 12, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 6, + orbs = { 2, 2, 2 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_emp", required = true }, + }, +} + +M[#M + 1] = { + id = 13, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 3, 2, 1 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_cold_snap", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true }, + }, +} + +M[#M + 1] = { + id = 14, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 3, 2, 1 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true, next = { 3 } }, + { id = 3, name = "invoker_cold_snap", required = true }, + }, +} + +M[#M + 1] = { + id = 15, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 3, 2, 1 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true }, + }, +} + +M[#M + 1] = { + id = 16, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 2, 1, 3 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true, next = { 3 } }, + { id = 3, name = "invoker_sun_strike", required = true }, + }, +} + +M[#M + 1] = { + id = 17, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Normal, + hero_level = 6, + orbs = { 2, 2, 2 }, + talents = T.NONE, + gold = 0, + items = { + "item_null_talisman", + "item_null_talisman", + }, + tags = { "solo-pick" }, + sequence = { + { id = 1, name = "invoker_ice_wall", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true, next = { 3 } }, + { id = 3, name = "invoker_emp", required = true }, + }, +} + +M[#M + 1] = { + id = 18, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 12, + orbs = { 5, 5, 2 }, + talents = T.NONE, + gold = 0, + items = { + "item_boots", + "item_null_talisman", + "item_null_talisman", + "item_ultimate_scepter", + }, + tags = { "teamfight" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_ice_wall", required = true, next = { 3 } }, + { id = 3, name = "invoker_cold_snap", required = true, next = { 4 } }, + { id = 4, name = "invoker_emp", required = true }, + }, +} + +M[#M + 1] = { + id = 19, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 12, + orbs = { 4, 3, 4 }, + talents = T.L10_LEFT, + gold = 0, + items = { + "item_boots", + "item_null_talisman", + "item_null_talisman", + "item_ultimate_scepter", + }, + tags = { "teamfight" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true, next = { 4 } }, + { id = 4, name = "invoker_cold_snap", required = true, next = { 5 } }, + { id = 5, name = "invoker_ice_wall", required = true }, + }, +} + +M[#M + 1] = { + id = 20, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Lethal, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 12, + orbs = { 4, 3, 4 }, + talents = T.L10_LEFT, + gold = 0, + items = { + "item_boots", + "item_null_talisman", + "item_null_talisman", + "item_ultimate_scepter", + "item_cyclone", + }, + tags = { "teamfight" }, + sequence = { + { id = 1, name = "item_cyclone", required = true, next = { 2 } }, + { id = 2, name = "invoker_sun_strike", required = true, next = { 3 } }, + { id = 3, name = "invoker_emp", required = true, next = { 4 } }, + { id = 4, name = "invoker_chaos_meteor", required = true, next = { 5 } }, + { id = 5, name = "invoker_deafening_blast", required = true }, + }, +} + +M[#M + 1] = { + id = 21, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Considerable, + difficulty_rating = S.DifficultyRating.Hard, + hero_level = 12, + orbs = { 4, 3, 5 }, + talents = T.NONE, + gold = 0, + items = { + "item_boots", + "item_null_talisman", + "item_null_talisman", + "item_ultimate_scepter", + }, + tags = { "teamfight" }, + sequence = { + { id = 1, name = "invoker_forge_spirit", required = true, next = { 2 } }, + { id = 2, name = "invoker_alacrity", required = true, next = { 3 } }, + { id = 3, name = "invoker_ice_wall", required = true, next = { 4 } }, + { id = 4, name = "invoker_cold_snap", required = true, next = { 5 } }, + { id = 5, name = "invoker_sun_strike", required = true }, + }, +} + +M[#M + 1] = { + id = 22, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Exceptional, + difficulty_rating = S.DifficultyRating.VeryHard, + hero_level = 20, + orbs = { 5, 7, 7 }, + talents = T.L10_LEFT, + gold = 0, + items = { + "item_travel_boots", + "item_null_talisman", + "item_null_talisman", + "item_null_talisman", + "item_refresher", + "item_ultimate_scepter", + }, + tags = { "late-game" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_chaos_meteor", required = true, next = { 3 } }, + { id = 3, name = "invoker_deafening_blast", required = true, next = { 4 } }, + { id = 4, name = "item_refresher", required = true, next = { 5 } }, + { id = 5, name = "invoker_chaos_meteor", required = true, next = { 6 } }, + { id = 6, name = "invoker_deafening_blast", required = true, next = { 7 } }, + { id = 7, name = "invoker_sun_strike", required = true }, + }, +} + +M[#M + 1] = { + id = 23, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Exceptional, + difficulty_rating = S.DifficultyRating.VeryHard, + hero_level = 20, + orbs = { 5, 7, 7 }, + talents = T.L10_LEFT, + gold = 0, + items = { + "item_travel_boots", + "item_null_talisman", + "item_null_talisman", + "item_ultimate_scepter", + "item_octarine_core", + "item_refresher", + }, + tags = { "late-game" }, + sequence = { + { id = 1, name = "invoker_tornado", required = true, next = { 2 } }, + { id = 2, name = "invoker_emp", required = true, next = { 3 } }, + { id = 3, name = "invoker_sun_strike", required = true, next = { 4 } }, + { id = 4, name = "invoker_chaos_meteor", required = true, next = { 5 } }, + { id = 5, name = "invoker_deafening_blast", required = true, next = { 6 } }, + { id = 6, name = "item_refresher", required = true, next = { 7 } }, + { id = 7, name = "invoker_chaos_meteor", required = true, next = { 8 } }, + { id = 8, name = "invoker_deafening_blast", required = true, next = { 9 } }, + { id = 9, name = "invoker_sun_strike", required = true }, + }, +} + +M[#M + 1] = { + id = 24, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Exceptional, + difficulty_rating = S.DifficultyRating.VeryHard, + hero_level = 20, + orbs = { 5, 7, 7 }, + talents = T.L10_LEFT, + gold = 0, + items = { + "item_travel_boots", + "item_null_talisman", + "item_refresher", + "item_ultimate_scepter", + "item_sheepstick", + "item_black_king_bar", + }, + tags = { "late-game" }, + sequence = { + { id = 1, name = "item_sheepstick", required = true, next = { 2 } }, + { id = 2, name = "invoker_tornado", required = true, next = { 3 } }, + { id = 3, name = "item_black_king_bar", required = true, next = { 4 } }, + { id = 4, name = "invoker_chaos_meteor", required = true, next = { 5 } }, + { id = 5, name = "invoker_deafening_blast", required = true, next = { 6 } }, + { id = 6, name = "item_refresher", required = true, next = { 7 } }, + { id = 7, name = "invoker_chaos_meteor", required = true, next = { 8 } }, + { id = 8, name = "invoker_deafening_blast", required = true, next = { 9 } }, + { id = 9, name = "invoker_sun_strike", required = true, next = { 10 } }, + { id = 10, name = "item_black_king_bar", required = true, next = { 11 } }, + { id = 11, name = "item_sheepstick", required = true }, + }, +} + +M[#M + 1] = { + id = 25, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Exceptional, + difficulty_rating = S.DifficultyRating.VeryHard, + hero_level = 20, + orbs = { 5, 7, 7 }, + talents = T.L10_LEFT, + gold = 0, + items = { + "item_travel_boots", + "item_black_king_bar", + "item_blink", + "item_sheepstick", + "item_refresher", + "item_ultimate_scepter", + }, + tags = { "late-game" }, + sequence = { + { id = 1, name = "item_black_king_bar", required = true, next = { 2 } }, + { id = 2, name = "item_blink", required = true, next = { 3 } }, + { id = 3, name = "item_sheepstick", required = true, next = { 4 } }, + { id = 4, name = "invoker_tornado", required = true, next = { 5 } }, + { id = 5, name = "invoker_chaos_meteor", required = true, next = { 6 } }, + { id = 6, name = "invoker_deafening_blast", required = true, next = { 7 } }, + { id = 7, name = "item_refresher", required = true, next = { 8 } }, + { id = 8, name = "item_black_king_bar", required = true, next = { 9 } }, + { id = 9, name = "invoker_chaos_meteor", required = true, next = { 10 } }, + { id = 10, name = "invoker_deafening_blast", required = true, next = { 11 } }, + { id = 11, name = "invoker_sun_strike", required = true, next = { 12 } }, + { id = 12, name = "item_sheepstick", required = true }, + }, +} + +M[#M + 1] = { + id = 26, + specialty = S.Specialty.QuasExort, + stance = S.Stance.Offensive, + damage_rating = S.DamageRating.Brutal, + difficulty_rating = S.DifficultyRating.LiterallyUnplayable, + hero_level = 25, + orbs = { 7, 7, 7 }, + talents = talents.select(T.L10_LEFT, T.L15_RIGHT, T.L20_RIGHT, T.L25_RIGHT), + gold = 0, + items = { + "item_travel_boots", + "item_black_king_bar", + "item_shivas_guard", + "item_refresher", + "item_octarine_core", + "item_ultimate_scepter", + }, + tags = { "late-game" }, + sequence = { + { id = 1, name = "invoker_alacrity", required = true, next = { 2 } }, + { id = 2, name = "invoker_forge_spirit", required = true, next = { 3 } }, + { id = 3, name = "item_black_king_bar", required = true, next = { 4 } }, + { id = 4, name = "invoker_tornado", required = true, next = { 5 } }, + { id = 5, name = "invoker_emp", required = true, next = { 6 } }, + { id = 6, name = "invoker_sun_strike", required = true, next = { 7 } }, + { id = 7, name = "invoker_chaos_meteor", required = true, next = { 8 } }, + { id = 8, name = "item_shivas_guard", required = true, next = { 9 } }, + { id = 9, name = "invoker_deafening_blast", required = true, next = { 10 } }, + { id = 10, name = "item_refresher", required = true, next = { 11 } }, + { id = 11, name = "item_shivas_guard", required = true, next = { 12 } }, + { id = 12, name = "invoker_chaos_meteor", required = true, next = { 13 } }, + { id = 13, name = "invoker_deafening_blast", required = true, next = { 14 } }, + { id = 14, name = "invoker_emp", required = true, next = { 15 } }, + { id = 15, name = "invoker_sun_strike", required = true, next = { 16 } }, + { id = 16, name = "invoker_ice_wall", required = true }, + }, +} + +return M diff --git a/game/scripts/vscripts/invokation/const/commands.lua b/game/scripts/vscripts/invk/const/commands.lua similarity index 65% rename from game/scripts/vscripts/invokation/const/commands.lua rename to game/scripts/vscripts/invk/const/commands.lua index c4913c6..8091e6e 100644 --- a/game/scripts/vscripts/invokation/const/commands.lua +++ b/game/scripts/vscripts/invk/const/commands.lua @@ -1,117 +1,117 @@ --- Command definitions. --- @module invokation.const.commands +--- @class invk.const.commands : invk.game_mode.ConsoleCommmand[] local M = {} --- Command definition. --- @table CommandDefinition --- @tfield string name Command name --- @tfield string method `GameMode` method name --- @tfield string help Command help --- @tfield int flags Command flags --- @tfield bool dev Only registered in development environment +--- @class invk.game_mode.ConsoleCommmand +--- @field name string # Command name +--- @field method string # `GameMode` method name +--- @field help string # Command help +--- @field flags? integer # Command flags +--- @field dev boolean # Only registered in development environment -table.insert(M, { - name = "inv_debug", +M[#M + 1] = { + name = "invk_debug", method = "CommandSetDebug", help = "Set debugging (empty - print debug status, 0 - disabled, 1 - enabled)", flags = FCVAR_CHEAT, dev = false, -}) +} -table.insert(M, { - name = "inv_debug_misc", +M[#M + 1] = { + name = "invk_debug_misc", method = "CommandDebugMisc", help = "Run miscellaneous debug code (use script_reload to reload)", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_dump_lua_version", +M[#M + 1] = { + name = "invk_dump_lua_version", method = "CommandDumpLuaVersion", help = "Dump Lua version", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_dump_global", +M[#M + 1] = { + name = "invk_dump_global", method = "CommandDumpGlobal", help = "Dump global value ()", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_find_global", +M[#M + 1] = { + name = "invk_find_global", method = "CommandFindGlobal", help = "Find global name ()", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_item_query", +M[#M + 1] = { + name = "invk_item_query", method = "CommandItemQuery", help = "Query items ()", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_dump_abilities", +M[#M + 1] = { + name = "invk_dump_abilities", method = "CommandDumpAbilities", help = "Dump current hero abilities ([simplified:int])", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_invoke", +M[#M + 1] = { + name = "invk_invoke", method = "CommandInvokeAbility", help = "Invoke an ability ()", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_dump_combo_graph", +M[#M + 1] = { + name = "invk_dump_combo_graph", method = "CommandDumpComboGraph", help = "Dumps a combo's finite state machine in DOT format", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_music_status", +M[#M + 1] = { + name = "invk_music_status", method = "CommandChangeMusicStatus", help = "Change music status ( )", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_dump_specials", +M[#M + 1] = { + name = "invk_dump_specials", method = "CommandDumpSpecials", help = "Dump Invoker ability specials ([onlyScaling:int])", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_debug_specials", +M[#M + 1] = { + name = "invk_debug_specials", method = "CommandDebugSpecials", help = "Run debug operations on ability specials ( )", flags = FCVAR_CHEAT, dev = true, -}) +} -table.insert(M, { - name = "inv_reinsert_ability", +M[#M + 1] = { + name = "invk_reinsert_ability", method = "CommandReinsertAbility", help = "Reinsert Invoker ability ()", flags = FCVAR_CHEAT, dev = true, -}) +} return M diff --git a/game/scripts/vscripts/invokation/const/custom_events.lua b/game/scripts/vscripts/invk/const/custom_events.lua similarity index 54% rename from game/scripts/vscripts/invokation/const/custom_events.lua rename to game/scripts/vscripts/invk/const/custom_events.lua index 991c8fa..2905576 100644 --- a/game/scripts/vscripts/invokation/const/custom_events.lua +++ b/game/scripts/vscripts/invk/const/custom_events.lua @@ -1,159 +1,144 @@ --- Custom event names. --- @module invokation.const.custom_events +--- @class invk.const.custom_events local M = {} ---- Player --- @section player - --- Payload for event `EVENT_PLAYER_HERO_IN_GAME` --- @table PlayerHeroInGame +--- @class invk.custom_events.PlayerHeroInGame --- Player picked a hero M.EVENT_PLAYER_HERO_IN_GAME = "invk_player_hero_in_game" --- Payload for event `EVENT_PLAYER_QUIT_REQUEST` --- @table PlayerQuitRequest +--- @class invk.custom_events.PlayerQuitRequest --- Player requested to leave M.EVENT_PLAYER_QUIT_REQUEST = "invk_player_quit_request" ---- Combos --- @section combos - --- Payload for event `EVENT_COMBOS_RELOAD` --- @table CombosReloadPayload +--- @class invk.custom_events.CombosReloadPayload --- Reload combos M.EVENT_COMBOS_RELOAD = "invk_combos_reload" --- Payload for event `EVENT_COMBO_START` --- @table ComboStartPayload --- @tfield int id Combo id +--- @class invk.custom_events.ComboStartPayload +--- @field id invk.combo.ComboId # Combo id --- Start combo M.EVENT_COMBO_START = "invk_combo_start" --- Payload for event `EVENT_COMBO_STARTED` --- @table ComboStartedPayload --- @tfield int id Combo id --- @tfield[opt] {int,...} next Next steps ids +--- @class invk.custom_events.ComboStartedPayload +--- @field id invk.combo.ComboId # Combo id +--- @field next? integer[] # Next steps ids --- Combo started M.EVENT_COMBO_STARTED = "invk_combo_started" --- Payload for event `EVENT_COMBO_STOP` --- @table ComboStopPayload +--- @class invk.custom_events.ComboStopPayload --- Stop combo M.EVENT_COMBO_STOP = "invk_combo_stop" --- Payload for event `EVENT_COMBO_STOPPED` --- @table ComboStoppedPayload --- @tfield int id Combo id +--- @class invk.custom_events.ComboStoppedPayload +--- @field id invk.combo.ComboId # Combo id --- Combo stopped M.EVENT_COMBO_STOPPED = "invk_combo_stopped" --- Payload for event `EVENT_COMBO_IN_PROGRESS` --- @table ComboInProgressPayload --- @tfield int id Combo id +--- @class invk.custom_events.ComboInProgressPayload +--- @field id invk.combo.ComboId # Combo id --- Combo in progress M.EVENT_COMBO_IN_PROGRESS = "invk_combo_in_progress" --- Payload for event `EVENT_COMBO_PROGRESS` --- @table ComboProgressPayload --- @tfield int id Combo id --- @tfield {[string]=number} metrics Combo metrics --- @tfield[opt] {int,...} next Next steps ids +--- @class invk.custom_events.ComboProgressPayload +--- @field id invk.combo.ComboId # Combo id +--- @field metrics invk.combo.Metrics # Combo metrics +--- @field next? integer[] # Next steps ids --- Combo progress M.EVENT_COMBO_PROGRESS = "invk_combo_progress" --- Payload for event `EVENT_COMBO_STEP_ERROR` --- @table ComboStepErrorPayload --- @tfield int id Combo id --- @tfield {int,...} expected Expected steps ids --- @tfield string ability Ability name +--- @class invk.custom_events.ComboStepErrorPayload +--- @field id invk.combo.ComboId # Combo id +--- @field expected integer[] # Expected steps ids +--- @field ability string # Ability name --- Combo step error M.EVENT_COMBO_STEP_ERROR = "invk_combo_step_error" --- Payload for event `EVENT_COMBO_PRE_FINISH` --- @table ComboPreFinishPayload --- @tfield int id Combo id --- @tfield {[string]=number} metrics Combo metrics --- @tfield int wait Time to wait before combo finishes +--- @class invk.custom_events.ComboPreFinishPayload +--- @field id invk.combo.ComboId # Combo id +--- @field metrics invk.combo.Metrics # Combo metrics +--- @field wait number # Time to wait before combo finishes --- Combo pre finish M.EVENT_COMBO_PRE_FINISH = "invk_combo_pre_finish" --- Payload for event `EVENT_COMBO_FINISHED` --- @table ComboFinishedPayload --- @tfield int id Combo id --- @tfield {[string]=number} metrics Combo metrics +--- @class invk.custom_events.ComboFinishedPayload +--- @field id invk.combo.ComboId # Combo id +--- @field metrics invk.combo.Metrics # Combo metrics --- Combo finished M.EVENT_COMBO_FINISHED = "invk_combo_finished" --- Payload for event `EVENT_COMBO_RESTART` --- @table ComboRestartPayload --- @tfield[opt=0] int hardReset Perform hard reset (`1`: yes, `0`: no) +--- @class invk.custom_events.ComboRestartPayload +--- @field hardReset? integer # Perform hard reset (`1`: yes, `0`: no) (default: `0`) --- Restart combo M.EVENT_COMBO_RESTART = "invk_combo_restart" ---- Freestyle --- @section freestyle - --- Payload for event `EVENT_FREESTYLE_HERO_LEVEL_UP` --- @table FreestyleHeroLevelUpPayload --- @tfield[opt] int level Level up to specified level --- @tfield[opt=0] int maxLevel Level up to max level (`1`: yes, `0`: no) +--- @class invk.custom_events.FreestyleHeroLevelUpPayload +--- @field level? integer # Level up to specified level +--- @field maxLevel? integer # Level up to max level (`1`: yes, `0`: no) (default: `0`) --- Freestyle hero level up M.EVENT_FREESTYLE_HERO_LEVEL_UP = "invk_freestyle_hero_level_up" ---- Combat Log --- @section combat_log - --- Payload for event `EVENT_COMBAT_LOG_CAPTURE_START` --- @table CombatLogCaptureStartPayload +--- @class invk.custom_events.CombatLogCaptureStartPayload --- Start capturing combat log M.EVENT_COMBAT_LOG_CAPTURE_START = "invk_combat_log_capture_start" --- Payload for event `EVENT_COMBAT_LOG_CAPTURE_STOP` --- @table CombatLogCaptureStopPayload +--- @class invk.custom_events.CombatLogCaptureStopPayload --- Stop capturing combat log M.EVENT_COMBAT_LOG_CAPTURE_STOP = "invk_combat_log_capture_stop" --- Payload for event `EVENT_COMBAT_LOG_ABILITY_USED` --- @table CombatLogAbilityUsedPayload +--- @class invk.custom_events.CombatLogAbilityUsedPayload --- Combat log ability used M.EVENT_COMBAT_LOG_ABILITY_USED = "invk_combat_log_ability_used" --- Payload for event `EVENT_COMBAT_LOG_CLEAR` --- @table CombatLogClearPayload +--- @class invk.custom_events.CombatLogClearPayload --- Clear combat log M.EVENT_COMBAT_LOG_CLEAR = "invk_combat_log_clear" ---- Item Picker --- @section item_picker - --- Payload for event `EVENT_ITEM_PICKER_QUERY` --- @table ItemPickerQueryPayload --- @tfield string query Query +--- @class invk.custom_events.ItemPickerQueryPayload +--- @field query string # Query --- Item picker query M.EVENT_ITEM_PICKER_QUERY_REQUEST = "invk_item_picker_query_request" --- Payload for event `EVENT_ITEM_PICKER_QUERY_RESPONSE` --- @table ItemPickerQueryResponsePayload --- @tfield {[string]=table,...} items Items found +--- @class invk.custom_events.ItemPickerQueryResponsePayload +--- @field items table[] # Items found --- Item picker query response M.EVENT_ITEM_PICKER_QUERY_RESPONSE = "invk_item_picker_query_response" diff --git a/game/scripts/vscripts/invokation/const/enums.lua b/game/scripts/vscripts/invk/const/enums.lua similarity index 61% rename from game/scripts/vscripts/invokation/const/enums.lua rename to game/scripts/vscripts/invk/const/enums.lua index 3c79467..b007f07 100644 --- a/game/scripts/vscripts/invokation/const/enums.lua +++ b/game/scripts/vscripts/invk/const/enums.lua @@ -1,5 +1,5 @@ --- Missing or renamed enums. --- @module invokation.const.enums +--- @class invk.const.enums local M = {} --- Missing (GameActivity_t) ACT_INVALID @@ -17,124 +17,91 @@ M.DOTA_ABILITY_TYPE_ULTIMATE = ABILITY_TYPE_ULTIMATE --- Missing (DOTA_ABILITY_BEHAVIOR) DOTA_ABILITY_BEHAVIOR_NOASSIST M.DOTA_ABILITY_BEHAVIOR_NOASSIST = 0 ---- No flags. --- (0) +--- No flags. (`0`) M.FCVAR_NONE = 0 ---- Don't add to linked list, etc. --- (1) +--- Don't add to linked list, etc. (`1`) M.FCVAR_UNREGISTERED = bit.lshift(1, 0) ---- Hidden in released products. --- (2) +--- Hidden in released products. (`2`) M.FCVAR_DEVELOPMENTONLY = bit.lshift(1, 1) ---- Defined by the game DLL. --- (4) +--- Defined by the game DLL. (`4`) M.FCVAR_GAMEDLL = bit.lshift(1, 2) ---- Defined by the client DLL. --- (8) +--- Defined by the client DLL. (`8`) M.FCVAR_CLIENTDLL = bit.lshift(1, 3) --- Hidden. --- Doesn't appear in find or autocomplete. Like DEVELOPMENTONLY, but can't be compiled out. --- (16) +--- Doesn't appear in find or autocomplete. Like DEVELOPMENTONLY, but can't be compiled out. (`16`) M.FCVAR_HIDDEN = bit.lshift(1, 4) ---- Defined by the material system (EP1-only). --- (16) +--- Defined by the material system (EP1-only). (`16`) M.FCVAR_MATERIAL_SYSTEM = bit.lshift(1, 4) ---- Server cvar, but we don't send the data since it's a password, etc. --- (32) +--- Server cvar, but we don't send the data since it's a password, etc. (`32`) M.FCVAR_PROTECTED = bit.lshift(1, 5) ---- Cvar cannot be changed by clients connected to a multiplayer server. --- (64) +--- Cvar cannot be changed by clients connected to a multiplayer server. (`64`) M.FCVAR_SPONLY = bit.lshift(1, 6) ---- Cvar is saved (config.cfg, vars.rc, etc). --- (128) +--- Cvar is saved (config.cfg, vars.rc, etc). (`128`) M.FCVAR_ARCHIVE = bit.lshift(1, 7) ---- Notifies players when changed. --- (256) +--- Notifies players when changed. (`256`) M.FCVAR_NOTIFY = bit.lshift(1, 8) ---- Changes the client's info string. --- (512) +--- Changes the client's info string. (`512`) M.FCVAR_USERINFO = bit.lshift(1, 9) ---- This var's string cannot contain unprintable characters. --- (e.g., used for player name, etc.) --- (1024) +--- This var's string cannot contain unprintable characters. (`1024`) +--- (e.g., used for player name, etc.) M.FCVAR_PRINTABLEONLY = bit.lshift(1, 10) ---- If this is a server, don't log changes to the log file / console if we are creating a log. --- (2048) +--- If this is a server, don't log changes to the log file / console if we are creating a log. (`2048`) M.FCVAR_UNLOGGED = bit.lshift(1, 11) ---- Never try to print. --- (4096) +--- Never try to print. (`4096`) M.FCVAR_NEVER_AS_STRING = bit.lshift(1, 12) ---- Server setting enforced on clients. --- (8192) +--- Server setting enforced on clients. (`8192`) M.FCVAR_REPLICATED = bit.lshift(1, 13) ---- Only useable in singleplayer / debug / multiplayer & `sv_cheats 1`. --- (16384) +--- Only useable in singleplayer / debug / multiplayer & `sv_cheats 1`. (`16384`) M.FCVAR_CHEAT = bit.lshift(1, 14) ---- Causes varnameN where N in interval (2, max) splitscreen slots for mod to be autogenerated. --- (32768) +--- Causes varnameN where N in interval (2, max) splitscreen slots for mod to be autogenerated. (`32768`) M.FCVAR_SS = bit.lshift(1, 15) --- (32768) +--- (`32768`) M.FCVAR_STUDIORENDER = bit.lshift(1, 15) ---- Record the cvar when starting a demo file. --- (65536) +--- Record the cvar when starting a demo file. (`65536`) M.FCVAR_DEMO = bit.lshift(1, 16) ---- Don't record the command in demo files. --- (131072) +--- Don't record the command in demo files. (`131072`) M.FCVAR_DONTRECORD = bit.lshift(1, 17) ---- This is one of the "added" @{FCVAR_SS} variables for the splitscreen players. --- (262144) +--- This is one of the "added" @{FCVAR_SS} variables for the splitscreen players. (`262144`) M.FCVAR_SS_ADDED = bit.lshift(1, 18) --- (262144) +--- (`262144`) M.FCVAR_PLUGIN = bit.lshift(1, 18) ---- Only available in released products. --- (524288) +--- Only available in released products. (`524288`) M.FCVAR_RELEASE = bit.lshift(1, 19) --- (524288) +--- (`524288`) M.FCVAR_DATACACHE = bit.lshift(1, 19) ---- If the cvar changes, it forces a material reload. --- (1048576) +--- If the cvar changes, it forces a material reload. (`1048576`) M.FCVAR_RELOAD_MATERIALS = bit.lshift(1, 20) --- (1048576) +--- (`1048576`) M.FCVAR_TOOLSYSTEM = bit.lshift(1, 20) ---- If the cvar changes, if forces a texture reload. --- (2097152) +--- If the cvar changes, if forces a texture reload. (`2097152`) M.FCVAR_RELOAD_TEXTURES = bit.lshift(1, 21) --- (2097152) +--- (`2097152`) M.FCVAR_FILESYSTEM = bit.lshift(1, 21) ---- Cvar cannot be changed by a client that is connected to a server. --- (4194304) +--- Cvar cannot be changed by a client that is connected to a server. (`4194304`) M.FCVAR_NOT_CONNECTED = bit.lshift(1, 22) ---- Cvar is read from the material system thread. --- (8388608) +--- Cvar is read from the material system thread. (`8388608`) M.FCVAR_MATERIAL_SYSTEM_THREAD = bit.lshift(1, 23) --- (8388608) +--- (`8388608`) M.FCVAR_SOUNDSYSTEM = bit.lshift(1, 23) ---- Cvar written to config.cfg on the Xbox. --- (16777216) +--- Cvar written to config.cfg on the Xbox. (`16777216`) M.FCVAR_ARCHIVE_XBOX = bit.lshift(1, 24) ---- Cvar written to config.cfg on the Xbox. --- (16777216) +--- Cvar written to config.cfg on the Xbox. (`16777216`) M.FCVAR_ARCHIVE_GAMECONSOLE = bit.lshift(1, 24) ---- Used as a debugging tool necessary to check material system thread cvars. --- (33554432) +--- Used as a debugging tool necessary to check material system thread cvars. (`33554432`) M.FCVAR_ACCESSIBLE_FROM_THREADS = bit.lshift(1, 25) --- (33554432) +--- (`33554432`) M.FCVAR_INPUTSYSTEM = bit.lshift(1, 25) --- (67108864) +--- (`67108864`) M.FCVAR_NETWORKSYSTEM = bit.lshift(1, 26) --- (134217728) +--- (`134217728`) M.FCVAR_VPHYSICS = bit.lshift(1, 27) ---- Server is allowed to execute the command on clients. --- (268435456) +--- Server is allowed to execute the command on clients. (`268435456`) M.FCVAR_SERVER_CAN_EXECUTE = bit.lshift(1, 28) ---- Server is not allowed to query the cvar's value --- (536870912) +--- Server is not allowed to query the cvar's value (`536870912`) M.FCVAR_SERVER_CANNOT_QUERY = bit.lshift(1, 29) ---- Focus vconsole on change? --- (1073741824) +--- Focus vconsole on change? (`1073741824`) M.FCVAR_VCONSOLE_SET_FOCUS = bit.lshift(1, 30) ---- `clientcmd` is allowed to execute this command. --- (1073741824) +--- `clientcmd` is allowed to execute this command. (`1073741824`) M.FCVAR_CLIENTCMD_CAN_EXECUTE = bit.lshift(1, 30) return M diff --git a/game/scripts/vscripts/invk/const/inventory.lua b/game/scripts/vscripts/invk/const/inventory.lua new file mode 100644 index 0000000..24965ad --- /dev/null +++ b/game/scripts/vscripts/invk/const/inventory.lua @@ -0,0 +1,63 @@ +local tbl = require("invk.lang.table") + +--- Inventory constants. +--- @class invk.const.inventory +local M = {} + +--- @enum invk.dota2.inventory.Section +M.Section = { + INVENTORY = "inventory", + STASH = "stash", + NEUTRAL = "neutral", +} + +--- Array of inventory slots indices. +--- @type DOTAScriptInventorySlot_t[] +M.INVENTORY_SLOTS = { + DOTA_ITEM_SLOT_1, + DOTA_ITEM_SLOT_2, + DOTA_ITEM_SLOT_3, + DOTA_ITEM_SLOT_4, + DOTA_ITEM_SLOT_5, + DOTA_ITEM_SLOT_6, + DOTA_ITEM_SLOT_7, + DOTA_ITEM_SLOT_8, + DOTA_ITEM_SLOT_9, +} + +--- Array of stash slots indices. +--- @type DOTAScriptInventorySlot_t[] +M.STASH_SLOTS = { + DOTA_STASH_SLOT_1, + DOTA_STASH_SLOT_2, + DOTA_STASH_SLOT_3, + DOTA_STASH_SLOT_4, + DOTA_STASH_SLOT_5, + DOTA_STASH_SLOT_6, +} + +--- Array of neutral slots indices. +--- @type DOTAScriptInventorySlot_t[] +M.NEUTRAL_SLOTS = { + DOTA_ITEM_NEUTRAL_ACTIVE_SLOT, + DOTA_ITEM_NEUTRAL_PASSIVE_SLOT, +} + +--- Array of all non-neutral slots indices (union of [INVENTORY_SLOTS] and [STASH_SLOTS]). +--- @type DOTAScriptInventorySlot_t[] +M.NON_NEUTRAL_SLOTS = tbl.append(M.INVENTORY_SLOTS, M.STASH_SLOTS) + +--- Array of all slots indices (union of [INVENTORY_SLOTS], [STASH_SLOTS] and [NEUTRAL_SLOTS]). +--- @type DOTAScriptInventorySlot_t[] +M.SLOTS = tbl.append(M.INVENTORY_SLOTS, M.STASH_SLOTS, M.NEUTRAL_SLOTS) + +M.ALL_SECTIONS = { M.Section.INVENTORY, M.Section.STASH, M.Section.NEUTRAL } + +--- @type { [invk.dota2.inventory.Section]: DOTAScriptInventorySlot_t[] } +M.SECTION_SLOTS = { + [M.Section.INVENTORY] = M.INVENTORY_SLOTS, + [M.Section.STASH] = M.STASH_SLOTS, + [M.Section.NEUTRAL] = M.NEUTRAL_SLOTS, +} + +return M diff --git a/game/scripts/vscripts/invk/const/invoker.lua b/game/scripts/vscripts/invk/const/invoker.lua new file mode 100644 index 0000000..3b5e89b --- /dev/null +++ b/game/scripts/vscripts/invk/const/invoker.lua @@ -0,0 +1,231 @@ +local HeroKeyValues = require("invk.dota2.kv.hero_key_values") +local UNITS = require("invk.const.units") +local talents = require("invk.dota2.talents") +local tbl = require("invk.lang.table") + +local FMT_ABILITY_TALENT_CONST_NAME = "TALENT_L%d_%s" + +--- @type { [string]: boolean } +local SKIP_SERIALIZATION = {} + +--- @param name string +local function skip_serialize(name) + SKIP_SERIALIZATION[name] = true +end + +--- Invoker constants. +--- @class invk.const.invoker +--- @field private __serialized invk.dota2.KeyValues? +local M = { + __serialized = nil, +} + +--- @return invk.dota2.KeyValues +function M:serialize() + if self.__serialized == nil then + self.__serialized = tbl.filter(self --[[@as table]], function(_, key) + return not SKIP_SERIALIZATION[key] + end) + end + + return self.__serialized +end + +(function() + local hero_kv = HeroKeyValues:load(UNITS.INVOKER) + + --- Hero id + M.HERO_ID = hero_kv:require_integer("HeroID") + + --- Unit name + M.UNIT_NAME = UNITS.INVOKER + + --- Units spawned by Invoker (copy of [invk.const.units.INVOKER_SPAWNED]) + M.SPAWNED_UNITS = UNITS.INVOKER_SPAWNED + + --- [invk.dota2.kv.HeroKeyValues] instance + M.KEY_VALUES = hero_kv + + skip_serialize("KEY_VALUES") + + --- @class invk.dota2.invoker.AbilityNames + --- @field TALENT_L10_RIGHT invk.dota2.invoker.AbilityName # Level 10 right talent ability name + --- @field TALENT_L10_LEFT invk.dota2.invoker.AbilityName # Level 10 left talent ability name + --- @field TALENT_L15_RIGHT invk.dota2.invoker.AbilityName # Level 15 right talent ability name + --- @field TALENT_L15_LEFT invk.dota2.invoker.AbilityName # Level 15 left talent ability name + --- @field TALENT_L20_RIGHT invk.dota2.invoker.AbilityName # Level 20 right talent ability name + --- @field TALENT_L20_LEFT invk.dota2.invoker.AbilityName # Level 20 left talent ability name + --- @field TALENT_L25_RIGHT invk.dota2.invoker.AbilityName # Level 25 right talent ability name + --- @field TALENT_L25_LEFT invk.dota2.invoker.AbilityName # Level 25 left talent ability name + M.AbilityName = { + --- Quas ability name + QUAS = "invoker_quas", + --- Wex ability name + WEX = "invoker_wex", + --- Exort ability name + EXORT = "invoker_exort", + --- Empty1 ability name + EMPTY1 = "invoker_empty1", + --- Empty2 ability name + EMPTY2 = "invoker_empty2", + --- Invoke ability name + INVOKE = "invoker_invoke", + --- Cold Snap ability name + COLD_SNAP = "invoker_cold_snap", + --- Ghost Walk ability name + GHOST_WALK = "invoker_ghost_walk", + --- Ice Wall ability name + ICE_WALL = "invoker_ice_wall", + --- EMP ability name + EMP = "invoker_emp", + --- Tornado ability name + TORNADO = "invoker_tornado", + --- Alacrity ability name + ALACRITY = "invoker_alacrity", + --- Sun Strike ability name + SUN_STRIKE = "invoker_sun_strike", + --- Forge Spirit ability name + FORGE_SPIRIT = "invoker_forge_spirit", + --- Chaos Meteor ability name + CHAOS_METEOR = "invoker_chaos_meteor", + --- Deafening Blast ability name + DEAFENING_BLAST = "invoker_deafening_blast", + } + + for enum_value, ability_name in pairs(M.KEY_VALUES.talents) do + local level_side = assertf( + talents.level_and_side(enum_value), + "could not find LevelAndSide() for talents value %d", + enum_value + ) + + local level = level_side[1] + local side = tostring(level_side[2]):upper() + local const_name = F(FMT_ABILITY_TALENT_CONST_NAME, level, side) + + M.AbilityName[const_name] = ability_name + end + + --- Tuple of orb abilities names. + --- + --- 1. Quas + --- 2. Wex + --- 3. Exort + --- + --- @type invk.dota2.invoker.OrbTriplet + M.ORB_ABILITIES = { M.AbilityName.QUAS, M.AbilityName.WEX, M.AbilityName.EXORT } + + --- List of orb abilities names. + --- + --- 1. Cold Snap + --- 2. Ghost Walk + --- 3. Ice Wall + --- 4. EMP + --- 5. Tornado + --- 6. Alacrity + --- 7. Sun Strike + --- 8. Forge Spirit + --- 9. Chaos Meteor + --- 10. Deafening Blast + --- + --- @type invk.dota2.invoker.AbilityName[] + M.SPELL_ABILITIES = { + M.AbilityName.COLD_SNAP, + M.AbilityName.GHOST_WALK, + M.AbilityName.ICE_WALL, + M.AbilityName.EMP, + M.AbilityName.TORNADO, + M.AbilityName.ALACRITY, + M.AbilityName.SUN_STRIKE, + M.AbilityName.FORGE_SPIRIT, + M.AbilityName.CHAOS_METEOR, + M.AbilityName.DEAFENING_BLAST, + } + + --- Array of talent abilities names. + --- @type invk.dota2.invoker.AbilityName[] + M.TALENT_ABILITIES = tbl.values(M.KEY_VALUES.talents) + + --- Table of orb abilities composition ("recipes") of spell abilities. + --- @type { [invk.dota2.invoker.AbilityName]: invk.dota2.invoker.OrbTriplet } + M.SPELL_COMPOSITION = { + [M.AbilityName.COLD_SNAP] = { + M.AbilityName.QUAS, + M.AbilityName.QUAS, + M.AbilityName.QUAS, + }, + [M.AbilityName.GHOST_WALK] = { + M.AbilityName.QUAS, + M.AbilityName.QUAS, + M.AbilityName.WEX, + }, + [M.AbilityName.ICE_WALL] = { + M.AbilityName.QUAS, + M.AbilityName.QUAS, + M.AbilityName.EXORT, + }, + [M.AbilityName.EMP] = { + M.AbilityName.WEX, + M.AbilityName.WEX, + M.AbilityName.WEX, + }, + [M.AbilityName.TORNADO] = { + M.AbilityName.WEX, + M.AbilityName.WEX, + M.AbilityName.QUAS, + }, + [M.AbilityName.ALACRITY] = { + M.AbilityName.WEX, + M.AbilityName.WEX, + M.AbilityName.EXORT, + }, + [M.AbilityName.SUN_STRIKE] = { + M.AbilityName.EXORT, + M.AbilityName.EXORT, + M.AbilityName.EXORT, + }, + [M.AbilityName.FORGE_SPIRIT] = { + M.AbilityName.EXORT, + M.AbilityName.EXORT, + M.AbilityName.QUAS, + }, + [M.AbilityName.CHAOS_METEOR] = { + M.AbilityName.EXORT, + M.AbilityName.EXORT, + M.AbilityName.WEX, + }, + [M.AbilityName.DEAFENING_BLAST] = { + M.AbilityName.QUAS, + M.AbilityName.WEX, + M.AbilityName.EXORT, + }, + } + + --- EMPTY1 and EMPTY2 can change indices, we're using them only to reference spell slots + --- @enum invk.dota2.invoker.AbilityIndex + M.AbilityIndex = { + --- Quas ability index. + QUAS = 0, + --- Wex ability index. + WEX = 1, + --- Exort ability index. + EXORT = 2, + --- Spell slot 1 ability index. + EMPTY1 = 3, + --- Spell slot 2 ability index. + EMPTY2 = 4, + --- Invoke ability index. + INVOKE = 5, + } + + --- Maximum index of the last visible ability. + --- + --- Abilities with index higher than this are hidden. + M.MAX_VISIBLE_ABILITY_INDEX = M.AbilityIndex.INVOKE + + M.FACETS = M.KEY_VALUES:require_kv("Facets") + + skip_serialize("FACETS") +end)() + +return M diff --git a/game/scripts/vscripts/invokation/const/limits.lua b/game/scripts/vscripts/invk/const/limits.lua similarity index 66% rename from game/scripts/vscripts/invokation/const/limits.lua rename to game/scripts/vscripts/invk/const/limits.lua index e5ba9c3..11ed761 100644 --- a/game/scripts/vscripts/invokation/const/limits.lua +++ b/game/scripts/vscripts/invk/const/limits.lua @@ -1,5 +1,5 @@ --- Limits constants. --- @module invokation.const.limits +--- @class invk.const.limits local M = {} M.MAX_HERO_LEVEL = 30 diff --git a/game/scripts/vscripts/invk/const/metadata.lua b/game/scripts/vscripts/invk/const/metadata.lua new file mode 100644 index 0000000..7857958 --- /dev/null +++ b/game/scripts/vscripts/invk/const/metadata.lua @@ -0,0 +1,25 @@ +--- Package metadata. +--- +--- This loosely follows the [Rockspec format][rockspec]. +--- +--- [rockspec]: https://github.com/luarocks/luarocks/wiki/Rockspec-format +--- @class invk.const.metadata +local M = {} + +--- Package name +M.package = "Invokation" + +--- Package version +M.version = "0.5.3" + +--- Package description +M.description = { + summary = "Invokation School of Arcane Arts", + license = "MIT", + homepage = "https://github.com/13k/invokation", + issues_url = "https://github.com/13k/invokation/issues", + maintainer = "13k ", + labels = { "dota2", "dota2-addon", "dota2-custom-game", "invoker", "invoker-trainer" }, +} + +return M diff --git a/game/scripts/vscripts/invk/const/net_table.lua b/game/scripts/vscripts/invk/const/net_table.lua new file mode 100644 index 0000000..7248afb --- /dev/null +++ b/game/scripts/vscripts/invk/const/net_table.lua @@ -0,0 +1,37 @@ +--- NetTable constants. +--- @class invk.const.net_tables +local M = {} + +--- @enum invk.net_table.Name +M.Name = { + MAIN = "invokation", + HERO = "hero", + ABILITIES = "abilities", +} + +--- @type { [invk.net_table.Name]: invk.net_table.Config } +M.Tables = { + [M.Name.MAIN] = { + name = M.Name.MAIN, + keys = { + COMBOS = "combos", + HERO_DATA = "hero_data", + }, + }, + + [M.Name.HERO] = { + name = M.Name.HERO, + keys = { + KEY_VALUES = "kv", + }, + }, + + [M.Name.ABILITIES] = { + name = M.Name.ABILITIES, + keys = { + KEY_VALUES = "kv", + }, + }, +} + +return M diff --git a/game/scripts/vscripts/invokation/const/precache.lua b/game/scripts/vscripts/invk/const/precache.lua similarity index 84% rename from game/scripts/vscripts/invokation/const/precache.lua rename to game/scripts/vscripts/invk/const/precache.lua index b842ba0..61660b5 100644 --- a/game/scripts/vscripts/invokation/const/precache.lua +++ b/game/scripts/vscripts/invk/const/precache.lua @@ -1,7 +1,7 @@ ---- Precache constants. --- @module invokation.const.precache -local UNITS = require("invokation.const.units") +local UNITS = require("invk.const.units") +--- Precache constants. +--- @class invk.const.precache local M = {} --- Precached units. diff --git a/game/scripts/vscripts/invokation/const/settings.lua b/game/scripts/vscripts/invk/const/settings.lua similarity index 54% rename from game/scripts/vscripts/invokation/const/settings.lua rename to game/scripts/vscripts/invk/const/settings.lua index 031a6c7..e42a708 100644 --- a/game/scripts/vscripts/invokation/const/settings.lua +++ b/game/scripts/vscripts/invk/const/settings.lua @@ -1,499 +1,540 @@ ---- Game settings. --- @module invokation.const.settings -local UNITS = require("invokation.const.units") +local UNITS = require("invk.const.units") +--- Game settings. +--- @class invk.const.settings local M = {} --- Control if the normal DOTA hero respawn rules apply. --- --- If disabled, heroes need to be manually respawned. --- --- `GameRules:SetHeroRespawnEnabled(bool)` +--- +--- If disabled, heroes need to be manually respawned. +--- +--- `GameRules:SetHeroRespawnEnabled(bool)` +--- @type boolean M.ENABLE_HERO_RESPAWN = true --- When true, all items are available at as long as any shop is in range. --- --- `GameRules:SetUseUniversalShopMode(bool)` +--- +--- `GameRules:SetUseUniversalShopMode(bool)` +--- @type boolean M.UNIVERSAL_SHOP_MODE = true --- When true, players can repeatedly pick the same hero. --- --- `GameRules:SetSameHeroSelectionEnabled(bool)` +--- +--- `GameRules:SetSameHeroSelectionEnabled(bool)` +--- @type boolean M.ALLOW_SAME_HERO_SELECTION = true --- Sets the amount of time players have to pick their hero. --- --- `GameRules:SetHeroSelectionTime(float)` +--- +--- `GameRules:SetHeroSelectionTime(float)` M.HERO_SELECTION_TIME = 0 --- Sets amount of penalty time before randoming a hero --- --- `GameRules:SetHeroSelectPenaltyTime(float)` +--- +--- `GameRules:SetHeroSelectPenaltyTime(float)` M.HERO_SELECTION_PENALTY_TIME = 3 --- Sets the amount of time players have between the hero selection and entering the showcase phase. --- --- `GameRules:SetStrategyTime(float)` +--- +--- `GameRules:SetStrategyTime(float)` M.STRATEGY_TIME = 0 --- Sets the amount of time players have between the strategy phase and entering the pre-game phase. --- --- `GameRules:SetShowcaseTime(float)` +--- +--- `GameRules:SetShowcaseTime(float)` M.SHOWCASE_TIME = 0 --- Sets the amount of time players have between picking their hero and game start. --- --- `GameRules:SetPreGameTime(float)` +--- +--- `GameRules:SetPreGameTime(float)` M.PRE_GAME_TIME = 0 --- Sets the amount of time players have between the game ending and the server disconnecting them. --- --- `GameRules:SetPostGameTime(float)` +--- +--- `GameRules:SetPostGameTime(float)` M.POST_GAME_TIME = 60 --- Sets the tree regrow time in seconds. --- --- `GameRules:SetTreeRegrowTime(float)` +--- +--- `GameRules:SetTreeRegrowTime(float)` M.TREE_REGROW_TIME = 300 --- Set the starting gold amount. --- --- `GameRules:SetStartingGold(int)` +--- +--- `GameRules:SetStartingGold(int)` M.STARTING_GOLD = 0 --- Set the auto gold increase per timed interval. --- --- `GameRules:SetGoldPerTick(int)` +--- +--- `GameRules:SetGoldPerTick(int)` M.GOLD_PER_TICK = 0 --- Set the time interval between auto gold increases. --- --- `GameRules:SetGoldTickTime(float)` +--- +--- `GameRules:SetGoldTickTime(float)` M.GOLD_TICK_TIME = 60 --- Scale the hero minimap icons on the minimap. --- --- `GameRules:SetHeroMinimapIconScale(flMinimapHeroIconScale)` +--- +--- `GameRules:SetHeroMinimapIconScale(flMinimapHeroIconScale)` M.MINIMAP_HERO_ICON_SCALE = 1 --- Scale the creep icons on the minimap. --- --- `GameRules:SetCreepMinimapIconScale(flMinimapCreepIconScale)` +--- +--- `GameRules:SetCreepMinimapIconScale(flMinimapCreepIconScale)` M.MINIMAP_CREEP_ICON_SCALE = 1 --- Scale the rune icons on the minimap. --- --- `GameRules:SetRuneMinimapIconScale(flMinimapRuneIconScale)` +--- +--- `GameRules:SetRuneMinimapIconScale(flMinimapRuneIconScale)` M.MINIMAP_RUNE_ICON_SCALE = 1 --- Sets whether the regular Dota creeps spawn. --- --- `GameRules:SetCreepSpawningEnabled(bool)` +--- +--- `GameRules:SetCreepSpawningEnabled(bool)` +--- @type boolean M.ENABLE_CREEP_SPAWN = false --- Sets a flag to enable/disable the default music handling code for custom games --- --- `GameRules:SetCustomGameAllowBattleMusic(bool)` +--- +--- `GameRules:SetCustomGameAllowBattleMusic(bool)` +--- @type boolean M.ENABLE_BATTLE_MUSIC = true --- Sets a flag to enable/disable the default music handling code for custom games --- --- `GameRules:SetCustomGameAllowHeroPickMusic(bool)` +--- +--- `GameRules:SetCustomGameAllowHeroPickMusic(bool)` +--- @type boolean M.ENABLE_HERO_PICK_MUSIC = true --- Sets a flag to enable/disable the default music handling code for custom games --- --- `GameRules:SetCustomGameAllowMusicAtGameStart(bool)` +--- +--- `GameRules:SetCustomGameAllowMusicAtGameStart(bool)` +--- @type boolean M.ENABLE_GAME_START_MUSIC = true --- Sets the amount of time between rune spawns. --- --- `GameRules:SetRuneSpawnTime(float)` +--- +--- `GameRules:SetRuneSpawnTime(float)` M.RUNE_SPAWN_TIME = 120 --- Enabled auto launch for custom game setup. --- --- The game will launch after @{AUTO_LAUNCH_DELAY} seconds. --- --- `GameRules:EnableCustomGameSetupAutoLaunch(bool)` +--- +--- The game will launch after [AUTO_LAUNCH_DELAY] seconds. +--- +--- `GameRules:EnableCustomGameSetupAutoLaunch(bool)` +--- @type boolean M.ENABLE_AUTO_LAUNCH = true --- Set the amount of time to wait for auto launch (default: 30, disable: 0). --- --- `GameRules:SetCustomGameSetupAutoLaunchDelay(float)` +--- +--- `GameRules:SetCustomGameSetupAutoLaunchDelay(float)` M.AUTO_LAUNCH_DELAY = 10 --- Set the amount of remaining time, in seconds, for custom game setup (disable: 0, infinite: -1). --- --- `GameRules:SetCustomGameSetupRemainingTime(float)` +--- +--- `GameRules:SetCustomGameSetupRemainingTime(float)` M.GAME_SETUP_TIME = 0 --- Setup (pre-gameplay) phase timeout (instant: 0, infinite: -1). --- --- If set to 0, players will not be assigned a "valid" team (their team value --- will be set to `DOTA_TEAM_NOTEAM`). --- --- If set to -1, `GameRules:FinishCustomGameSetup` must be called manually. --- --- `GameRules:SetCustomGameSetupTimeout(float)` +--- +--- If set to 0, players will not be assigned a "valid" team (their team value +--- will be set to `DOTA_TEAM_NOTEAM`). +--- +--- If set to -1, `GameRules:FinishCustomGameSetup` must be called manually. +--- +--- `GameRules:SetCustomGameSetupTimeout(float)` M.GAME_SETUP_TIMEOUT = 1 --- Lock team assignemnt. --- --- If team assignment is locked players cannot change teams. --- --- The host can still unlock the teams. --- --- `GameRules:LockCustomGameSetupTeamAssignment(bool)` +--- +--- If team assignment is locked players cannot change teams. +--- +--- The host can still unlock the teams. +--- +--- `GameRules:LockCustomGameSetupTeamAssignment(bool)` +--- @type boolean M.LOCK_TEAM_SETUP = true --- Should we use custom team colors? +--- @type boolean M.USE_CUSTOM_TEAM_COLORS = true --- Should we use custom team colors to color the players/minimap? +--- @type boolean M.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS = true --- Allows heroes in the map to give a specific amount of XP (this value must be set). --- --- `GameRules:SetUseCustomHeroXPValues(bool)` +--- +--- `GameRules:SetUseCustomHeroXPValues(bool)` +--- @type boolean M.USE_CUSTOM_XP_VALUES = false --- Heroes will use the basic NPC functionality for determining their bounty, --- rather than DOTA specific formulas. --- --- `GameRules:SetUseBaseGoldBountyOnHeroes(bool)` +--- rather than DOTA specific formulas. +--- +--- `GameRules:SetUseBaseGoldBountyOnHeroes(bool)` +--- @type boolean M.USE_BASE_HERO_GOLD_BOUNTY = true --- Should we display kills only on the top bar? (No denies, suicides, kills by neutrals) --- --- Requires @{USE_CUSTOM_TOP_BAR_VALUES} set to `true` +--- +--- Requires [USE_CUSTOM_TOP_BAR_VALUES] set to `true` +--- @type boolean M.SHOW_KILLS_ON_TOPBAR = false --- Should the game end after a certain number of kills? +--- @type boolean M.END_GAME_ON_KILLS = false --- How many kills for a team should signify an end of game? M.KILLS_TO_END_GAME_FOR_TEAM = 0 --- Sets whether First Blood can be triggered. --- --- `GameRules:SetFirstBloodActive(bool)` +--- +--- `GameRules:SetFirstBloodActive(bool)` +--- @type boolean M.ENABLE_FIRST_BLOOD = false --- Sets whether the multikill, streak, and first-blood banners appear at the top of the screen. --- --- `GameRules:SetHideKillMessageHeaders(bool)` +--- +--- `GameRules:SetHideKillMessageHeaders(bool)` +--- @type boolean M.HIDE_KILL_BANNERS = true --- Sets the game end delay (default: -1). --- --- `GameRules:SetCustomGameEndDelay(float)` +--- +--- `GameRules:SetCustomGameEndDelay(float)` M.GAME_END_DELAY = -1 --- Sets the victory message. --- --- `GameRules:SetCustomVictoryMessage(string)` +--- +--- `GameRules:SetCustomVictoryMessage(string)` M.VICTORY_MESSAGE = "Well played!" --- Sets the victory message duration. --- --- `GameRules:SetCustomVictoryMessageDuration(float)` +--- +--- `GameRules:SetCustomVictoryMessageDuration(float)` M.VICTORY_MESSAGE_DURATION = 3 --- Turn the panel for showing recommended items at the shop off/on. --- --- `GameMode:SetRecommendedItemsDisabled(bDisabled)` +--- +--- `GameMode:SetRecommendedItemsDisabled(bDisabled)` +--- @type boolean M.RECOMMENDED_BUILDS_DISABLED = false --- Set a different camera distance (default: 1134, disable: -1). --- --- `GameMode:SetCameraDistanceOverride(flCameraDistanceOverride)` +--- +--- `GameMode:SetCameraDistanceOverride(flCameraDistanceOverride)` M.CAMERA_DISTANCE_OVERRIDE = -1 --- Set a different camera smooth count (default: 8). --- --- `GameMode:SetCameraSmoothCountOverride(nSmoothCount)` +--- +--- `GameMode:SetCameraSmoothCountOverride(nSmoothCount)` M.CAMERA_SMOOTH_COUNT = 8 --- Set the rate cooldown ticks down for items in the backpack. --- --- `GameMode:SetCustomBackpackCooldownPercent(flPercent)` +--- +--- `GameMode:SetCustomBackpackCooldownPercent(flPercent)` M.CUSTOM_BACKPACK_COOLDOWN_PERCENT = 0.5 --- Set a custom cooldown for swapping items into the backpack. --- --- `GameMode:SetCustomBackpackSwapCooldown(flCooldown)` +--- +--- `GameMode:SetCustomBackpackSwapCooldown(flCooldown)` M.CUSTOM_BACKPACK_SWAP_COOLDOWN = 6 --- Set a custom cooldown for team Glyph ability. --- --- `GameMode:SetCustomGlyphCooldown(flCooldown)` +--- +--- `GameMode:SetCustomGlyphCooldown(flCooldown)` M.CUSTOM_GLYPH_COOLDOWN = 300 --- Set a custom cooldown for team Scan ability. --- --- `GameMode:SetCustomScanCooldown(flCooldown)` +--- +--- `GameMode:SetCustomScanCooldown(flCooldown)` M.CUSTOM_SCAN_COOLDOWN = 300 --- Set the effect used as a custom weather effect, when units are on --- non-default terrain, in this mode. --- --- `GameMode:SetCustomTerrainWeatherEffect(pszEffectName)` +--- non-default terrain, in this mode. +--- +--- `GameMode:SetCustomTerrainWeatherEffect(pszEffectName)` +--- @type string? M.CUSTOM_TERRAIN_WEATHER_EFFECT = nil --- If set to true, use current rune spawn rules. --- --- Either setting respects custom spawn intervals. --- --- `GameMode:SetUseDefaultDOTARuneSpawnLogic(bEnabled)` +--- +--- Either setting respects custom spawn intervals. +--- +--- `GameMode:SetUseDefaultDOTARuneSpawnLogic(bEnabled)` +--- @type boolean M.USE_DEFAULT_DOTA_RUNE_SPAWN_LOGIC = true --- Turns on capability to define custom buyback costs. --- --- `GameMode:SetCustomBuybackCostEnabled(bEnabled)` +--- +--- `GameMode:SetCustomBuybackCostEnabled(bEnabled)` +--- @type boolean M.CUSTOM_BUYBACK_COST_ENABLED = true --- Turns on capability to define custom buyback cooldowns. --- --- `GameMode:SetCustomBuybackCooldownEnabled(bEnabled)` +--- +--- `GameMode:SetCustomBuybackCooldownEnabled(bEnabled)` +--- @type boolean M.CUSTOM_BUYBACK_COOLDOWN_ENABLED = true --- Enables or disables buyback completely. --- --- `GameMode:SetBuybackEnabled(bEnabled)` +--- +--- `GameMode:SetBuybackEnabled(bEnabled)` +--- @type boolean M.BUYBACK_ENABLED = false --- Turn the fog of war on or off. --- --- `GameMode:SetFogOfWarDisabled(bDisabled)` +--- +--- `GameMode:SetFogOfWarDisabled(bDisabled)` +--- @type boolean M.DISABLE_FOG_OF_WAR = false --- Enable or disable unseen fog of war. --- --- When enabled parts of the map the player has never seen will be completely hidden by fog of war. --- --- @{DISABLE_FOG_OF_WAR} must be `false` for @{USE_UNSEEN_FOG_OF_WAR} to work. --- --- `GameMode:SetUnseenFogOfWarEnabled(bEnabled)` +--- +--- When enabled parts of the map the player has never seen will be completely hidden by fog of war. +--- +--- [DISABLE_FOG_OF_WAR] must be `false` for [USE_UNSEEN_FOG_OF_WAR] to work. +--- +--- `GameMode:SetUnseenFogOfWarEnabled(bEnabled)` +--- @type boolean M.USE_UNSEEN_FOG_OF_WAR = false --- Enables/Disables bots in custom games. --- --- Note: this will only work with default heroes in the dota map. --- --- `GameMode:SetBotThinkingEnabled(bEnabled)` +--- +--- Note: this will only work with default heroes in the dota map. +--- +--- `GameMode:SetBotThinkingEnabled(bEnabled)` +--- @type boolean M.USE_STANDARD_DOTA_BOT_THINKING = false --- Set if the bots should try their best to push with a human player. --- --- `GameMode:SetBotsAlwaysPushWithHuman(bAlwaysPush)` +--- +--- `GameMode:SetBotsAlwaysPushWithHuman(bAlwaysPush)` +--- @type boolean M.BOTS_ALWAYS_PUSH_WITH_HUMAN = false --- Set if bots should enable their late game behavior. --- --- `GameMode:SetBotsInLateGame(bLateGame)` +--- +--- `GameMode:SetBotsInLateGame(bLateGame)` +--- @type boolean M.BOTS_LATE_GAME_BEHAVIOR = false --- Set the max tier of tower that bots want to push. (-1 to disable). --- --- `GameMode:SetBotsMaxPushTier(nMaxTier)` +--- +--- `GameMode:SetBotsMaxPushTier(nMaxTier)` M.BOTS_MAX_PUSH_TIER = -1 --- Set bounty rune spawn rate. --- --- `GameMode:SetBountyRuneSpawnInterval(flInterval)` +--- +--- `GameMode:SetBountyRuneSpawnInterval(flInterval)` M.BOUNTY_RUNE_SPAWN_INTERVAL = 600 --- Override the values of the team values on the top game bar. --- --- `GameMode:SetTopBarTeamValuesOverride(bOverride)` +--- +--- `GameMode:SetTopBarTeamValuesOverride(bOverride)` +--- @type boolean M.USE_CUSTOM_TOP_BAR_VALUES = true --- Turning on/off the team values on the top game bar. --- --- `GameMode:SetTopBarTeamValuesVisible(bVisible)` +--- +--- `GameMode:SetTopBarTeamValuesVisible(bVisible)` +--- @type boolean M.TOP_BAR_VISIBLE = false --- Enables/Disables tower backdoor protection. --- --- `GameMode:SetTowerBackdoorProtectionEnabled(bEnabled)` +--- +--- `GameMode:SetTowerBackdoorProtectionEnabled(bEnabled)` +--- @type boolean M.ENABLE_TOWER_BACKDOOR_PROTECTION = true --- Make it so illusions are immediately removed upon death, rather than --- sticking around for a few seconds. --- --- `GameMode:SetRemoveIllusionsOnDeath(bRemove)` +--- sticking around for a few seconds. +--- +--- `GameMode:SetRemoveIllusionsOnDeath(bRemove)` +--- @type boolean M.REMOVE_ILLUSIONS_ON_DEATH = true --- Sets the scale applied to non-fixed respawn times (default: 1). --- --- `GameMode:SetRespawnTimeScale(flValue)` +--- +--- `GameMode:SetRespawnTimeScale(flValue)` M.RESPAWN_TIME_SCALE = 1 --- Turn the sound when gold is acquired off/on. --- --- `GameMode:SetGoldSoundDisabled(bDisabled)` +--- +--- `GameMode:SetGoldSoundDisabled(bDisabled)` +--- @type boolean M.DISABLE_GOLD_SOUNDS = false --- Specify whether the default combat events will show in the HUD. --- --- `GameMode:SetHudCombatEventsDisabled(bDisabled)` +--- +--- `GameMode:SetHudCombatEventsDisabled(bDisabled)` +--- @type boolean M.DISABLE_COMBAT_EVENTS_HUD = false --- Set whether tombstones can be channeled to be removed by enemy heroes. --- --- `GameMode:SetKillableTombstones(bEnabled)` +--- +--- `GameMode:SetKillableTombstones(bEnabled)` +--- @type boolean M.KILLABLE_TOMBSTONES = false --- Use to disable gold loss on death. --- --- `GameMode:SetLoseGoldOnDeath(bEnabled)` +--- +--- `GameMode:SetLoseGoldOnDeath(bEnabled)` +--- @type boolean M.LOSE_GOLD_ON_DEATH = false --- Show the player hero's inventory in the HUD, regardless of what unit is selected. --- --- `GameMode:SetAlwaysShowPlayerInventory(bAlwaysShow)` +--- +--- `GameMode:SetAlwaysShowPlayerInventory(bAlwaysShow)` +--- @type boolean M.ALWAYS_SHOW_PLAYER_INVENTORY = false --- Set whether player names are always shown, regardless of client setting. --- --- `GameMode:SetAlwaysShowPlayerNames(bEnabled)` +--- +--- `GameMode:SetAlwaysShowPlayerNames(bEnabled)` +--- @type boolean M.ALWAYS_SHOW_PLAYER_NAMES = false --- Turn purchasing items to the stash off/on. --- --- If purchasing to the stash is off the player must be at a shop to purchase items. --- --- `GameMode:SetStashPurchasingDisabled(bDisabled)` +--- +--- If purchasing to the stash is off the player must be at a shop to purchase items. +--- +--- `GameMode:SetStashPurchasingDisabled(bDisabled)` +--- @type boolean M.DISABLE_STASH_PURCHASING = true --- Mutes the in-game announcer. --- --- `GameMode:SetAnnouncerDisabled(bDisabled)` +--- +--- `GameMode:SetAnnouncerDisabled(bDisabled)` +--- @type boolean M.DISABLE_ANNOUNCER = true --- Force all players to use the specified hero and disable the normal hero --- selection process (e.g. `"npc_dota_hero_axe"`). --- --- Must be used before hero selection. Set to `nil` to allow players to pick their own hero. --- --- `GameMode:SetCustomGameForceHero(pHeroName)` +--- selection process (e.g. `"npc_dota_hero_axe"`). +--- +--- Must be used before hero selection. Set to `nil` to allow players to pick their own hero. +--- +--- `GameMode:SetCustomGameForceHero(pHeroName)` M.FORCE_PICKED_HERO = UNITS.INVOKER --- Set a fixed delay for all players to respawn after (-1 for default). --- --- `GameMode:SetFixedRespawnTime(flFixedRespawnTime)` +--- +--- `GameMode:SetFixedRespawnTime(flFixedRespawnTime)` M.FIXED_RESPAWN_TIME = 1 --- Set the constant rate that the fountain will regen mana (-1 for default). --- --- `GameMode:SetFountainConstantManaRegen(flConstantManaRegen)` +--- +--- `GameMode:SetFountainConstantManaRegen(flConstantManaRegen)` M.FOUNTAIN_CONSTANT_MANA_REGEN = -1 --- Set the percentage rate that the fountain will regen mana. (-1 for default). --- --- `GameMode:SetFountainPercentageManaRegen(flPercentageManaRegen)` +--- +--- `GameMode:SetFountainPercentageManaRegen(flPercentageManaRegen)` M.FOUNTAIN_PERCENTAGE_MANA_REGEN = -1 --- Set the percentage rate that the fountain will regen health. (-1 for default). --- --- `GameMode:SetFountainPercentageHealthRegen(flPercentageHealthRegen)` +--- +--- `GameMode:SetFountainPercentageHealthRegen(flPercentageHealthRegen)` M.FOUNTAIN_PERCENTAGE_HEALTH_REGEN = -1 --- Allows clicks on friendly buildings to be handled normally. --- --- `GameMode:SetFriendlyBuildingMoveToEnabled(bEnabled)` +--- +--- `GameMode:SetFriendlyBuildingMoveToEnabled(bEnabled)` +--- @type boolean M.ENABLE_FRIENDLY_BUILDING_MOVE_TO_CLICK = true --- Set the maximum attack speed for units. --- --- `GameMode:SetMaximumAttackSpeed(nMaxSpeed)` +--- +--- `GameMode:SetMaximumAttackSpeed(nMaxSpeed)` M.MAXIMUM_ATTACK_SPEED = 600 --- Set the minimum attack speed for units. --- --- `GameMode:SetMinimumAttackSpeed(nMinSpeed)` +--- +--- `GameMode:SetMinimumAttackSpeed(nMinSpeed)` M.MINIMUM_ATTACK_SPEED = 20 --- Set pausing enabled/disabled. --- --- `GameMode:SetPauseEnabled(bEnabled)` +--- +--- `GameMode:SetPauseEnabled(bEnabled)` +--- @type boolean M.ENABLE_PAUSE = true --- Set power rune spawn rate. --- --- `GameMode:SetPowerRuneSpawnInterval(flInterval)` +--- +--- `GameMode:SetPowerRuneSpawnInterval(flInterval)` M.POWER_RUNE_SPAWN_INTERVAL = 120 --- Should we disable the day night cycle from naturally occurring? --- --- (Manual adjustment still possible) --- --- `GameMode:SetDaynightCycleDisabled(bDisable)` +--- +--- (Manual adjustment still possible) +--- +--- `GameMode:SetDaynightCycleDisabled(bDisable)` +--- @type boolean M.DISABLE_DAY_NIGHT_CYCLE = false --- Specify whether the full screen death overlay effect plays when the selected hero dies. --- --- `GameMode:SetDeathOverlayDisabled(bDisabled)` +--- +--- `GameMode:SetDeathOverlayDisabled(bDisabled)` +--- @type boolean M.DISABLE_DEATH_OVERLAY = true --- Set drafting hero banning time. --- --- `GameMode:SetDraftingBanningTimeOverride(flValue)` +--- +--- `GameMode:SetDraftingBanningTimeOverride(flValue)` M.DRAFTING_BANNING_TIME = 0 --- Set drafting hero pick time. --- `GameMode:SetDraftingHeroPickSelectTimeOverride(flValue)` +--- `GameMode:SetDraftingHeroPickSelectTimeOverride(flValue)` M.DRAFTING_HERO_PICK_SELECTION_TIME = 0 --- Mutes the in-game killing spree announcer. --- --- `GameMode:SetKillingSpreeAnnouncerDisabled(bDisabled)` +--- +--- `GameMode:SetKillingSpreeAnnouncerDisabled(bDisabled)` +--- @type boolean M.DISABLE_KILLING_SPREE_ANNOUNCER = true --- Hide the sticky item in the quickbuy. --- --- `GameMode:SetStickyItemDisabled(bDisabled)` +--- +--- `GameMode:SetStickyItemDisabled(bDisabled)` +--- @type boolean M.DISABLE_STICKY_ITEM = true --- Set if weather effects are disabled. --- --- `GameMode:SetWeatherEffectsDisabled(bDisable)` +--- +--- `GameMode:SetWeatherEffectsDisabled(bDisable)` +--- @type boolean M.DISABLE_WEATHER_EFFECTS = false --- Enable/disable gold penalty for late picking. --- --- `GameMode:SetSelectionGoldPenaltyEnabled(bEnabled)` +--- +--- `GameMode:SetSelectionGoldPenaltyEnabled(bEnabled)` +--- @type boolean M.ENABLE_SELECTION_GOLD_PENALTY = true --- Turn on custom-defined XP values for hero level ups. --- --- The table should be defined before switching this on. --- --- `GameMode:SetUseCustomHeroLevels(bEnabled)` +--- +--- The table should be defined before switching this on. +--- +--- `GameMode:SetUseCustomHeroLevels(bEnabled)` +--- @type boolean M.USE_CUSTOM_HERO_LEVELS = false --- Allows definition of a table of hero XP values. --- --- If @{USE_CUSTOM_XP_VALUES} is set, use these values as required XP per level. --- --- `GameMode:SetCustomXPRequiredToReachNextLevel(hTable)` +--- +--- If [USE_CUSTOM_XP_VALUES] is set, use these values as required XP per level. +--- +--- `GameMode:SetCustomXPRequiredToReachNextLevel(hTable)` M.XP_PER_LEVEL_TABLE = {} --- Which runes should be enabled to spawn in our game mode? --- --- You always need at least 2 non-bounty type runes to be able to spawn or your game will crash. --- --- @table ENABLED_RUNES --- @tfield bool DOTA_RUNE_DOUBLEDAMAGE Double Damage --- @tfield bool DOTA_RUNE_HASTE Haste --- @tfield bool DOTA_RUNE_ILLUSION Illusion --- @tfield bool DOTA_RUNE_INVISIBILITY Invisibility --- @tfield bool DOTA_RUNE_REGENERATION Regeneration --- @tfield bool DOTA_RUNE_BOUNTY Bounty --- @tfield bool DOTA_RUNE_ARCANE Arcane --- --- `GameMode:SetRuneEnabled(nRune, bEnabled)` +--- +--- You always need at least 2 non-bounty type runes to be able to spawn or your game will crash. +--- +--- `GameMode:SetRuneEnabled(nRune, bEnabled)` +--- @type { [DOTA_RUNES]: boolean } M.ENABLED_RUNES = { [DOTA_RUNE_DOUBLEDAMAGE] = true, [DOTA_RUNE_HASTE] = true, @@ -505,29 +546,19 @@ M.ENABLED_RUNES = { } --- Custom team colors. --- --- If @{USE_CUSTOM_TEAM_COLORS} is set, team colors will be set to these colors. --- --- If @{USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS} is set, player colors will be set --- according to their respective teams. --- --- Color definition is a tuple of 3 integers: `{red, green, blue}`. --- --- @table TEAM_COLORS --- @tfield {int,...} DOTA_TEAM_GOODGUYS Radiant --- @tfield {int,...} DOTA_TEAM_BADGUYS Dire --- @tfield {int,...} DOTA_TEAM_CUSTOM_1 Custom Team 1 --- @tfield {int,...} DOTA_TEAM_CUSTOM_2 Custom Team 2 --- @tfield {int,...} DOTA_TEAM_CUSTOM_3 Custom Team 3 --- @tfield {int,...} DOTA_TEAM_CUSTOM_4 Custom Team 4 --- @tfield {int,...} DOTA_TEAM_CUSTOM_5 Custom Team 5 --- @tfield {int,...} DOTA_TEAM_CUSTOM_6 Custom Team 6 --- @tfield {int,...} DOTA_TEAM_CUSTOM_7 Custom Team 7 --- @tfield {int,...} DOTA_TEAM_CUSTOM_8 Custom Team 8 --- --- `SetTeamCustomHealthbarColor(teamNumber, r, g, b)` --- --- `PlayerResource:SetCustomPlayerColor(playerId, r, g, b)` +--- +--- If [USE_CUSTOM_TEAM_COLORS] is set, team colors will be set to these colors. +--- +--- If [USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS] is set, player colors will be set +--- according to their respective teams. +--- +--- Color definition is a tuple of 3 integers: `{red, green, blue}`. +--- +--- ```lua +--- SetTeamCustomHealthbarColor(teamNumber, r, g, b) +--- PlayerResource:SetCustomPlayerColor(playerId, r, g, b) +--- ``` +--- @type { [DOTATeam_t]: { [1]: integer, [2]: integer, [3]: integer } } M.TEAM_COLORS = { [DOTA_TEAM_GOODGUYS] = { 61, 210, 150 }, -- Teal [DOTA_TEAM_BADGUYS] = { 243, 201, 9 }, -- Yellow @@ -542,20 +573,11 @@ M.TEAM_COLORS = { } --- If we're not automatically setting the number of players per team, use this table. --- --- @table CUSTOM_TEAM_PLAYER_COUNT --- @tfield int DOTA_TEAM_GOODGUYS Radiant --- @tfield int DOTA_TEAM_BADGUYS Dire --- @tfield int DOTA_TEAM_CUSTOM_1 Custom Team 1 --- @tfield int DOTA_TEAM_CUSTOM_2 Custom Team 2 --- @tfield int DOTA_TEAM_CUSTOM_3 Custom Team 3 --- @tfield int DOTA_TEAM_CUSTOM_4 Custom Team 4 --- @tfield int DOTA_TEAM_CUSTOM_5 Custom Team 5 --- @tfield int DOTA_TEAM_CUSTOM_6 Custom Team 6 --- @tfield int DOTA_TEAM_CUSTOM_7 Custom Team 7 --- @tfield int DOTA_TEAM_CUSTOM_8 Custom Team 8 --- --- `GameRules:SetCustomGameTeamMaxPlayers(int, int)` +--- +--- ```lua +--- GameRules:SetCustomGameTeamMaxPlayers(team, count) +--- ``` +--- @type { [DOTATeam_t]: integer } M.CUSTOM_TEAM_PLAYER_COUNT = { [DOTA_TEAM_GOODGUYS] = 1, [DOTA_TEAM_BADGUYS] = 0, diff --git a/game/scripts/vscripts/invokation/const/sound_events.lua b/game/scripts/vscripts/invk/const/sound_events.lua similarity index 68% rename from game/scripts/vscripts/invokation/const/sound_events.lua rename to game/scripts/vscripts/invk/const/sound_events.lua index 211668c..a364943 100644 --- a/game/scripts/vscripts/invokation/const/sound_events.lua +++ b/game/scripts/vscripts/invk/const/sound_events.lua @@ -1,23 +1,14 @@ --- Sound event names. --- @module invokation.const.sound_events +--- @class invk.const.sound_events local M = {} ---- Invoker --- @section invoker - --- Invoker meteor loop M.SNDEVT_INVOKER_METEOR_LOOP = "Hero_Invoker.ChaosMeteor.Loop" ---- Dummy Target --- @section dummy - ---- dummy creation events +--- Dummy creation events M.SNDEVTS_DUMMY_CREATE = { "Hero_ShadowShaman.Hex.Target" } ---- Combo --- @section combo - ---- start combo events +--- Start combo events M.SNDEVTS_COMBO_START = { "invoker_invo_begin_01", "invoker_invo_move_08", @@ -27,7 +18,7 @@ M.SNDEVTS_COMBO_START = { "invoker_invo_ability_invoke_01", } ---- stop combo events +--- Stop combo events M.SNDEVTS_COMBO_STOP = { "invoker_invo_failure_04" } return M diff --git a/game/scripts/vscripts/invokation/const/units.lua b/game/scripts/vscripts/invk/const/units.lua similarity index 52% rename from game/scripts/vscripts/invokation/const/units.lua rename to game/scripts/vscripts/invk/const/units.lua index 97e88ee..43e1c44 100644 --- a/game/scripts/vscripts/invokation/const/units.lua +++ b/game/scripts/vscripts/invk/const/units.lua @@ -1,19 +1,19 @@ --- Unit constants. --- @module invokation.const.units +--- @class invk.const.units local M = {} --- Dummy target spawn entity name --- @tfield string DUMMY_TARGET_SPAWN M.DUMMY_TARGET_SPAWN = "dummy_target_spawn" + --- Dummy target unit name --- @tfield string DUMMY_TARGET M.DUMMY_TARGET = "npc_invokation_dummy_target" + --- Invoker unit name --- @tfield string INVOKER M.INVOKER = "npc_dota_hero_invoker" + --- Units spawned by Invoker --- @table INVOKER_SPAWNED --- @tfield string FORGED_SPIRIT -M.INVOKER_SPAWNED = { FORGED_SPIRIT = "npc_dota_invoker_forged_spirit" } +M.INVOKER_SPAWNED = { + FORGED_SPIRIT = "npc_dota_invoker_forged_spirit", +} return M diff --git a/game/scripts/vscripts/invk/dota2/ability.lua b/game/scripts/vscripts/invk/dota2/ability.lua new file mode 100644 index 0000000..ce460c7 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/ability.lua @@ -0,0 +1,53 @@ +local class = require("middleclass") + +local INVOKER = require("invk.const.invoker") +local tbl = require("invk.lang.table") + +--- @alias invk.dota2.AbilityOrItem (CDOTABaseAbility | CDOTA_Item) + +--- Ability class that represents either an ability or item. +--- @class invk.dota2.Ability : middleclass.Class +--- @field entity invk.dota2.AbilityOrItem +--- @field name string +--- @field index integer +--- @field is_item boolean +local M = class("invk.dota2.Ability") + +local ORB_ABILITIES = tbl.reduce(INVOKER.ORB_ABILITIES, function(h, ability) + h[ability] = true + return h +end, {} --[[@as { [string]: boolean } ]]) + +--- Constructor. +--- @param entity invk.dota2.AbilityOrItem # Ability or item entity +function M:initialize(entity) + self.entity = entity + self.name = self.entity:GetAbilityName() + self.index = self.entity:GetAbilityIndex() + self.is_item = self.entity:IsItem() +end + +--- Checks if this ability is an Invoker orb ability (quas, wex or exort). +--- @return boolean # `true` if it's an orb ability, `false` otherwise +function M:is_orb_ability() + return ORB_ABILITIES[self.name] ~= nil +end + +--- Checks if this ability is an Invoker "invocation" ability (quas, wex, exort or invoke). +--- @return boolean # `true` if it's an invocation ability, `false` otherwise +function M:is_invocation_ability() + return self:is_orb_ability() or self.name == INVOKER.AbilityName.INVOKE +end + +--- @return number +function M:duration() + return self.entity:GetDuration() +end + +--- @param name string +--- @return number +function M:get_special_value_for(name) + return self.entity:GetSpecialValueFor(name) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/custom_events.lua b/game/scripts/vscripts/invk/dota2/custom_events.lua new file mode 100644 index 0000000..dac72fe --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/custom_events.lua @@ -0,0 +1,56 @@ +--- Custom events helpers. +--- @class invk.dota2.custom_events +local M = {} + +--- @generic Args +--- @param cb fun(player: CBaseEntity?, ...: Args) +--- @return fun(ent_idx: EntityIndex, ...: Args) +local function create_handler(cb) + --- @param playerEntIdx EntityIndex + --- @param ... Args + return function(playerEntIdx, ...) + local player = EntIndexToHScript(playerEntIdx) + + cb(player, ...) + end +end + +--- Register a callback to be called when a particular custom event arrives. +--- @generic Args +--- @param event string # Event +--- @param cb fun(player: CBaseEntity?, ...: Args) # Callback +--- @return CustomGameEventListenerID # Listener id that can be used to unregister later +function M.subscribe(event, cb) + return CustomGameEventManager:RegisterListener(event, create_handler(cb)) +end + +--- Unregister a given listener. +--- @param id CustomGameEventListenerID +function M.unsubscribe(id) + return CustomGameEventManager:UnregisterListener(id) +end + +--- Send event to all players. +--- @param event string # # Event name +--- @param payload? table # # Payload +function M.send_all(event, payload) + CustomGameEventManager:Send_ServerToAllClients(event, payload or {}) +end + +--- Send event to player. +--- @param event string # Event name +--- @param player CDOTAPlayerController # Player +--- @param payload? table # Payload +function M.send_player(event, player, payload) + CustomGameEventManager:Send_ServerToPlayer(player, event, payload or {}) +end + +--- Send event to team. +--- @param event string # Event name +--- @param team DOTATeam_t # Team id +--- @param payload? table # Payload +function M.send_team(event, team, payload) + CustomGameEventManager:Send_ServerToTeam(team, event, payload or {}) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/damage_instance.lua b/game/scripts/vscripts/invk/dota2/damage_instance.lua new file mode 100644 index 0000000..dea2c22 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/damage_instance.lua @@ -0,0 +1,49 @@ +local class = require("middleclass") + +--- DamageInstance class. +--- @class invk.dota2.DamageInstance : middleclass.Class +--- @field victim invk.dota2.Unit # Victim unit instance +--- @field amount number # Damage amount +--- @field attacker? invk.dota2.Unit # Attacker unit instance +--- @field inflictor? invk.dota2.Ability # Inflictor ability instance +--- @field category DamageCategory_t +local M = class("invk.dota2.DamageInstance") + +--- Constructor. +--- @param victim invk.dota2.Unit # Victim unit instance +--- @param amount number # Damage amount +--- @param attacker? invk.dota2.Unit # Attacker unit instance +--- @param inflictor? invk.dota2.Ability # Inflictor ability instance +function M:initialize(victim, amount, attacker, inflictor) + self.victim = victim + self.amount = amount + self.attacker = attacker + self.inflictor = inflictor + self.category = inflictor and DOTA_DAMAGE_CATEGORY_SPELL or DOTA_DAMAGE_CATEGORY_ATTACK +end + +--- Returns the victim unit name. +--- @return string # Victim unit name +function M:victim_name() + return self.victim.name +end + +--- Returns the attacker unit name if it exists. +--- @return string? # Attacker unit name +function M:attacker_name() + return self.attacker and self.attacker.name +end + +--- Returns the player owner of the attacker unit if it exists. +--- @return CDOTAPlayerController? # Attacker player owner +function M:attacker_player_owner() + return self.attacker and self.attacker.entity:GetPlayerOwner() +end + +--- Returns the inflictor ability name if it exists. +--- @return string? # Inflictor ability name +function M:inflictor_name() + return self.inflictor and self.inflictor.name +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/dummy_target.lua b/game/scripts/vscripts/invk/dota2/dummy_target.lua new file mode 100644 index 0000000..cd9c00e --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/dummy_target.lua @@ -0,0 +1,91 @@ +local class = require("middleclass") + +local UNITS = require("invk.const.units") +local Units = require("invk.dota2.units") +local tbl = require("invk.lang.table") + +--- DummyTarget class. +--- @class invk.dota2.DummyTarget : middleclass.Class +--- @field spawn_ent CBaseEntity? +--- @field entity CDOTA_BaseNPC? +local M = class("invk.dota2.DummyTarget") + +--- @class invk.dota2.DummyTargetOptions +--- @field spawn? boolean # Spawn dummy unit immediately (default: `true`) + +--- Constructor. +--- @param options? invk.dota2.DummyTargetOptions # Options table +function M:initialize(options) + self.spawn_ent = Entities:FindByName(nil, UNITS.DUMMY_TARGET_SPAWN) + + if not self.spawn_ent then + print("\n\nERROR: COULD NOT FIND DUMMY TARGET SPAWN LOCATION\n\n") + return + end + + --- @type invk.dota2.DummyTargetOptions + local opts = tbl.extend({ spawn = true }, options or {}) + + if opts.spawn then + self:spawn() + end +end + +--- Checks if dummy unit is alive. +--- @return boolean +function M:is_alive() + return self.entity ~= nil and not self.entity:IsNull() and self.entity:IsAlive() +end + +--- Checks if the dummy unit is dead. +--- @return boolean +function M:is_dead() + return not self:is_alive() +end + +--- Spawns the dummy unit. +function M:spawn() + if not self.spawn_ent then + print("\n\nERROR: COULD NOT FIND DUMMY TARGET SPAWN LOCATION\n\n") + return + end + + if self:is_alive() then + return + end + + local location = self.spawn_ent:GetAbsOrigin() + local unit = Units.create(UNITS.DUMMY_TARGET, { + location = location, + team = DOTA_TEAM_BADGUYS, + }) + + unit:SetIdleAcquire(false) + + self.entity = unit + + self:hold() +end + +--- Kills the dummy unit. +function M:kill() + if self.entity and self:is_alive() then + Units.destroy(self.entity) + end + + self.entity = nil +end + +--- Resets the dummy unit. +function M:reset() + self:kill() + self:spawn() +end + +function M:hold() + if self.entity then + self.entity:Hold() + end +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/game.lua b/game/scripts/vscripts/invk/dota2/game.lua new file mode 100644 index 0000000..199745c --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/game.lua @@ -0,0 +1 @@ +--- @alias invk.dota2.ClockFn (fun(): number) diff --git a/game/scripts/vscripts/invk/dota2/invoker.lua b/game/scripts/vscripts/invk/dota2/invoker.lua new file mode 100644 index 0000000..cc246cd --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/invoker.lua @@ -0,0 +1,199 @@ +local class = require("middleclass") + +local Ability = require("invk.dota2.ability") +local I = require("invk.const.invoker") +local tbl = require("invk.lang.table") + +--- @alias invk.dota2.invoker.AbilityName string + +--- @alias invk.dota2.invoker.OrbTriplet { +--- [1]: invk.dota2.invoker.AbilityName, +--- [2]: invk.dota2.invoker.AbilityName, +--- [3]: invk.dota2.invoker.AbilityName, +--- } + +--- Invoker class. +--- @class invk.dota2.Invoker : middleclass.Class +--- @field hero CDOTA_BaseNPC_Hero +local M = class("invk.dota2.Invoker") + +--- Constructor. +--- @param hero CDOTA_BaseNPC_Hero # Hero entity +function M:initialize(hero) + self.hero = hero +end + +--- @param ability1 invk.dota2.Ability +--- @param ability2 invk.dota2.Ability +function M:swap_abilities(ability1, ability2) + return self.hero:SwapAbilities( + ability1.name, + ability2.name, + ability2.index <= I.MAX_VISIBLE_ABILITY_INDEX, + ability1.index <= I.MAX_VISIBLE_ABILITY_INDEX + ) +end + +--- Invokes an ability by name. +--- @param ability_name invk.dota2.invoker.AbilityName Ability name +function M:invoke(ability_name) + local base_ability = self.hero:FindAbilityByName(ability_name) + + if not base_ability then + return + end + + local invoked = Ability:new(base_ability) + + -- I(i) : [i, s2], [s3, s4, s5] -> [i, s2], [s3, s4, s5] + if invoked.index == I.AbilityIndex.EMPTY1 then + return + end + + local base_spell1 = self.hero:GetAbilityByIndex(I.AbilityIndex.EMPTY1) + + if not base_spell1 then + return + end + + local spell1 = Ability:new(base_spell1) + + -- I(i) : [s1, i], [s2, s3, s4] -> [i, s1], [s2, s3, s4] + if invoked.index == I.AbilityIndex.EMPTY2 then + self:swap_abilities(spell1, invoked) + return + end + + local base_spell2 = self.hero:GetAbilityByIndex(I.AbilityIndex.EMPTY2) + + if not base_spell2 then + return + end + + local spell2 = Ability:new(base_spell2) + + -- I(i) : [s1, s2], [s3, s4, i] -> [s2, s1], [s3, s4, i] -> [i, s1], [s3, s4, s2] + self:swap_abilities(spell1, spell2) + self:swap_abilities(spell2, invoked) +end + +--- @param hero CDOTA_BaseNPC_Hero +--- @param ability CDOTABaseAbility +--- @param target_level integer +--- @return boolean +local function can_level_up_ability(hero, ability, target_level) + return (ability:CanAbilityBeUpgraded() == ABILITY_CAN_BE_UPGRADED) + and (hero:GetAbilityPoints() > 0) + and (ability:GetLevel() < target_level) +end + +--- Ability level up option. +--- +--- If no option is given, level up the ability 1 level. +--- @class invk.dota2.invoker.AbilityLevelUpOption +--- @field level? integer # Specific level +--- @field max_level? boolean # Level up to max ability level + +--- @class invk.dota2.invoker.LevelUpAbilitiesOptions +--- @field max_level? boolean # Level up abilities to max level (default: `false`) +--- @field [invk.dota2.invoker.AbilityName] invk.dota2.invoker.AbilityLevelUpOption? # Orb ability level up option + +--- Levels up orb abilities. +--- @param options? invk.dota2.invoker.LevelUpAbilitiesOptions +function M:level_up_abilities(options) + local opts = options or {} + + for _, name in ipairs(I.ORB_ABILITIES) do + if opts.max_level or opts[name] then + local ability = assertf(self.hero:FindAbilityByName(name), "could not find ability %q", name) + local ability_opt = opts[name] or {} + --- @type integer + local target_level + + if opts.max_level or ability_opt.max_level then + target_level = ability:GetMaxLevel() + elseif ability_opt.level then + target_level = ability_opt.level + else + target_level = ability:GetLevel() + 1 + end + + while can_level_up_ability(self.hero, ability, target_level) do + self.hero:UpgradeAbility(ability) + end + end + end +end + +--[[ + This is a hack. "AbilityValues" values for Invoker spells that depend on + orb ability level (specials that have "levelkey" set to "quaslevel", + "wexlevel" or "exortlevel") don't change when orb ability levels are + manually changed (with `CDOTABaseAbility:SetLevel`). Since we're resetting + orb levels to zero, this hack "resets" spell abilities by removing and + reinserting them on the hero. + + WARNING: when removing an ability, make sure they aren't visible (invoked), + otherwise the whole ability slot will disappear from the UI. +]] +--- @param hero CDOTA_BaseNPC_Hero +--- @param ability CDOTABaseAbility +local function reinsert_spell_ability(hero, ability) + local name = ability:GetAbilityName() + + if not ability:IsHidden() then + errorf("Tried to remove visible ability %q.", name) + end + + local index = ability:GetAbilityIndex() + local level = ability:GetLevel() + + hero:RemoveAbility(name) + + ability = hero:AddAbility(name) + ability:SetAbilityIndex(index) + ability:SetLevel(level) +end + +--- @class invk.dota2.invoker.ResetAbilitiesOptions +--- @field reinsert? bool Reinsert (reset) spell abilities (default: `false`) + +--- Resets orb abilities levels to zero. +--- +--- Reinsert option is a workaround to fix spells not scaling back (special values that +--- depend on orb levels). Another way to fix this is to completely replace the +--- player's hero with [PlayerResource:ReplaceHeroWith]. If hero replacement is +--- being used, this option is not needed. +--- @param options? invk.dota2.invoker.ResetAbilitiesOptions # Options table +--- @return integer # The number of ability points gained by downgrading orb abilities +function M:reset_abilities(options) + local opts = options or {} + local points = 0 + local reset_abilities = tbl.append(I.ORB_ABILITIES, I.TALENT_ABILITIES) + + for _, name in ipairs(reset_abilities) do + local ability = self.hero:FindAbilityByName(name) + + if ability ~= nil then + points = points + ability:GetLevel() + ability:SetLevel(0) + end + end + + if opts.reinsert then + self:invoke(I.AbilityName.EMPTY2) + self:invoke(I.AbilityName.EMPTY1) + + for _, name in ipairs(I.SPELL_ABILITIES) do + local ability = self.hero:FindAbilityByName(name) + + if ability then + reinsert_spell_ability(self.hero, ability) + end + end + end + + return points +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/kv.lua b/game/scripts/vscripts/invk/dota2/kv.lua new file mode 100644 index 0000000..cfac6a8 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/kv.lua @@ -0,0 +1,42 @@ +local inspect = require("inspect") + +--- @alias invk.dota2.KeyValues { [string]: invk.dota2.kv.Value } + +--- @alias invk.dota2.kv.Value +--- | number +--- | string +--- | invk.dota2.KeyValues + +--- KeyValue utils. +--- @class invk.dota2.kv +local M = {} + +--- KeyValue value type. +--- @enum invk.dota2.kv.Type +M.Type = { + Number = "number", + String = "string", + KeyValues = "kv", +} + +--- @param ty invk.dota2.kv.Type +--- @param value invk.dota2.kv.Value +--- @return invk.dota2.kv.Value +function M.require_type(ty, value) + local lua_ty = type(value) + local message = F("expected KeyValues type %q for value %s", ty, inspect(value)) + + if ty == M.Type.Number then + assert(lua_ty == "number", message) + elseif ty == M.Type.String then + assert(lua_ty == "string", message) + elseif ty == M.Type.KeyValues then + assert(lua_ty == "table", message) + else + errorf("invalid KeyValues type %q", ty) + end + + return value +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua new file mode 100644 index 0000000..e83aa89 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua @@ -0,0 +1,20 @@ +local class = require("middleclass") + +local KeyValues = require("invk.dota2.kv.key_values") + +--- AbilityKeyValues class. +--- @class invk.dota2.kv.AbilityKeyValues : middleclass.Class, invk.dota2.kv.KeyValues +--- @field name string +--- @field kv invk.dota2.KeyValues +local M = class("invk.dota2.kv.AbilityKeyValues", KeyValues) + +--- Constructor. +--- @param name string # Ability name +--- @param data invk.dota2.KeyValues # KeyValues data +function M:initialize(name, data) + KeyValues.initialize(self, data) + + self.name = name +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua new file mode 100644 index 0000000..42e005c --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua @@ -0,0 +1,88 @@ +local class = require("middleclass") + +local AbilityKeyValues = require("invk.dota2.kv.ability_key_values") +local KeyValues = require("invk.dota2.kv.key_values") +local talents = require("invk.dota2.talents") +local tbl = require("invk.lang.table") + +local KV_HEROES_PATH = "scripts/npc/npc_heroes.txt" +local KV_ABILITIES_PATH_PATT = "scripts/npc/heroes/%s.txt" +local ABILITY_KEY_PATT = "^Ability(%d+)$" + +--- @param value invk.dota2.kv.Value +--- @param key string +--- @return integer?, string? +local function parse_ability_entry(value, key) + if type(value) ~= "string" or value == "" then + return nil + end + + local m_ability_id = key:match(ABILITY_KEY_PATT) + + if m_ability_id == nil then + return nil + end + + local ability_id = tonumber(m_ability_id) + + if ability_id == nil then + return nil + end + + --- @cast ability_id integer + return ability_id, value +end + +--- HeroKeyValues class. +--- @class invk.dota2.kv.HeroKeyValues : middleclass.Class, invk.dota2.kv.KeyValues +--- @field name string +--- @field abilities { [invk.dota2.invoker.AbilityName]: invk.dota2.kv.AbilityKeyValues } +--- @field talents invk.dota2.talents.Map +--- @field load fun(class: invk.dota2.kv.HeroKeyValues, name: string): invk.dota2.kv.HeroKeyValues +local M = class("invk.dota2.kv.HeroKeyValues", KeyValues) + +--- @param name string # Hero unit name +--- @return invk.dota2.kv.HeroKeyValues +function M.static:load(name) + local heroes = KeyValues:load(KV_HEROES_PATH) + local hero = heroes:require_kv(name) + + local abilities_path = F(KV_ABILITIES_PATH_PATT, name) + local abilities = KeyValues:load(abilities_path) + + return self:new(name, hero.data, abilities) +end + +--- Constructor. +--- @param name string # Hero unit name +--- @param hero invk.dota2.KeyValues # Hero KeyValues data +--- @param abilities invk.dota2.kv.KeyValues # Abilities KeyValues data +function M:initialize(name, hero, abilities) + KeyValues.initialize(self, hero) + + self.name = name + self.abilities = {} + + --- @type invk.dota2.invoker.AbilityName[] + local abilities_names = tbl.map(self.data, parse_ability_entry) + local talents_start = self:require_integer("AbilityTalentStart") + local regular_abilities = tbl.slice(abilities_names, 1, talents_start - 1) + local talent_abilities = tbl.slice(abilities_names, talents_start) + + for _, ability_name in ipairs(regular_abilities) do + local ability = abilities:require_kv(ability_name) + + self.abilities[ability_name] = AbilityKeyValues:new(ability_name, ability.data) + end + + self.talents = talents.names_array_to_enums_table(talent_abilities) +end + +--- @return invk.dota2.KeyValues +function M:abilities_data() + return tbl.map(self.abilities, function(kv) + return kv.data + end) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua new file mode 100644 index 0000000..04750d6 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua @@ -0,0 +1,40 @@ +local class = require("middleclass") + +local KeyValues = require("invk.dota2.kv.key_values") +local tbl = require("invk.lang.table") + +--- ItemKeyValues class. +--- @class invk.dota2.kv.ItemKeyValues : middleclass.Class, invk.dota2.kv.KeyValues +--- @field name string +--- @field shop_tags string[] +local M = class("invk.dota2.kv.ItemKeyValues", KeyValues) + +--- Constructor. +--- @param name string # Item name +--- @param data invk.dota2.KeyValues # KeyValues data +function M:initialize(name, data) + KeyValues.initialize(self, data) + + self.name = name + self.shop_tags = self:get_strings("ItemShopTags", ";") +end + +--- Checks if the item matches the given search query. +--- +--- It searches for matches in these entries: +--- +--- * `ItemShopTags` +--- +--- @param query string # Query string +--- @return boolean +function M:matches_query(query) + --- @param s string + --- @return boolean + local function matcher(s) + return s:match(query) ~= nil + end + + return matcher(self.name) or (tbl.index(self.shop_tags, matcher) ~= nil) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua new file mode 100644 index 0000000..4b36eea --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua @@ -0,0 +1,53 @@ +local class = require("middleclass") + +local ItemKeyValues = require("invk.dota2.kv.item_key_values") +local KeyValues = require("invk.dota2.kv.key_values") +local tbl = require("invk.lang.table") + +local KV_PATH = "scripts/npc/items.txt" +local ITEM_KEY_PATT = "^item_" + +--- @param value invk.dota2.kv.Value +--- @param key string +--- @return invk.dota2.kv.ItemKeyValues? +local function parse_item_entry(value, key) + if key:match(ITEM_KEY_PATT) and type(value) == "table" then + return ItemKeyValues:new(key, value) + else + return nil + end +end + +--- Collection of [invk.dota2.kv.ItemKeyValues]. +--- @class invk.dota2.kv.ItemsKeyValues : middleclass.Class +--- @field data { [string]: invk.dota2.kv.ItemKeyValues } +--- @field load fun(): invk.dota2.kv.ItemsKeyValues +local M = class("invk.dota2.kv.ItemsKeyValues") + +--- @return invk.dota2.kv.ItemsKeyValues +function M.static:load() + local items = KeyValues:load(KV_PATH) + + return self:new(items.data) +end + +--- Constructor. +--- @param data invk.dota2.KeyValues # KeyValues data +function M:initialize(data) + self.data = tbl.map(data, parse_item_entry) +end + +--- Searches for item KeyValues matching the given query. +--- @param query string # Query string +--- @return invk.dota2.KeyValues # A table of found entries +function M:search(query) + return tbl.map(self.data, function(item) + if item:MatchesQuery(query) then + return item.data + else + return nil + end + end) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/kv/key_values.lua b/game/scripts/vscripts/invk/dota2/kv/key_values.lua new file mode 100644 index 0000000..5b8400a --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/kv/key_values.lua @@ -0,0 +1,126 @@ +local class = require("middleclass") + +local kv = require("invk.dota2.kv") +local str = require("invk.lang.string") +local tbl = require("invk.lang.table") + +--- @class invk.dota2.kv.KeyValues : middleclass.Class +--- @field data invk.dota2.KeyValues +--- @field load fun(class: invk.dota2.kv.KeyValues, path: string): invk.dota2.kv.KeyValues +local M = class("invk.dota2.kv.KeyValuesBase") + +--- @param path string # KeyValues file path +--- @return invk.dota2.kv.KeyValues +function M.static:load(path) + return self:new(LoadKeyValues(path)) +end + +--- @param data invk.dota2.KeyValues +function M:initialize(data) + self.data = data +end + +--- @generic T +--- @param key string +--- @param ty invk.dota2.kv.Type +--- @param default? T +--- @return T? +function M:get(key, ty, default) + local value = self.data[key] + + if value == nil then + return default + end + + return kv.require_type(ty, value) +end + +--- @generic T +--- @param key string +--- @param ty invk.dota2.kv.Type +--- @return T +function M:require(key, ty) + local value = self:get(key, ty) + + return assertf(value, "KeyValues key %q not found", key) +end + +--- @param key string +--- @param default? string +--- @return string? +function M:get_string(key, default) + return self:get(key, kv.Type.String, default) +end + +--- @param key string +--- @param default? number +--- @return number? +function M:get_number(key, default) + return self:get(key, kv.Type.Number, default) +end + +--- @param key string +--- @param default? integer +--- @return integer? +function M:get_integer(key, default) + return self:get_number(key, default) --[[@as integer?]] +end + +--- @param key string +--- @param default? invk.dota2.KeyValues +--- @return invk.dota2.kv.KeyValues? +function M:get_kv(key, default) + local data = self:get(key, kv.Type.KeyValues, default) + + if data == nil then + return nil + end + + return M:new(data) +end + +--- @param key string +--- @return string +function M:require_string(key) + return self:require(key, kv.Type.String) +end + +--- @param key string +--- @return number +function M:require_number(key) + return self:require(key, kv.Type.Number) +end + +--- @param key string +--- @return integer +function M:require_integer(key) + return self:require_number(key) --[[@as integer]] +end + +--- @param key string +--- @return invk.dota2.kv.KeyValues +function M:require_kv(key) + local data = self:require(key, kv.Type.KeyValues) + + return M:new(data) +end + +--- Splits a value into an array of strings. +--- @param key string +--- @param sep string +--- @return string[] +function M:get_strings(key, sep) + local s = self:get_string(key) + + if not s then + return {} + end + + local strings = str.split(s, sep) + + strings = tbl.map(strings, str.trim) + + return strings +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/net_table.lua b/game/scripts/vscripts/invk/dota2/net_table.lua new file mode 100644 index 0000000..8d26288 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/net_table.lua @@ -0,0 +1,63 @@ +local class = require("middleclass") + +local Logger = require("invk.logger") + +--- @class invk.net_table.Config +--- @field name invk.net_table.Name +--- @field keys { [string]: string } + +--- NetTable class. +--- @class invk.dota2.NetTable : middleclass.Class, invk.log.Mixin +--- @field name invk.net_table.Name +--- @field keys { [string]: string } +--- @field logger invk.Logger? +local M = class("invk.dota2.NetTable") + +M:include(Logger.Mixin) + +--- @class invk.dota2.NetTableOptions +--- @field logger? invk.Logger + +--- Constructor. +--- @param config invk.net_table.Config # Net table config +--- @param options? invk.dota2.NetTableOptions +function M:initialize(config, options) + local opts = options or {} + + self.name = config.name + self.keys = config.keys + + if opts.logger then + self.logger = opts.logger:child(F("net_table.%s", self.name)) + end +end + +--- Sets a net table value. +--- @param key string # Key +--- @param value any # Value +--- @return boolean # Setting success +function M:set(key, value) + local ok = CustomNetTables:SetTableValue(self.name, key, value) + + self:debugf("set %q (%s): %s", key, type(value), ok) + + return ok +end + +--- Gets a net table value. +--- @param key string # Key +--- @param default? any # Default value in case the net table value is `nil` (default: `nil`) +--- @return any # Value of `key` if it exists, `defaultValue` otherwise +function M:get(key, default) + local value = CustomNetTables:GetTableValue(self.name, key) + + self:debugf("get %q (%s)", key, type(value)) + + if value == nil then + return default + end + + return value +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/player.lua b/game/scripts/vscripts/invk/dota2/player.lua new file mode 100644 index 0000000..a746ce7 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/player.lua @@ -0,0 +1,80 @@ +local class = require("middleclass") + +local val = require("invk.lang.value") + +--- Player class. +--- @class invk.dota2.Player : middleclass.Class +--- @field entity CDOTAPlayerController # player entity +--- @field id integer # player id +--- @field account_id integer # player's 32-bit account id +--- @field steam_id Uint64 # player's 64-bit steam id +--- @field hero CDOTA_BaseNPC_Hero # player's assigned hero entity +local M = class("invk.dota2.Player") + +--- Constructor. +--- @param entity CDOTAPlayerController # Player entity +function M:initialize(entity) + self.entity = entity + self.id = self.entity:GetPlayerID() + self.account_id = PlayerResource:GetSteamAccountID(self.id) + self.steam_id = PlayerResource:GetSteamID(self.id) + self.hero = self.entity:GetAssignedHero() +end + +--- @class invk.dota2.player.ReplaceHeroOptions +--- @field gold? integer # New hero starting gold (default: `0`) +--- @field xp? integer # New hero starting experience (default: `0`) +--- @field remove? boolean # Remove old hero entity. Not removing the entity will make it linger +--- under the player's ownership and control (default: `true`) + +--- Replaces the player's hero with a new one. +--- +--- After replacing the hero, this Player instance's `hero` attribute will +--- reference the new entity. +--- @param hero_name string # Hero unit name +--- @param options? invk.dota2.player.ReplaceHeroOptions # Options table +--- @return CDOTA_BaseNPC_Hero # New hero entity +function M:replace_hero(hero_name, options) + local opts = options or {} + local old_hero = self.hero + local gold = opts.gold or 0 + local xp = opts.xp or 0 + local remove = val.non_nil(opts.remove, true) + + self.hero = PlayerResource:ReplaceHeroWith(self.id, hero_name, gold, xp) + + if remove then + old_hero:RemoveSelf() + end + + return self.hero +end + +--- Remove the player's owned units with given name. +--- @param unit_name string # Unit name +--- @return integer # The number of units removed +function M:remove_owned_units_by_name(unit_name) + local to_remove = {} + local ent = Entities:FindByName(nil, unit_name) + + while ent ~= nil do + --- @cast ent CDOTA_BaseNPC + if type(ent.GetPlayerOwner) == "function" then + local owner = ent:GetPlayerOwner() + + if owner:GetPlayerID() == self.id then + table.insert(to_remove, ent) + end + end + + ent = Entities:FindByName(ent, unit_name) + end + + for _, ent_to_remove in ipairs(to_remove) do + ent_to_remove:RemoveSelf() + end + + return #to_remove +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/sound_events.lua b/game/scripts/vscripts/invk/dota2/sound_events.lua new file mode 100644 index 0000000..8dd8a47 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/sound_events.lua @@ -0,0 +1,69 @@ +--- Sound events helpers. +--- @class invk.dota2.sound_events +local M = {} + +--- Play named sound for all players. +--- @param event string +function M.emit_global(event) + EmitGlobalSound(event) +end + +--- Play named sound only on the client for the passed in player. +--- @param event string +--- @param player CDOTAPlayerController +function M.emit_on_player(event, player) + EmitSoundOnClient(event, player) +end + +--- Play named sound on entity. +--- @param event string +--- @param entity CBaseEntity +function M.emit_on_entity(event, entity) + EmitSoundOn(event, entity) +end + +--- Emit a sound on a location from a unit. +--- @param event string +--- @param entity CBaseEntity +--- @param location Vector +function M.emit_on_location_with_caster(event, entity, location) + EmitSoundOnLocationWithCaster(location, event, entity) +end + +--- Emit a sound on a location from a unit, only for players allied with that unit. +--- @param event string +--- @param entity CBaseEntity +--- @param location Vector +function M.emit_on_location_for_allies(event, entity, location) + EmitSoundOnLocationForAllies(location, event, entity) +end + +--- Emit an announcer sound for all players. +--- @param event string +function M.emit_announcer(event) + EmitAnnouncerSound(event) +end + +--- Emit an announcer sound for a player. +--- @param event string +--- @param player CDOTAPlayerController +function M.emit_announcer_for_player(event, player) + EmitAnnouncerSoundForPlayer(event, player:GetPlayerID()) +end + +--- Emit an announcer sound for a team. +--- @param event string +--- @param team DOTATeam_t +function M.emit_announcer_for_team(event, team) + EmitAnnouncerSoundForTeam(event, team) +end + +--- Emit an announcer sound for a team at a specific location. +--- @param event string +--- @param team DOTATeam_t +--- @param location Vector +function M.emit_announcer_on_location_for_team(event, team, location) + EmitAnnouncerSoundForTeamOnLocation(event, team, location) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/talents.lua b/game/scripts/vscripts/invk/dota2/talents.lua new file mode 100644 index 0000000..1ba129a --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/talents.lua @@ -0,0 +1,103 @@ +local tbl = require("invk.lang.table") + +--- Talents helpers. +--- @class invk.dota2.talents +local M = {} + +--- @alias invk.dota2.talents.Level +--- | 10 +--- | 15 +--- | 20 +--- | 25 + +--- @enum invk.dota2.talents.Side +M.Side = { + LEFT = "left", + RIGHT = "right", +} + +--- @alias invk.dota2.talents.LevelSide { +--- [1]: invk.dota2.talents.Level, +--- [2]: invk.dota2.talents.Side, +--- } + +--- @enum invk.dota2.Talents +M.Talents = { + --- No talents selected + NONE = 0x00, + --- Level 10 right talent + L10_RIGHT = 0x01, + --- Level 10 left talent + L10_LEFT = 0x02, + --- Level 15 right talent + L15_RIGHT = 0x04, + --- Level 15 left talent + L15_LEFT = 0x08, + --- Level 20 right talent + L20_RIGHT = 0x10, + --- Level 20 left talent + L20_LEFT = 0x20, + --- Level 25 right talent + L25_RIGHT = 0x40, + --- Level 25 left talent + L25_LEFT = 0x80, +} + +--- @type invk.dota2.Talents[] +local LIST = { + M.Talents.L10_RIGHT, + M.Talents.L10_LEFT, + M.Talents.L15_RIGHT, + M.Talents.L15_LEFT, + M.Talents.L20_RIGHT, + M.Talents.L20_LEFT, + M.Talents.L25_RIGHT, + M.Talents.L25_LEFT, +} + +--- @type { [invk.dota2.Talents]: invk.dota2.talents.LevelSide } +local LEVEL_SIDE = { + [M.Talents.L10_RIGHT] = { 10, M.Side.RIGHT }, + [M.Talents.L10_LEFT] = { 10, M.Side.LEFT }, + [M.Talents.L15_RIGHT] = { 15, M.Side.RIGHT }, + [M.Talents.L15_LEFT] = { 15, M.Side.LEFT }, + [M.Talents.L20_RIGHT] = { 20, M.Side.RIGHT }, + [M.Talents.L20_LEFT] = { 20, M.Side.LEFT }, + [M.Talents.L25_RIGHT] = { 25, M.Side.RIGHT }, + [M.Talents.L25_LEFT] = { 25, M.Side.LEFT }, +} + +--- Returns the bitwise OR'ed values +--- @param ... invk.dota2.Talents +--- @return invk.dota2.Talents +function M.select(...) + return bit.bor(...) +end + +--- Map of talent enums and talent ability names +--- @alias invk.dota2.talents.Map { [invk.dota2.Talents]: string } + +--- Maps an array of ability names to a map of talents enums and talent ability names +--- @param names string[] +--- @return invk.dota2.talents.Map +function M.names_array_to_enums_table(names) + assertf( + #names <= #LIST, + "names length should be equal or less than talents LIST length. expected: %d <= %d", + #names, + #LIST + ) + + return tbl.transform(names, function(name, i) + return LIST[i], name + end) +end + +--- Converts an enum value into level and side values. +--- @param value invk.dota2.Talents +--- @return invk.dota2.talents.LevelSide? # Level and Side tuple if value is valid, `nil` otherwise +function M.level_and_side(value) + return LEVEL_SIDE[value] +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/timers.lua b/game/scripts/vscripts/invk/dota2/timers.lua new file mode 100644 index 0000000..87ea59f --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/timers.lua @@ -0,0 +1,272 @@ +--- Timers framework. +--- +--- Original code: [https://github.com/bmddota/barebones](https://github.com/bmddota/barebones) +--- +--- @author bmddota (original author) +--- @author 13k (updates) +--- @license Apache License 2.0 +--- @copyright bmddota + +local class = require("middleclass") + +local val = require("invk.lang.value") + +--- @class invk.dota2.timers +--- @field timers { [string]: invk.dota2.Timer } +local M = { _VERSION = "1.06" } + +local THINK_NAME = "timers" +local THINK_INTERVAL = 0.01 + +local ERRF_INVALID_TIMER_ID = "Invalid timer id: %s [%s]" +local ERRF_INVALID_TIMER_CALLBACK = "Invalid timer %q: callback must be a function" +local ERRF_INVALID_TIMER_ALREADY_REGISTERED = "Invalid timer %q: already registered" + +--- Default error handler. +--- @param msg string # Error message +--- @return string # Error message and stack trace. +function M.default_error_handler(msg) + return msg .. "\n" .. debug.traceback() .. "\n" +end + +local function unique_id() + return DoUniqueString("timer") +end + +local function handle_error(timer, err) + print("[ERROR] Timer " .. timer.id .. ":") + print(err) +end + +--- @class invk.dota2.Timer : middleclass.Class +--- @field id string +--- @field callback (fun(...): any...) +--- @field args any[] +--- @field realtime boolean +--- @field delay number +--- @field paused boolean +--- @field at number +--- @field onError (fun(err: string): string) +--- @field private callback_wrapper (fun(): any...) +local Timer = class("Timer") + +--- @class invk.dota2.TimerOptions +--- @field callback (fun(...): any...) # Timer function +--- @field id? string # Timer id +--- @field args? any[] # List of arguments to pass to the callback +--- @field at? number # Specific start time (timestamp in seconds). `nil`, `0` or negative number means it starts immediately +--- @field delay? number # Delay start time (in seconds). `nil`, `0` or negative number means it starts immediately +--- @field realtime? boolean # If `true`, uses real clock (ignores pauses) (default: `false`) +--- @field paused? boolean # If `true`, the timer starts paused and must be manually unpaused with [Unpause] (default: `false`) +--- @field onError? fun(err: string): string # Error handler function. If `nil`, uses [default_error_handler] (default: `nil`) + +--- @param options invk.dota2.TimerOptions +function Timer:initialize(options) + self.id = options.id or unique_id() + self.callback = options.callback + self.args = options.args or {} + self.realtime = val.non_nil(options.realtime, false) + self.delay = options.delay or 0 + self.onError = options.onError or M.default_error_handler + self.paused = val.non_nil(options.paused, false) + self.at = (options.at or self:now()) + self.delay + + assertf(type(self.id) == "string", ERRF_INVALID_TIMER_ID, self.id, type(self.id)) + assertf(type(self.callback) == "function", ERRF_INVALID_TIMER_CALLBACK, self.id) + + self.callback_wrapper = function() + return self.callback(unpack(self.args)) + end +end + +--- @private +function Timer:now() + return self.realtime and Time() or GameRules:GetGameTime() +end + +--- @private +function M:think() + for _, timer in pairs(self.timers) do + self:process_timer(timer) + end + + return self.interval +end + +--- @private +function M:process_timer(timer) + if timer.paused then + return + end + + if timer.at > timer:now() then + return + end + + local removeTimer = true + local success, result = xpcall(timer.callbackWrapper, timer.onError) + + if not success then + handle_error(timer, result) + elseif type(result) == "number" then + timer.at = timer.at + result + removeTimer = false + end + + if removeTimer then + self.timers[timer.id] = nil + end +end + +--- Initializes timers. +--- +--- Should be placed inside the custom game's `Activate` function. +--- +--- @param interval? number # Timer processing interval (default: `0.01`) +function M:start(interval) + self.interval = interval or THINK_INTERVAL + self.timers = {} + + GameRules:GetGameModeEntity():SetThink("think", self, THINK_NAME, self.interval) +end + +--- Creates a timer with the given options. +--- +--- ```lua +--- -- Immediately calls `obj.fn(obj, 13)` (equivalent to `obj:fn(13)`), +--- -- if `fn` returns a number, repeats at that interval +--- Create({callback = obj.fn, args = {obj, 13}}) +--- +--- -- 10 seconds delayed, run once using game time (respect pauses) +--- Create({ +--- delay = 10.0, +--- callback = function() +--- print("Hello. I'm running 10 seconds after when I was started.") +--- end +--- }) +--- +--- -- 10 second delayed, run once regardless of pauses +--- Create({ +--- delay = 10.0, +--- realtime = true, +--- callback = function() +--- print("Hello. I'm running 10 seconds after I was started even if someone paused the game.") +--- end +--- }) +--- +--- -- At a specific time, run once using game time (respect pauses) +--- Create({ +--- at = GameRules:GetGameTime() + 10.0, +--- callback = function() +--- print("Hello. I'm running when I was scheduled to run.") +--- end +--- }) +--- +--- -- At a specific time, run once using real time (regardless of pauses) +--- Create({ +--- at = Time() + 10.0, +--- realtime = true, +--- callback = function() +--- print("Hello. I'm running when I was scheduled to run, even if someone paused the game.") +--- end +--- }) +--- +--- -- At a specific time, 10 second delay from that time, run once using game time (respect pauses) +--- Create({ +--- at = GameRules:GetGameTime() + 30.0, +--- delay = 10.0, +--- callback = function() +--- print("Hello. I'm running 10 seconds after when I was scheduled to run.") +--- end +--- }) +--- +--- -- A timer running every second that starts 5 seconds in the future. +--- -- Uses game time, respecting pauses. +--- Create({ +--- delay = 5.0, +--- callback = function() +--- print("Hello. I'm running 5 seconds after you called me and then every second thereafter.") +--- return 1.0 +--- end +--- }) +--- +--- -- A timer running every second that starts after 2 minutes regardless of pauses +--- Create({ +--- id = "uniqueTimerId", +--- delay = 120.0, +--- realtime = true, +--- callback = function() +--- print("Hello. I'm running after 2 minutes and then every second thereafter.") +--- return 1.0 +--- end +--- }) +--- ``` +--- @param options invk.dota2.TimerOptions +--- @return string # Timer ID +function M:create(options) + if options.id then + assertf(self.timers[options.id] == nil, ERRF_INVALID_TIMER_ALREADY_REGISTERED, options.id) + end + + local timer = Timer:new(options) + + self.timers[timer.id] = timer + + return timer.id +end + +--- @private +--- @param id string +--- @param value boolean +--- @return string? +function M:set_paused(id, value) + local timer = self.timers[id] + + if timer == nil then + return nil + end + + timer.paused = value + + return id +end + +--- Pauses a timer. +--- @param id string # Timer id +--- @return string? # Id of paused timer or `nil` if the id isn't registered +function M:pause(id) + return self:set_paused(id, true) +end + +--- Unpauses a timer. +--- @param id string # Timer id +--- @return string? # Id of paused timer or `nil` if the id isn't registered +function M:unpause(id) + return self:set_paused(id, false) +end + +--- Cancels a timer. +--- @param id string # Timer id +--- @return string? # Id of canceled timer or `nil` if the id isn't registered +function M:cancel(id) + local timer = self.timers[id] + + self.timers[id] = nil + + return timer and id +end + +--- Cancels all timers. +--- @return string[] # Array of timer ids that were canceled +function M:cancel_all() + local canceled = {} + + for id, _ in pairs(self.timers) do + self.timers[id] = nil + canceled[#canceled + 1] = id + end + + return canceled +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/unit.lua b/game/scripts/vscripts/invk/dota2/unit.lua new file mode 100644 index 0000000..afacdb2 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/unit.lua @@ -0,0 +1,355 @@ +local class = require("middleclass") + +local INVENTORY = require("invk.const.inventory") +local LIMITS = require("invk.const.limits") +local tbl = require("invk.lang.table") +local val = require("invk.lang.value") + +--- Unit class. +--- @class invk.dota2.Unit : middleclass.Class +--- @field entity CDOTA_BaseNPC +--- @field name string +--- @field is_hero boolean +local M = class("invk.dota2.Unit") + +local ERRF_UNIT_NO_INVENTORY = "Unit '%s' does not have an inventory" +local ERRF_UNIT_CANNOT_RESPAWN = "Unit '%s' cannot respawn" + +--- Constructor. +--- @param entity CDOTA_BaseNPC # Unit entity +function M:initialize(entity) + self.entity = entity + self.name = self.entity:GetUnitName() + self.is_hero = self.entity:IsHero() +end + +--- @return CDOTA_BaseNPC_Hero +function M:require_hero() + assert(self.is_hero, "expected hero unit") + + --- @cast self.entity CDOTA_BaseNPC_Hero + return self.entity +end + +--- @class invk.dota2.unit.RespawnOptions +--- @field buyback? boolean # Is buyback respawn? (default: `false`) +--- @field penalty? boolean # Apply respawn penalty? (default: `false`) + +--- Respawns the unit. +--- +--- If the unit is a hero, uses [CDOTA_BaseNPC_Hero:RespawnHero] with given +--- options, otherwise uses [CDOTA_BaseNPC:RespawnUnit]. +--- @param options? invk.dota2.unit.RespawnOptions # Options table (default: `{}`) +function M:respawn(options) + if not self.entity:UnitCanRespawn() then + errorf(ERRF_UNIT_CANNOT_RESPAWN, self.name) + end + + local opts = options or {} + local buyback = val.non_nil(opts.buyback, false) + local penalty = val.non_nil(opts.penalty, false) + + if self.is_hero then + --- @cast self.entity CDOTA_BaseNPC_Hero + return self.entity:RespawnHero(buyback, penalty) + end + + return self.entity:RespawnUnit() +end + +--- @class invk.dota2.unit.PurgeOptions +--- @field buffs? boolean # Remove positive buffs (default: `true`) +--- @field debuffs? boolean # Remove negative buffs (default: `true`) +--- @field stuns? boolean # Remove stuns (default: `true`) +--- @field exceptions? boolean # Remove exceptions (default: `true`) +--- @field frame_only? boolean # Remove buffs created this frame only (default: `false`) + +--- Purges the unit. +--- @param options? invk.dota2.unit.PurgeOptions # Options table (default: `{}`) +function M:purge(options) + local opts = options or {} + local buffs = val.non_nil(opts.buffs, true) + local debuffs = val.non_nil(opts.debuffs, true) + local stuns = val.non_nil(opts.stuns, true) + local exceptions = val.non_nil(opts.exceptions, true) + local frame_only = val.non_nil(opts.frame_only, false) + + return self.entity:Purge(buffs, debuffs, frame_only, stuns, exceptions) +end + +--- @class invk.dota.unit.HeroLevelUpOptions +--- @field play_effects? boolean # Play level up effects (default: `false`) + +--- Levels up the hero unit. +--- @param level integer # Target level (if current level is higher, does nothing) +--- @param options? invk.dota.unit.HeroLevelUpOptions # Options table (default: `{}`) +function M:hero_level_up_to(level, options) + local hero = self:require_hero() + local opts = options or {} + local play_effects = val.non_nil(opts.play_effects, false) + + if level > LIMITS.MAX_HERO_LEVEL then + level = LIMITS.MAX_HERO_LEVEL + end + + while hero:GetLevel() < level do + hero:HeroLevelUp(play_effects) + end +end + +--- Heals the unit to the maximum health. +--- @param heal_source? CBaseEntity # Heal source entity +function M:give_max_health(heal_source) + return self.entity:Heal(self.entity:GetMaxHealth(), heal_source) +end + +--- Gives the unit maximum mana. +function M:give_max_mana() + return self.entity:GiveMana(self.entity:GetMaxMana()) +end + +--- @class invk.dota2.unit.GiveGoldOptions +--- @field reliable? boolean # Is this gold reliable? (default: `true`) +--- @field reason? EDOTA_ModifyGold_Reason # Reason flags (default: `DOTA_ModifyGold_Unspecified`) + +--- Gives the hero unit a gold amount. +--- @param amount integer # Gold amount (can be negative) +--- @param options? invk.dota2.unit.GiveGoldOptions # Options table +function M:give_gold(amount, options) + local hero = self:require_hero() + local opts = options or {} + local reliable = val.non_nil(opts.reliable, true) + local reason = val.non_nil(opts.reason, DOTA_ModifyGold_Unspecified) + + return hero:ModifyGold(amount, reliable, reason) +end + +--- @class invk.dota2.unit.ForEachItemOptions +--- @field sections? invk.dota2.inventory.Section[] # Array of inventory sections to scan (default: `{}`) + +--- Iterates over the unit's inventory, yielding each non-nil item. +--- @param f (fun(item: CDOTA_Item): (boolean?, any...)) # Iterator function +--- @param options? invk.dota2.unit.ForEachItemOptions # Options table (default: `{}`) +--- @return any... +function M:for_each_item(f, options) + if not self.entity:HasInventory() then + errorf(ERRF_UNIT_NO_INVENTORY, self.name) + end + + local opts = options or {} + --- @type invk.dota2.inventory.Section[] + local sections = opts.sections or INVENTORY.ALL_SECTIONS + --- @type DOTAScriptInventorySlot_t[] + local slots = {} + + for _, section in ipairs(sections) do + slots = tbl.append(slots, INVENTORY.SECTION_SLOTS[section]) + end + + for _, slot in ipairs(slots) do + local item = self.entity:GetItemInSlot(slot) + + if item then + local ret = { f(item) } + local continue = true + + if ret[1] ~= nil then + continue = ret[1] + table.remove(ret, 1) + end + + if not continue then + return unpack(ret) + end + end + end + + return nil +end + +--- @class invk.dota2.unit.ItemNamesOptions : invk.dota2.unit.ForEachItemOptions +--- @field sort? boolean # Sorts the resulting array. (default: `false`) + +--- Returns an array of names of all items in the unit's inventory. +--- @param options? invk.dota2.unit.ItemNamesOptions # Accepts the same options as @{ForEachItem} (default: `{}`) +--- @return string[] # Array of item names +function M:item_names(options) + local names = {} + local opts = options or {} + + self:for_each_item(function(item) + names[#names + 1] = item:GetAbilityName() + end, opts) + + if opts.sort then + table.sort(names) + end + + return names +end + +--- @class invk.dota2.unit.AddItemsByNameOptions +--- @field only_missing? boolean # Only add missing items (the diff between the inventory and the array) (default: `false`) + +--- Add items with given names. +--- @param items string[] # Array of item names +--- @param options? invk.dota2.unit.AddItemsByNameOptions # Options table (default: `{}`) +--- @return CDOTA_Item[] # Array of added item entities +function M:add_items_by_name(items, options) + if not self.entity:HasInventory() then + errorf(ERRF_UNIT_NO_INVENTORY, self.name) + end + + local opts = options or {} + + if opts.only_missing then + items = tbl.diff(items, self:item_names()) + end + + return tbl.map(items, function(name) + return self.entity:AddItemByName(name) + end) +end + +--- Finds item by name in inventory. +--- @param name string # Item name +--- @param options? invk.dota2.unit.ForEachItemOptions +--- @return CDOTA_Item? # Item if found, `nil` otherwise +function M:find_item_in_inventory(name, options) + return self:for_each_item(function(item) + if item:GetAbilityName() == name then + return false, item + end + end, options) +end + +--- @class invk.dota2.unit.RemoveItemsOptions : invk.dota2.unit.ForEachItemOptions +--- @field endCooldown? boolean # Reset item cooldowns before removing (default: `false`) + +--- Removes all items. +--- @param options? invk.dota2.unit.RemoveItemsOptions +--- @return CDOTA_Item[] # An array of removed items +function M:remove_items(options) + local opts = options or {} + --- @type CDOTA_Item[] + local removed = {} + + self:for_each_item(function(item) + if opts.endCooldown then + item:EndCooldown() + end + + self.entity:RemoveItem(item) + + removed[#removed + 1] = item + end, opts) + + return removed +end + +--- Clears all items cooldowns. +--- @param options? invk.dota2.unit.ForEachItemOptions +function M:end_item_cooldowns(options) + self:for_each_item(function(item) + item:EndCooldown() + end, options) +end + +--- Removes all dropped items owned by this unit. +--- @return CDOTA_Item[] # An array of removed items +function M:remove_dropped_items() + --- @type CDOTA_Item[] + local removed = {} + + for i = 0, GameRules:NumDroppedItems() - 1 do + local ent = GameRules:GetDroppedItem(i) + + if ent then + ---- @type CDOTA_Item + -- local item = EntityFramework:CreateEntity("CDOTA_Item", ent) + local item = EntIndexToHScript(ent:GetEntityIndex()) --[[@as CDOTA_Item]] + local purchaser = item:GetPurchaser() + local ent_idx = purchaser and purchaser:GetEntityIndex() + + if ent_idx == self.entity:GetEntityIndex() then + item:RemoveSelf() + + removed[#removed + 1] = item + end + end + end + + return removed +end + +--- Finds ability or item by name. +--- @param name string # Ability or item name +--- @return invk.dota2.AbilityOrItem? # Ability or item entity if found +function M:find_ability_or_item(name) + if self.entity:HasAbility(name) then + return self.entity:FindAbilityByName(name) + end + + if self.entity:HasInventory() and self.entity:HasItemInInventory(name) then + return self:find_item_in_inventory(name) + end + + return nil +end + +--- Iterates over the unit's abilities, yielding each non-nil ability. +--- @generic Ret +--- @param f fun(ability: CDOTABaseAbility): (boolean?, Ret...) +function M:for_each_ability(f) + for i = 0, self.entity:GetAbilityCount() - 1 do + local ability = self.entity:GetAbilityByIndex(i) + + if ability ~= nil then + local ret = { f(ability) } + local continue = true + + if ret[1] ~= nil then + continue = ret[1] + table.remove(ret, 1) + end + + if not continue then + return unpack(ret) + end + end + end + + return nil +end + +--- Clears all abilities cooldowns. +function M:end_ability_cooldowns() + self:for_each_ability(function(ability) + ability:EndCooldown() + end) +end + +---------------------------------------------------------------------------------------------------- + +--- @return integer +function M:get_level() + return self.entity:GetLevel() +end + +function M:hold() + self.entity:Hold() +end + +--- @param name string +function M:stop_sound(name) + self.entity:StopSound(name) +end + +--- @param points integer +function M:set_ability_points(points) + local hero = self:require_hero() + + hero:SetAbilityPoints(points) +end + +return M diff --git a/game/scripts/vscripts/invk/dota2/units.lua b/game/scripts/vscripts/invk/dota2/units.lua new file mode 100644 index 0000000..a27d265 --- /dev/null +++ b/game/scripts/vscripts/invk/dota2/units.lua @@ -0,0 +1,69 @@ +local val = require("invk.lang.value") + +--- Units helpers. +--- @class invk.dota2.units +local M = {} + +--- @class invk.dota2.units.CreateOptions +--- @field location Vector # Target location +--- @field team DOTATeam_t # Team number +--- @field find_clear_space? boolean # Find clear space for the unit (default: `true`) +--- @field npc_owner? CDOTA_BaseNPC # NPC owner +--- @field unit_owner? CDOTA_BaseNPC # Unit Owner + +--- Creates an unit by name. +--- @param name string # Unit name +--- @param options? invk.dota2.units.CreateOptions # Options table +--- @return CDOTA_BaseNPC # Created unit +function M.create(name, options) + local opts = options or {} + local find_clear_space = val.non_nil(opts.find_clear_space, true) + + return CreateUnitByName( + name, + opts.location, + find_clear_space, + opts.npc_owner, + opts.unit_owner, + opts.team + ) +end + +--- @class invk.dota2.units.CreateAsyncOptions : invk.dota2.units.CreateOptions +--- @field cb fun(unit: CDOTA_BaseNPC) # Callback function + +--- Creates an unit by name (async). +--- @param name string # Unit name +--- @param options invk.dota2.units.CreateAsyncOptions # Options table +--- @return SpawnGroupHandle +function M.create_async(name, options) + local opts = options or {} + local find_clear_space = val.non_nil(opts.find_clear_space, true) + + return CreateUnitByNameAsync( + name, + opts.location, + find_clear_space, + opts.npc_owner, + opts.unit_owner, + opts.team, + opts.cb + ) +end + +--- Creates a new data-driven unit with the given table. +--- @param definition table # Unit definition table +--- @param location Vector # Target location +--- @return CDOTA_BaseNPC # Created unit +function M.create_from_table(definition, location) + return CreateUnitFromTable(definition, location) +end + +--- Kills and removes the given unit. +--- @param unit CDOTA_BaseNPC # Unit entity +function M.destroy(unit) + unit:ForceKill(false) + unit:RemoveSelf() +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode.lua b/game/scripts/vscripts/invk/game_mode.lua new file mode 100644 index 0000000..e558b2a --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode.lua @@ -0,0 +1,999 @@ +local class = require("middleclass") +local inspect = require("inspect") + +local Ability = require("invk.dota2.ability") +local COMMANDS = require("invk.const.commands") +local CUSTOM_EVENTS = require("invk.const.custom_events") +local Combos = require("invk.combo.combos") +local CustomEvents = require("invk.dota2.custom_events") +local DamageInstance = require("invk.dota2.damage_instance") +local Env = require("invk.game_mode.env") +local INVOKER = require("invk.const.invoker") +local Invoker = require("invk.dota2.invoker") +local ItemsKeyValues = require("invk.dota2.kv.items_key_values") +local Logger = require("invk.logger") +local META = require("invk.const.metadata") +local NET_TABLES = require("invk.const.net_table") +local NetTable = require("invk.dota2.net_table") +local PRECACHE = require("invk.const.precache") +local S = require("invk.const.settings") +local Timers = require("invk.dota2.timers") +local Unit = require("invk.dota2.unit") +local func = require("invk.lang.function") +local rand = require("invk.lang.random") +local tbl = require("invk.lang.table") + +local LOGNAME = "invk" +local DEFAULT_ENV = Env.is_dev_mode() and Env.DEVELOPMENT or Env.PRODUCTION + +--- Main class for the game. +--- @class invk.GameMode : middleclass.Class, invk.log.Mixin +--- @field env invk.Env +--- @field users { [integer]: CDOTAPlayerController? } +--- @field players { [PlayerID]: CDOTAPlayerController? } +--- @field items_kv invk.dota2.kv.ItemsKeyValues +--- @field net_tables { [invk.net_table.Name]: invk.dota2.NetTable } +--- @field combos invk.combo.Combos +--- @field logger invk.Logger +--- @field private game_mode CDOTABaseGameMode +--- @field private _reentrant boolean +--- @field private _first_player_loaded boolean +--- @field private _first_spawned boolean +local M = class("invk.GameMode") + +M:include(Logger.Mixin) + +M.META = META +M._VERSION = META.version + +--- Precaches resources/units/items/abilities that will be needed for sure in +--- your game and that will not be precached by hero selection. +--- +--- When a hero is selected from the hero selection screen, the game will +--- precache that hero's assets, any equipped cosmetics, and perform the +--- data-driven precaching defined in that hero's `precache{}` block, as well as +--- the `precache{}` block for any equipped abilities. +function M.precache(ctx) + for _, name in ipairs(PRECACHE.UNITS) do + PrecacheUnitByNameSync(name, ctx) + end + + for path, ty in pairs(PRECACHE.RESOURCES) do + PrecacheResource(ty, path, ctx) + end +end + +--- @class invk.GameModeOptions +--- @field env? invk.Env # Environment + +--- Constructor. +--- @param options? invk.GameModeOptions # Options table +function M:initialize(options) + local opts = options or {} + + self._reentrant = false + self._first_player_loaded = false + self._first_spawned = false + + self.env = opts.env or DEFAULT_ENV + self.users = {} + self.players = {} + + self.logger = + Logger:new(LOGNAME, self.env == Env.DEVELOPMENT and Logger.Level.DEBUG or Logger.Level.INFO) + + self.items_kv = ItemsKeyValues:load() + + self.net_tables = tbl.map(NET_TABLES.Tables, function(config) + return NetTable:new(config, { logger = self.logger }) + end) + + self.combos = Combos:new(self.net_tables[NET_TABLES.Name.MAIN], { logger = self.logger }) +end + +--- @param fn_name string +--- @return fun(...: any): any... +function M:fn_handler(fn_name) + if self.env == Env.DEVELOPMENT then + return func.lookupbyname(self, fn_name) + end + + return self[fn_name] +end + +--- @param method_name string +--- @return fun(...: any): any... +function M:method_handler(method_name) + return func.bind(self:fn_handler(method_name), self) +end + +--- Entry-point for the game initialization. +function M:activate() + if M._reentrant then + return + end + + self:d("(addon) Activating...") + + self:setup_modules() + self:setup_net_tables() + self:setup_game_rules() + self:setup_game_mode() + self:register_game_events() + self:register_custom_events() + self:register_commands() + self:register_convars() + + self:d("(addon) Done") +end + +function M:setup_modules() + self:d(" (timers) setup") + Timers:start() + + self:d(" (random) seed") + rand.seed() +end + +--- Used to set up async precache calls at the beginning of the gameplay. +--- +--- In this function, place all of your `PrecacheItemByNameAsync` and +--- `PrecacheUnitByNameAsync`. These calls will be made after all players have +--- loaded in, but before they have selected their heroes. +--- `PrecacheItemByNameAsync` can also be used to precache dynamically-added +--- datadriven abilities instead of items. `PrecacheUnitByNameAsync` will +--- precache the `precache{}` block statement of the unit and all `precache{}` +--- block statements for every `Ability#` defined on the unit. +--- +--- This function should only be called once. If you want to/need to precache +--- more items/abilities/units at a later time, you can call the functions +--- individually (for example if you want to precache units in a new wave of +--- holdout). +--- +--- This function should generally only be used if `Precache` is not working. +function M:post_load_precache() + self:d("Performing Post-Load precache") +end + +--- net_tables {{{ + +function M:setup_net_tables() + self:d(" (net_tables) setup") + + -- main/hero_data + do + local net_table = self.net_tables[NET_TABLES.Name.MAIN] + + net_table:set(net_table.keys.HERO_DATA, INVOKER:serialize()) + end + + -- hero/key_values + do + local net_table = self.net_tables[NET_TABLES.Name.HERO] + + net_table:set(net_table.keys.KEY_VALUES, INVOKER.KEY_VALUES.data) + end + + -- abilities/key_values + do + local net_table = self.net_tables[NET_TABLES.Name.ABILITIES] + + net_table:set(net_table.keys.KEY_VALUES, INVOKER.KEY_VALUES:abilities_data()) + end +end + +--- }}} +--- game_rules {{{ + +function M:setup_game_rules() + self:d(" (GameRules) setup") + + GameRules:SetCreepMinimapIconScale(S.MINIMAP_CREEP_ICON_SCALE) + GameRules:SetCreepSpawningEnabled(S.ENABLE_CREEP_SPAWN) + GameRules:SetCustomGameAllowBattleMusic(S.ENABLE_BATTLE_MUSIC) + GameRules:SetCustomGameAllowHeroPickMusic(S.ENABLE_HERO_PICK_MUSIC) + GameRules:SetCustomGameAllowMusicAtGameStart(S.ENABLE_GAME_START_MUSIC) + GameRules:SetCustomGameEndDelay(S.GAME_END_DELAY) + GameRules:SetCustomGameSetupRemainingTime(S.GAME_SETUP_TIME) + GameRules:SetCustomGameSetupTimeout(S.GAME_SETUP_TIMEOUT) + GameRules:SetCustomVictoryMessage(S.VICTORY_MESSAGE) + GameRules:SetCustomVictoryMessageDuration(S.VICTORY_MESSAGE_DURATION) + GameRules:SetFirstBloodActive(S.ENABLE_FIRST_BLOOD) + GameRules:SetGoldPerTick(S.GOLD_PER_TICK) + GameRules:SetGoldTickTime(S.GOLD_TICK_TIME) + GameRules:SetHeroMinimapIconScale(S.MINIMAP_HERO_ICON_SCALE) + GameRules:SetHeroRespawnEnabled(S.ENABLE_HERO_RESPAWN) + GameRules:SetHeroSelectionTime(S.HERO_SELECTION_TIME) + GameRules:SetHeroSelectPenaltyTime(S.HERO_SELECTION_PENALTY_TIME) + GameRules:SetHideKillMessageHeaders(S.HIDE_KILL_BANNERS) + GameRules:SetPostGameTime(S.POST_GAME_TIME) + GameRules:SetPreGameTime(S.PRE_GAME_TIME) + GameRules:SetRuneMinimapIconScale(S.MINIMAP_RUNE_ICON_SCALE) + GameRules:SetRuneSpawnTime(S.RUNE_SPAWN_TIME) + GameRules:SetSameHeroSelectionEnabled(S.ALLOW_SAME_HERO_SELECTION) + GameRules:SetShowcaseTime(S.SHOWCASE_TIME) + GameRules:SetStartingGold(S.STARTING_GOLD) + GameRules:SetStrategyTime(S.STRATEGY_TIME) + GameRules:SetTreeRegrowTime(S.TREE_REGROW_TIME) + GameRules:SetUseBaseGoldBountyOnHeroes(S.USE_BASE_HERO_GOLD_BOUNTY) + GameRules:SetUseCustomHeroXPValues(S.USE_CUSTOM_XP_VALUES) + GameRules:SetUseUniversalShopMode(S.UNIVERSAL_SHOP_MODE) + + if self.env == Env.DEVELOPMENT then + GameRules:EnableCustomGameSetupAutoLaunch(true) + GameRules:LockCustomGameSetupTeamAssignment(true) + GameRules:SetCustomGameSetupAutoLaunchDelay(0) + else + GameRules:EnableCustomGameSetupAutoLaunch(S.ENABLE_AUTO_LAUNCH) + GameRules:LockCustomGameSetupTeamAssignment(S.LOCK_TEAM_SETUP) + GameRules:SetCustomGameSetupAutoLaunchDelay(S.AUTO_LAUNCH_DELAY) + end + + for team, number in pairs(S.CUSTOM_TEAM_PLAYER_COUNT) do + GameRules:SetCustomGameTeamMaxPlayers(team, number) + end + + if S.USE_CUSTOM_TEAM_COLORS then + for team, color in pairs(S.TEAM_COLORS) do + SetTeamCustomHealthbarColor(team, color[1], color[2], color[3]) + end + end + + -- Sets a callback to handle saving custom game account records (callback is + -- passed a player id and should return a flat simple table) [Preview/Unreleased] + -- GameRules:SetCustomGameAccountRecordSaveFunction(handle, handle) +end + +--- }}} +--- game_mode {{{ + +function M:setup_game_mode() + self:d(" (GameMode) setup") + + self.game_mode = GameRules:GetGameModeEntity() + + self.game_mode:SetAlwaysShowPlayerInventory(S.ALWAYS_SHOW_PLAYER_INVENTORY) + self.game_mode:SetAlwaysShowPlayerNames(S.ALWAYS_SHOW_PLAYER_NAMES) + self.game_mode:SetAnnouncerDisabled(S.DISABLE_ANNOUNCER) + self.game_mode:SetBotThinkingEnabled(S.USE_STANDARD_DOTA_BOT_THINKING) + self.game_mode:SetBotsAlwaysPushWithHuman(S.BOTS_ALWAYS_PUSH_WITH_HUMAN) + self.game_mode:SetBotsInLateGame(S.BOTS_LATE_GAME_BEHAVIOR) + self.game_mode:SetBotsMaxPushTier(S.BOTS_MAX_PUSH_TIER) + self.game_mode:SetBountyRuneSpawnInterval(S.BOUNTY_RUNE_SPAWN_INTERVAL) + self.game_mode:SetBuybackEnabled(S.BUYBACK_ENABLED) + self.game_mode:SetCameraDistanceOverride(S.CAMERA_DISTANCE_OVERRIDE) + self.game_mode:SetCameraSmoothCountOverride(S.CAMERA_SMOOTH_COUNT) + self.game_mode:SetCustomBackpackCooldownPercent(S.CUSTOM_BACKPACK_COOLDOWN_PERCENT) + self.game_mode:SetCustomBackpackSwapCooldown(S.CUSTOM_BACKPACK_SWAP_COOLDOWN) + self.game_mode:SetCustomBuybackCooldownEnabled(S.CUSTOM_BUYBACK_COOLDOWN_ENABLED) + self.game_mode:SetCustomBuybackCostEnabled(S.CUSTOM_BUYBACK_COST_ENABLED) + self.game_mode:SetCustomGlyphCooldown(S.CUSTOM_GLYPH_COOLDOWN) + self.game_mode:SetCustomScanCooldown(S.CUSTOM_SCAN_COOLDOWN) + self.game_mode:SetDaynightCycleDisabled(S.DISABLE_DAY_NIGHT_CYCLE) + self.game_mode:SetDeathOverlayDisabled(S.DISABLE_DEATH_OVERLAY) + self.game_mode:SetDraftingBanningTimeOverride(S.DRAFTING_BANNING_TIME) + self.game_mode:SetDraftingHeroPickSelectTimeOverride(S.DRAFTING_HERO_PICK_SELECTION_TIME) + self.game_mode:SetFixedRespawnTime(S.FIXED_RESPAWN_TIME) + self.game_mode:SetFogOfWarDisabled(S.DISABLE_FOG_OF_WAR) + self.game_mode:SetFountainConstantManaRegen(S.FOUNTAIN_CONSTANT_MANA_REGEN) + self.game_mode:SetFountainPercentageHealthRegen(S.FOUNTAIN_PERCENTAGE_HEALTH_REGEN) + self.game_mode:SetFountainPercentageManaRegen(S.FOUNTAIN_PERCENTAGE_MANA_REGEN) + self.game_mode:SetFriendlyBuildingMoveToEnabled(S.ENABLE_FRIENDLY_BUILDING_MOVE_TO_CLICK) + self.game_mode:SetGoldSoundDisabled(S.DISABLE_GOLD_SOUNDS) + self.game_mode:SetHudCombatEventsDisabled(S.DISABLE_COMBAT_EVENTS_HUD) + self.game_mode:SetKillingSpreeAnnouncerDisabled(S.DISABLE_KILLING_SPREE_ANNOUNCER) + self.game_mode:SetLoseGoldOnDeath(S.LOSE_GOLD_ON_DEATH) + self.game_mode:SetMaximumAttackSpeed(S.MAXIMUM_ATTACK_SPEED) + self.game_mode:SetMinimumAttackSpeed(S.MINIMUM_ATTACK_SPEED) + self.game_mode:SetPauseEnabled(S.ENABLE_PAUSE) + self.game_mode:SetPowerRuneSpawnInterval(S.POWER_RUNE_SPAWN_INTERVAL) + self.game_mode:SetRecommendedItemsDisabled(S.RECOMMENDED_BUILDS_DISABLED) + self.game_mode:SetRemoveIllusionsOnDeath(S.REMOVE_ILLUSIONS_ON_DEATH) + self.game_mode:SetRespawnTimeScale(S.RESPAWN_TIME_SCALE) + self.game_mode:SetSelectionGoldPenaltyEnabled(S.ENABLE_SELECTION_GOLD_PENALTY) + self.game_mode:SetStashPurchasingDisabled(S.DISABLE_STASH_PURCHASING) + self.game_mode:SetStickyItemDisabled(S.DISABLE_STICKY_ITEM) + self.game_mode:SetTopBarTeamValuesOverride(S.USE_CUSTOM_TOP_BAR_VALUES) + self.game_mode:SetTopBarTeamValuesVisible(S.TOP_BAR_VISIBLE) + self.game_mode:SetTowerBackdoorProtectionEnabled(S.ENABLE_TOWER_BACKDOOR_PROTECTION) + self.game_mode:SetUnseenFogOfWarEnabled(S.USE_UNSEEN_FOG_OF_WAR) + self.game_mode:SetUseDefaultDOTARuneSpawnLogic(S.USE_DEFAULT_DOTA_RUNE_SPAWN_LOGIC) + self.game_mode:SetWeatherEffectsDisabled(S.DISABLE_WEATHER_EFFECTS) + + -- Must be set before `SetUseCustomHeroLevels` + self.game_mode:SetCustomXPRequiredToReachNextLevel(S.XP_PER_LEVEL_TABLE) + self.game_mode:SetUseCustomHeroLevels(S.USE_CUSTOM_HERO_LEVELS) + + -- self.gameMode:SetCustomAttributeDerivedStatValue(nStatType, flNewValue) + -- self.gameMode:SetHUDVisible(iHUDElement, bVisible) + -- self.gameMode:SetKillableTombstones(S.KILLABLE_TOMBSTONES) + -- self.gameMode:SetTopBarTeamValue(iTeam, nValue) + + if S.FORCE_PICKED_HERO ~= nil then + self.game_mode:SetCustomGameForceHero(S.FORCE_PICKED_HERO) + end + + if S.CUSTOM_TERRAIN_WEATHER_EFFECT ~= nil then + self.game_mode:SetCustomTerrainWeatherEffect(S.CUSTOM_TERRAIN_WEATHER_EFFECT) + end + + for rune, spawn in pairs(S.ENABLED_RUNES) do + self.game_mode:SetRuneEnabled(rune, spawn) + end +end + +--- }}} +--- events {{{ + +--- @param event string +--- @param method_name string +--- @return EventListenerID +function M:listen_to_game_event(event, method_name) + return ListenToGameEvent(event, self:fn_handler(method_name), self) +end + +--- @param event string +--- @param method_name string +--- @return CustomGameEventListenerID +function M:subscribe_to_custom_event(event, method_name) + return CustomEvents.subscribe(event, self:method_handler(method_name)) +end + +function M:register_game_events() + self:d(" (game_events) register listeners") + + self:listen_to_game_event("dota_ability_channel_finished", "OnAbilityChannelFinished") + self:listen_to_game_event("dota_item_purchased", "OnItemPurchased") + self:listen_to_game_event("dota_non_player_used_ability", "OnNonPlayerUsedAbility") + self:listen_to_game_event("dota_player_begin_cast", "OnAbilityCastBegins") + self:listen_to_game_event("dota_player_used_ability", "OnAbilityUsed") + self:listen_to_game_event("entity_hurt", "OnEntityHurt") + self:listen_to_game_event("entity_killed", "_OnEntityKilled") + self:listen_to_game_event("game_rules_state_change", "_OnGameRulesStateChange") + self:listen_to_game_event("npc_spawned", "_OnNPCSpawned") + self:listen_to_game_event("player_connect_full", "_OnConnectFull") +end + +function M:register_custom_events() + self:d(" (custom_events) register listeners") + + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_PLAYER_QUIT_REQUEST, "OnPlayerQuitRequest") + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_START, "OnComboStart") + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_STOP, "OnComboStop") + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_RESTART, "OnComboRestart") + self:subscribe_to_custom_event( + CUSTOM_EVENTS.EVENT_FREESTYLE_HERO_LEVEL_UP, + "OnFreestyleHeroLevelUp" + ) + + self:subscribe_to_custom_event( + CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_START, + "OnCombatLogCaptureStart" + ) + + self:subscribe_to_custom_event( + CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_STOP, + "OnCombatLogCaptureStop" + ) + self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_REQUEST, "OnItemPickerQuery") +end + +-- events.internal {{{ + +local WARNF_MISSING_TEAM_COLOR = + "Attempted to set custom player color for player %d and team %d, but the team color is not configured." + +--- Called when the overall game state has changed. +--- @param payload table +function M:_OnGameRulesStateChange(payload) + if self._reentrant then + return + end + + local state = GameRules:State_Get() + + self._reentrant = true + self:OnGameRulesStateChange(state, payload) + self._reentrant = false + + if state == DOTA_GAMERULES_STATE_HERO_SELECTION then + self:post_load_precache() + self:OnAllPlayersLoaded() + + if S.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS then + for i = 0, DOTA_DEFAULT_MAX_TEAM_PLAYERS do + if PlayerResource:IsValidPlayer(i) then + local team = PlayerResource:GetTeam(i) + local color = S.TEAM_COLORS[team] + + if color ~= nil then + PlayerResource:SetCustomPlayerColor(i, color[1], color[2], color[3]) + else + self:warnf(WARNF_MISSING_TEAM_COLOR, i, team) + end + end + end + end + elseif state == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then + self:OnGameInProgress() + end +end + +--- @class invk.game_mode.events.PlayerConnectFull +--- @field PlayerID integer # Player id +--- @field userid integer # User id + +--- Called once when the player fully connects and becomes "Ready" during loading. +--- @param payload invk.game_mode.events.PlayerConnectFull +function M:_OnConnectFull(payload) + self:d("_OnConnectFull", { payload = payload }) + + if self._reentrant then + return + end + + local player = assertf( + PlayerResource:GetPlayer(payload.PlayerID), + "received invalid player ID from event payload %s", + inspect(payload) + ) + + self._reentrant = true + self:OnConnectFull(player, payload.userid) + self._reentrant = false + + if not self._first_player_loaded then + self._first_player_loaded = true + self:OnFirstPlayerLoaded() + end +end + +--- @class invk.game_mode.events.NpcSpawned +--- @field entindex integer # Unit entity index + +--- Called when an NPC has spawned somewhere in game, including heroes. +--- @param payload invk.game_mode.events.NpcSpawned +function M:_OnNPCSpawned(payload) + self:d("_OnNPCSpawned", { payload = payload }) + + if self._reentrant then + return + end + + local npc = EntIndexToHScript(payload.entindex) --[[@as CDOTA_BaseNPC?]] + + if npc ~= nil and npc:IsRealHero() and not self._first_spawned then + self._first_spawned = true + self:OnHeroInGame(npc) + end +end + +--- @class invk.game_events.OnEntityKilled +--- @field entindex_killed integer # Victim (unit) entity index +--- @field entindex_attacker? integer # Attacker (unit) entity index +--- @field entindex_inflictor? integer # Inflictor (item, ability, etc) entity index + +--- Called when an entity was killed. +--- @param payload invk.game_events.OnEntityKilled +function M:_OnEntityKilled(payload) + self:d("_OnEntityKilled", { payload = payload }) + + if self._reentrant then + return + end + + local killed = EntIndexToHScript(payload.entindex_killed) + local attacker = nil + local inflictor = nil + + if payload.entindex_attacker ~= nil then + attacker = EntIndexToHScript(payload.entindex_attacker) + end + + if payload.entindex_inflictor ~= nil then + inflictor = EntIndexToHScript(payload.entindex_inflictor) + end + + self._reentrant = true + self:OnEntityKilled(killed, attacker, inflictor) + self._reentrant = false +end + +-- }}} +-- events.game {{{ + +local ERRF_ABILITY_OR_ITEM_NOT_FOUND = "Could not find ability or item named %q on unit %q" + +--- The overall game state has changeds. +--- @param state DOTA_GameState +--- @param payload table +function M:OnGameRulesStateChange(state, payload) + self:d("OnGameRulesStateChange", { state = state, payload = payload }) +end + +--- Called once when the player fully connects and becomes "Ready" during loading. +--- @param player CDOTAPlayerController +--- @param user_id integer +function M:OnConnectFull(player, user_id) + self:d("OnConnectFull", { player = player:GetPlayerID() }) + + self.users[user_id] = player + self.players[player:GetPlayerID()] = player +end + +--- Called once and only once as soon as the first player (almost certain to be +--- the server in local lobbies) loads in. +--- +--- It can be used to initialize state that isn't initializeable in @{Activate} +--- but needs to be done before everyone loads in. +function M:OnFirstPlayerLoaded() + self:d("OnFirstPlayerLoaded") +end + +--- Called once and only once after all players have loaded into the game, +--- right as the hero selection time begins. +--- +--- It can be used to initialize non-hero player state or adjust the hero +--- selection (i.e. force random etc) +function M:OnAllPlayersLoaded() + self:d("OnAllPlayersLoaded") +end + +--- Called once and only once for every player when they spawn into the game +--- for the first time. +--- +--- It is also called if the player's hero is replaced with a new hero for any +--- reason. This function is useful for initializing heroes, such as adding +--- levels, changing the starting gold, removing/adding abilities, adding +--- physics, etc. +--- +--- @param hero CDOTA_BaseNPC_Hero +function M:OnHeroInGame(hero) + self:d("OnHeroInGame", { hero = hero:GetUnitName() }) + + local player_id = hero:GetPlayerID() + local player = + assertf(PlayerResource:GetPlayer(player_id), "received invalid player id %d", player_id) + + local payload = { + id = hero:GetHeroID(), + name = hero:GetUnitName(), + variant = hero:GetHeroFacetID(), + } + + CustomEvents.send_player(CUSTOM_EVENTS.EVENT_PLAYER_HERO_IN_GAME, player, payload) +end + +--- Called once and only once when the game completely begins (about 0:00 on the clock). +function M:OnGameInProgress() + self:d("OnGameInProgress") +end + +--- @class invk.game_events.OnEntityHurt +--- @field damage number # Damage amount +--- @field damagebits integer # Damage flags +--- @field entindex_killed integer # Victim (unit) entity index +--- @field entindex_attacker integer # Attacker (unit) entity index +--- @field entindex_inflictor integer # Inflictor (item, ability, etc) entity index + +--- An entity has been hurt. +--- @param payload invk.game_events.OnEntityHurt +function M:OnEntityHurt(payload) + self:d("OnEntityHurt", { payload = payload }) + + local attacker + local inflictor + local victim = Unit:new(EntIndexToHScript(payload.entindex_killed)) + + if payload.entindex_attacker ~= nil then + attacker = Unit:new(EntIndexToHScript(payload.entindex_attacker)) + end + + -- FIXME: This is a hack to fix an issue when an entity is killed with `ForceKill`, + -- FIXME: which will trigger this event. I'm not sure which enum `damagebits` is using, + -- FIXME: but regular damage seems to always set it to 0 while `ForceKill` sets it to 4096 + if payload.entindex_inflictor ~= nil and payload.damagebits == 0 then + inflictor = Ability:new(EntIndexToHScript(payload.entindex_inflictor)) + end + + local damage = DamageInstance:new(victim, payload.damage, attacker, inflictor) + + self.combos:on_entity_hurt(damage) +end + +--- @class invk.game_events.OnItemPurchased +--- @field PlayerID integer # Player id +--- @field itemname string # Item name +--- @field itemcost integer # Item cost + +--- An item was purchased by a player. +--- @param payload invk.game_events.OnItemPurchased +function M:OnItemPurchased(payload) + self:d("OnItemPurchased", { payload = payload }) + + local player = assertf( + PlayerResource:GetPlayer(payload.PlayerID), + "received invalid player ID from event payload %s", + inspect(payload) + ) + + self.combos:on_item_purchased(player, { + item = payload.itemname, + cost = payload.itemcost, + }) +end + +--- @class invk.game_events.OnAbilityCastBegins +--- @field PlayerID integer # Player id +--- @field abilityname string # Ability name + +--- Called whenever an ability begins its PhaseStart phase (but before it is actually cast). +--- @param payload invk.game_events.OnAbilityCastBegins +function M:OnAbilityCastBegins(payload) + self:d("OnAbilityCastBegins", { payload = payload }) +end + +--- @class invk.game_events.OnAbilityUsed +--- @field PlayerID integer # Player id +--- @field caster_entindex integer # Caster (unit) entity index +--- @field abilityname string # Ability name + +--- An ability was used by a player (including items). +--- @param payload invk.game_events.OnAbilityUsed +function M:OnAbilityUsed(payload) + self:d("OnAbilityUsed", { payload = payload }) + + local player = assertf( + PlayerResource:GetPlayer(payload.PlayerID), + "received invalid player ID from event payload %s", + inspect(payload) + ) + + local caster = Unit(EntIndexToHScript(payload.caster_entindex)) + local abilityEnt = caster:FindAbilityOrItem(payload.abilityname) + + if abilityEnt == nil then + errorf(ERRF_ABILITY_OR_ITEM_NOT_FOUND, payload.abilityname, caster.name) + end + + local ability = Ability(abilityEnt) + + self.combos:on_ability_used(player, caster, ability) +end + +--- A non-player entity (necro-book, chen creep, etc) used an ability. +-- @tparam table payload +-- @tparam int payload.caster_entindex Caster (unit) entity index +-- @tparam string payload.abilityname Ability name +function M:OnNonPlayerUsedAbility(payload) + self:d("OnNonPlayerUsedAbility", { payload = payload }) +end + +--- A channelled ability finished by either completing or being interrupted. +-- @tparam table payload +-- @tparam string payload.abilityname Ability name +-- @tparam int payload.interrupted `1` if ability was interrupted +function M:OnAbilityChannelFinished(payload) + self:d("OnAbilityChannelFinished", { payload = payload }) +end + +--- An entity died. +-- @tparam CDOTA_BaseNPC killed Killed unit +-- @tparam[opt] CDOTA_BaseNPC attacker Attacker unit +-- @tparam[opt] CDOTABaseAbility inflictor Inflictor ability +function M:OnEntityKilled(killed, attacker, inflictor) + self:d("OnEntityKilled", { + killed = killed:GetName(), + attacker = attacker and attacker:GetName(), + inflictor = inflictor and inflictor:GetName(), + }) +end + +-- }}} +-- events.custom {{{ + +--- Handles player quit request events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.PlayerQuitRequest +function M:OnPlayerQuitRequest(player, payload) + self:d("OnPlayerQuitRequest", { player = player:GetPlayerID(), payload = payload }) + + SendToServerConsole("disconnect") +end + +--- Handles combos reload events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.CombosReloadPayload +function M:OnCombosReload(player, payload) + self:d("OnCombosReload", { player = player:GetPlayerID(), payload = payload }) + self.combos:load() +end + +--- Handles combo start events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ComboStartPayload +function M:OnComboStart(player, payload) + self:d("OnComboStart", { player = player:GetPlayerID(), payload = payload }) + + local combo = self.combos:create(payload.id) + + self.combos:on_start(player, combo) +end + +--- Handles combo stop events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ComboStopPayload +function M:OnComboStop(player, payload) + self:d("OnComboStop", { player = player:GetPlayerID(), payload = payload }) + + self.combos:on_stop(player) +end + +--- Handles combo restart events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ComboRestartPayload +function M:OnComboRestart(player, payload) + self:d("OnComboRestart", { player = player:GetPlayerID(), payload = payload }) + + local options = { hardReset = payload.hardReset == 1 } + + self.combos:on_restart(player, options) +end + +--- Handles freestyle hero level up events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.FreestyleHeroLevelUpPayload +function M:OnFreestyleHeroLevelUp(player, payload) + self:d("OnFreestyleHeroLevelUp", { player = player:GetPlayerID(), payload = payload }) + + local options = { + level = payload.level, + max_level = payload.maxLevel == 1, + } + + self.combos:freestyle_hero_level_up(player, options) +end + +--- Handles combat log capture start events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.CombatLogCaptureStartPayload +function M:OnCombatLogCaptureStart(player, payload) + self:d("OnCombatLogCaptureStart", { player = player:GetPlayerID(), payload = payload }) + + self.combos:start_capturing_abilities(player) +end + +--- Handles combat log capture stop events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.CombatLogCaptureStopPayload +function M:OnCombatLogCaptureStop(player, payload) + self:d("OnCombatLogCaptureStop", { player = player:GetPlayerID(), payload = payload }) + + self.combos:stop_capturing_abilities(player) +end + +--- Handles item picker query events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ItemPickerQueryPayload +function M:OnItemPickerQuery(player, payload) + self:d("OnItemPickerQuery", { player = player:GetPlayerID(), payload = payload }) + + local response = { items = self.items_kv:search(payload.query) } + + CustomEvents.send_player(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_RESPONSE, player, response) +end + +-- }}} + +--- }}} +--- commands {{{ + +--- @param method_name string +function M:command_handler(method_name) + return function(command, ...) + self:d(command, method_name, ...) + + local callback = self:method_handler(method_name) + local pawn = Convars:GetDOTACommandClient() --[[@as CBasePlayerPawn]] + local player = pawn:GetController() + + return callback(player, ...) + end +end + +--- @param cmd invk.game_mode.ConsoleCommmand +function M:register_command(cmd) + Convars:RegisterCommand(cmd.name, self:command_handler(cmd.method), cmd.help, cmd.flags or 0) +end + +function M:register_commands() + self:d(" (commands) register commands") + + for _, cmd in ipairs(COMMANDS) do + if not cmd.dev or (cmd.dev and self.env == Env.DEVELOPMENT) then + self:register_command(cmd) + end + end +end + +--- Sets debugging on/off. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @param arg? string # `"1"`: enables debugging, `"0"`: disables debugging, `nil`: prints debugging value. +function M:CommandSetDebug(_player, arg) + if arg == "1" then + self.logger.level = Logger.Level.DEBUG + elseif arg == "0" then + self.logger.level = Logger.Level.INFO + else + print(F("inv_debug = %d", self.logger.level <= Logger.Level.DEBUG and 1 or 0)) + end +end + +--- Placeholder command to run miscellaneous debug code. +--- +--- Use `script_reload` to reload after changes. +--- +--- @param player CDOTAPlayerController # Player who issued this console command. +--- @param ... any +function M:CommandDebugMisc(player, ...) + local cmd = require("invk.game_mode.commands.debug_misc") + + cmd.run(self, player, ...) +end + +--- Dumps Lua version. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @diagnostic disable-next-line: unused +function M:CommandDumpLuaVersion(_player) + print(_VERSION) +end + +--- Dumps global value. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @param name string # Dot-separated value name +--- @diagnostic disable-next-line: unused +function M:CommandDumpGlobal(_player, name) + if not name then + error("Argument is required") + end + + local cmd = require("invk.game_mode.commands.globals") + + cmd.dump(name) +end + +--- Searches a global value. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @param pattern string # Name pattern (uses `string.match` for matching) +--- @diagnostic disable-next-line: unused +function M:CommandFindGlobal(_player, pattern) + if not pattern then + error("Argument is required") + end + + local cmd = require("invk.game_mode.commands.globals") + + cmd.find(pattern) +end + +--- Queries items. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @param query string # Query string +function M:CommandItemQuery(_player, query) + if not query then + error("Argument is required") + end + + local cmd = require("invk.game_mode.commands.item") + + cmd.query(self, query) +end + +--- Dumps current hero abilities. +--- @param player CDOTAPlayerController # Player who issued this console command +--- @param simple? string # Simple version or verbose +--- @diagnostic disable-next-line: unused +function M:CommandDumpAbilities(player, simple) + local cmd = require("invk.game_mode.commands.dump_abilities") + + cmd.run(player, simple ~= nil) +end + +--- Invokes ability by name. +--- @param player CDOTAPlayerController # Player who issued this console command +--- @param ability string # Ability name +--- @diagnostic disable-next-line: unused +function M:CommandInvokeAbility(player, ability) + if not ability then + error("Argument is required") + end + + local hero = player:GetAssignedHero() + local invoker = Invoker:new(hero) + + invoker:invoke(ability) +end + +--- Dumps combo graph in DOT format. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @param id string # Combo id +function M:CommandDumpComboGraph(_player, id) + if not id then + error("Argument is required") + end + + local cmd = require("invk.game_mode.commands.combo") + + cmd.todot(self, id) +end + +--- Changes music status. +--- @param player CDOTAPlayerController # Player who issued this console command +--- @param status string # Music status +--- @param intensity string # Music intensity +--- @diagnostic disable-next-line: unused +function M:CommandChangeMusicStatus(player, status, intensity) + if not status or not intensity then + error("Arguments and are required") + end + + local cmd = require("invk.game_mode.commands.music") + + cmd.set_status(player, status, intensity) +end + +--- Dumps Invoker ability specials values. +--- @param player CDOTAPlayerController # Player who issued this console command +--- @param only_scaling? string # Dump only values that scale, ignoring fixed values +--- @diagnostic disable-next-line: unused +function M:CommandDumpSpecials(player, only_scaling) + local cmd = require("invk.game_mode.commands.dump_specials") + + cmd.dump(player, { only_scaling = (only_scaling ~= nil) }) +end + +--- Debug operations on ability specials KeyValues. +--- @param _player CDOTAPlayerController # Player who issued this console command +--- @param op string # Operation name (`dump`, `find_keys`, `find_values`) +--- @param query string # Operation query (dump: path, findKeys: pattern, findValues: pattern) +--- @diagnostic disable-next-line: unused +function M:CommandDebugSpecials(_player, op, query) + local cmd = require("invk.game_mode.commands.debug_specials") + + if op == "dump" then + cmd.dump(query) + elseif op == "find_keys" then + cmd.find_keys(query) + elseif op == "find_values" then + cmd.find_values(query) + else + errorf("Invalid op %q", op) + end +end + +--- Reinserts an ability into the current hero. +--- @param player CDOTAPlayerController # Player who issued this console command +--- @param name string # Ability name +--- @diagnostic disable-next-line: unused +function M:CommandReinsertAbility(player, name) + if not name then + error("Argument is required") + end + + local cmd = require("invk.game_mode.commands.ability") + + cmd.reinsert(player, name) +end + +--- }}} +--- convars {{{ + +function M:register_convars() + self:d(" (convars) register convars") +end + +--- }}} + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/ability.lua b/game/scripts/vscripts/invk/game_mode/commands/ability.lua new file mode 100644 index 0000000..c994dba --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/ability.lua @@ -0,0 +1,23 @@ +local M = {} + +--- @param player CDOTAPlayerController +--- @param name string +function M.reinsert(player, name) + local hero = player:GetAssignedHero() + local ability = hero:FindAbilityByName(name) + + if not ability then + errorf("Ability %q not found", name) + end + + local index = ability:GetAbilityIndex() + local level = ability:GetLevel() + + hero:RemoveAbility(name) + + ability = hero:AddAbility(name) + ability:SetAbilityIndex(index) + ability:SetLevel(level) +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/combo.lua b/game/scripts/vscripts/invk/game_mode/commands/combo.lua new file mode 100644 index 0000000..26dce27 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/combo.lua @@ -0,0 +1,21 @@ +local M = {} + +--- @param game_mode invk.GameMode +--- @param id string +function M.todot(game_mode, id) + local combo_id = tonumber(id) --[[@as integer?]] + + if not combo_id then + errorf("Invalid combo id %q", id) + end + + local combo = game_mode.combos:create(combo_id) --[[@as invk.combo.Combo?]] + + if combo == nil then + error("Could not find combo") + end + + print(combo:todot()) +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/debug_misc.lua b/game/scripts/vscripts/invk/game_mode/commands/debug_misc.lua new file mode 100644 index 0000000..c693dbc --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/debug_misc.lua @@ -0,0 +1,21 @@ +--# selene: allow(unused_variable) + +local M = {} + +--- @param game_mode invk.GameMode +--- @param player CDOTAPlayerController +--- @param ... string +--- @diagnostic disable-next-line: unused +function M.run(game_mode, player, ...) + print("debug_misc") + + local combo_hero = require("invk.combo.hero") + + if select("#", ...) > 0 then + combo_hero.teardown(player, { hard_reset = true }) + else + combo_hero.level_up(player, { max_level = true }) + end +end + +return M diff --git a/game/scripts/vscripts/invokation/game_mode/commands/debug_specials.lua b/game/scripts/vscripts/invk/game_mode/commands/debug_specials.lua similarity index 62% rename from game/scripts/vscripts/invokation/game_mode/commands/debug_specials.lua rename to game/scripts/vscripts/invk/game_mode/commands/debug_specials.lua index cd9936a..86c4f5c 100644 --- a/game/scripts/vscripts/invokation/game_mode/commands/debug_specials.lua +++ b/game/scripts/vscripts/invk/game_mode/commands/debug_specials.lua @@ -1,10 +1,13 @@ -local pp = require("pl.pretty") -local stringx = require("pl.stringx") +local inspect = require("inspect") -local ABILITIES = require("invokation.const.abilities") +local ABILITIES = require("invk.const.abilities") +local str = require("invk.lang.string") +--- @class invk.commands.debug_specials local M = {} +--- @param ... string|string[] +--- @return string local function joinpath(...) local path = { ... } @@ -16,10 +19,10 @@ local function joinpath(...) path = path[1] end - return stringx.join(".", path) + return table.concat(path, ".") end -local function iterSpecials(keys) +local function iter_specials(keys) local ability, special local abilities = ABILITIES.KEY_VALUES @@ -34,7 +37,7 @@ local function iterSpecials(keys) end if type(ability) ~= "table" then - print(string.format("(WARN) %s not a table [%s]", joinpath(keys.ability), type(ability))) + print(F("(WARN) %s not a table [%s]", joinpath(keys.ability), type(ability))) keys.ability = next(abilities, keys.ability) @@ -42,7 +45,7 @@ local function iterSpecials(keys) return nil end - return iterSpecials(keys) + return iter_specials(keys) end local specials = ability.AbilitySpecial @@ -50,11 +53,7 @@ local function iterSpecials(keys) if type(specials) ~= "table" then if specials ~= nil then print( - string.format( - "(WARN) %s not a table [%s]", - joinpath(keys.ability, "AbilitySpecial"), - type(specials) - ) + F("(WARN) %s not a table [%s]", joinpath(keys.ability, "AbilitySpecial"), type(specials)) ) end @@ -64,7 +63,7 @@ local function iterSpecials(keys) return nil end - return iterSpecials(keys) + return iter_specials(keys) end keys.special, special = next(specials, keys.special) @@ -76,55 +75,61 @@ local function iterSpecials(keys) return nil end - return iterSpecials(keys) + return iter_specials(keys) end local path = { keys.ability, "AbilitySpecial", keys.special } if type(special) ~= "table" then if special ~= nil then - print(string.format("(WARN) %s not a table [%s]", joinpath(path), type(special))) + print(F("(WARN) %s not a table [%s]", joinpath(path), type(special))) end - return iterSpecials(keys) + return iter_specials(keys) end return keys.special, special, path end -local function walkSpecials() - return iterSpecials, {} +local function walk_specials() + return iter_specials, {} end +--- @param query string function M.dump(query) local value = ABILITIES.KEY_VALUES local currentPath = {} - local path = stringx.split(query, ".") + local path = str.split(query, ".") + table.insert(path, 2, "AbilitySpecial") for _, seg in ipairs(path) do table.insert(currentPath, seg) - value = value[seg] - if value == nil then + local subvalue = value[seg] --[[@as invk.dota2.KeyValues]] + + if subvalue == nil then break end + + value = subvalue end local currentProp = joinpath(currentPath) if value == nil then - print(string.format("%s not found", currentProp)) + print(F("%s not found", currentProp)) else - print(string.format("%s [%s]", currentProp, type(value))) - pp.dump(value) + print(F("%s [%s]", currentProp, type(value))) + print(inspect(value)) end end -function M.findKeys(query) +--- @param query string +function M.find_keys(query) local keys = {} - for _, special, path in walkSpecials() do + for _, special, path in walk_specials() do for key, _ in pairs(special) do if key:match(query) then keys[key] = keys[key] or {} @@ -136,15 +141,16 @@ function M.findKeys(query) print("---") for key, paths in pairs(keys) do print(key) - pp.dump(paths) + print(inspect(paths)) print("---") end end -function M.findValues(query) +--- @param query string +function M.find_values(query) local keys = {} - for _, special, _ in walkSpecials() do + for _, special, _ in walk_specials() do for key, value in pairs(special) do if type(value) == "string" and value:match(query) then keys[key] = keys[key] or {} @@ -156,7 +162,7 @@ function M.findValues(query) print("---") for key, values in pairs(keys) do print(key) - pp.dump(values) + print(inspect(values)) print("---") end end diff --git a/game/scripts/vscripts/invk/game_mode/commands/dump_abilities.lua b/game/scripts/vscripts/invk/game_mode/commands/dump_abilities.lua new file mode 100644 index 0000000..3ea9b01 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/dump_abilities.lua @@ -0,0 +1,60 @@ +local inspect = require("inspect") + +local M = {} + +--- @param ability CDOTABaseAbility? +--- @param simple boolean +--- @return table? +local function debug_ability(ability, simple) + if ability == nil then + return nil + end + + if simple then + return { + ability:GetAbilityIndex(), + ability:GetAbilityName(), + ability:GetLevel(), + } + end + + return { + name = ability:GetAbilityName(), + index = ability:GetAbilityIndex(), + type = ability:GetAbilityType(), + level = ability:GetLevel(), + max_level = ability:GetMaxLevel(), + damage = ability:GetAbilityDamage(), + damage_type = ability:GetAbilityDamageType(), + is_castable = ability:IsFullyCastable(), + is_activated = ability:IsActivated(), + is_hidden = ability:IsHidden(), + is_attribute_bonus = ability:IsAttributeBonus(), + is_item = ability:IsItem(), + is_passive = ability:IsPassive(), + procs_magic_stick = ability:ProcsMagicStick(), + is_trained = ability:IsTrained(), + can_be_upgraded = ability:CanAbilityBeUpgraded(), + hero_level_to_upgrade = ability:GetHeroLevelRequiredToUpgrade(), + duration = ability:GetDuration(), + cast_range = ability:GetCastRange(), + cast_point = ability:GetCastPoint(), + backswing_time = ability:GetBackswingTime(), + channel_time = ability:GetChannelTime(), + } +end + +--- @param player CDOTAPlayerController +--- @param simple boolean +function M.run(player, simple) + local hero = player:GetAssignedHero() + + for i = 0, hero:GetAbilityCount() - 1 do + local ability = hero:GetAbilityByIndex(i) + local repr = inspect(debug_ability(ability, simple)) + + print(F("[%d] %s", i, repr)) + end +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/dump_specials.lua b/game/scripts/vscripts/invk/game_mode/commands/dump_specials.lua new file mode 100644 index 0000000..348cb68 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/dump_specials.lua @@ -0,0 +1,123 @@ +local INVOKER = require("invk.const.invoker") +local str = require("invk.lang.string") +local tbl = require("invk.lang.table") + +--- @class invk.commands.dump_specials +local M = {} + +--- @type { [string]: std.type } +local FIELD_TYPES = { + FIELD_INTEGER = "number", + FIELD_FLOAT = "number", +} + +--- @param key string +--- @param value any +--- @param lua_type std.type +--- @return boolean +local function is_special_key(key, value, lua_type) + if key == "var_type" then + return false + end + + if not key:match("^[a-z_]+$") then + return false + end + + local function is_lua_type(_, v) + return type(v) == lua_type + end + + if is_lua_type(nil, value) then + return true + end + + if type(value) == "table" then + if tbl.all(value, is_lua_type) then + return true + end + end + + return false +end + +--- @param value invk.dota2.kv.Value +--- @return boolean +local function is_scaling_special_key(value) + return type(value) == "table" +end + +--- @param kv invk.dota2.KeyValues +--- @return invk.dota2.KeyValues +local function extract_specials(kv) + return tbl.map(kv, function(special) + if type(special) ~= "table" then + return nil + end + + --- @cast special invk.dota2.KeyValues + + if type(special.var_type) ~= "string" then + return nil + end + + local specials = tbl.filter(special, function(value, key) + return is_special_key(key, value, FIELD_TYPES[value.var_type]) + end) + + return tbl.keys(specials)[1] + end) +end + +--- @param kv invk.dota2.KeyValues +--- @return invk.dota2.KeyValues +local function extract_scaling_specials(kv) + return tbl.map(kv, function(special) + if type(special) ~= "table" then + return nil + end + + --- @cast special invk.dota2.KeyValues + + local specials = tbl.filter(special, is_scaling_special_key) + + return tbl.keys(specials)[1] + end) +end + +--- @param player CDOTAPlayerController +--- @param options? { only_scaling?: boolean } +function M.dump(player, options) + local opts = options or {} + + local hero = player:GetAssignedHero() + --- @type fun(kv: invk.dota2.KeyValues): invk.dota2.KeyValues + local extractor + + if opts.only_scaling then + extractor = extract_scaling_specials + else + extractor = extract_specials + end + + --- @type invk.dota2.KeyValues + local specials = tbl.map(INVOKER.KEY_VALUES:abilities_data(), function(kv) + return extractor(kv.AbilityValues or {}) + end) + + local max_ability_len = str.max_len(tbl.keys(specials)) + local max_special_len = tbl.max(tbl.map(specials, str.max_len)) + local fmt = F("%%-%ds %%-%ds %%s", max_ability_len, max_special_len) + + for a_name, s_names in pairs(specials) do + local ability = assertf(hero:FindAbilityByName(a_name), "could not find ability %q", a_name) + + for _, s_name in ipairs(s_names) do + local s_value = ability:GetSpecialValueFor(s_name) + + print(F(fmt, a_name, s_name, s_value)) + end + end +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/globals.lua b/game/scripts/vscripts/invk/game_mode/commands/globals.lua new file mode 100644 index 0000000..daae956 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/globals.lua @@ -0,0 +1,48 @@ +local inspect = require("inspect") + +local M = {} + +--- @param name string +function M.dump(name) + -- selene: allow(global_usage) + local value = _G + + for segment in name:gmatch("([^.]+)%.?") do + value = value[segment] + end + + local ty = type(value) + local repr = inspect(value) + + print(F("%q (%s): %s", name, ty, repr)) + + if ty == "function" then + local info = debug.getinfo(value) + + print(F("source: %s:%d", info.source, info.linedefined)) + end +end + +--- @param pattern string +function M.find(pattern) + local matches = {} + + -- selene: allow(global_usage) + for name, _ in pairs(_G) do + if name:match(pattern) then + table.insert(matches, name) + end + end + + table.sort(matches) + + print(F("Globals matching pattern %q:", pattern)) + + for _, match in ipairs(matches) do + print(F(" * %s", match)) + end + + print("---") +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/item.lua b/game/scripts/vscripts/invk/game_mode/commands/item.lua new file mode 100644 index 0000000..bf65a8d --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/item.lua @@ -0,0 +1,24 @@ +local inspect = require("inspect") + +local tbl = require("invk.lang.table") + +local M = {} + +--- @param game_mode invk.GameMode +--- @param query string +function M.query(game_mode, query) + local items = game_mode.items_kv:search(query) + + if tbl.is_empty(items) then + print("No items found.") + return + end + + for name, kv in pairs(items) do + local repr = inspect(kv) + + print(F("%s %s", name, repr)) + end +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/commands/music.lua b/game/scripts/vscripts/invk/game_mode/commands/music.lua new file mode 100644 index 0000000..891d4e6 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/commands/music.lua @@ -0,0 +1,26 @@ +local M = {} + +--- @param player CDOTAPlayerController +--- @param status string +--- @param intensity string +function M.set_status(player, status, intensity) + local status_n = tonumber(status) --[[@as integer?]] + + if not status_n then + errorf("Invalid status %q", status) + end + + if not status_n then + errorf("Invalid status %q", status) + end + + local intensity_n = tonumber(intensity) + + if not intensity_n then + errorf("Invalid intensity %q", intensity) + end + + player:SetMusicStatus(status_n, intensity_n) +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/env.lua b/game/scripts/vscripts/invk/game_mode/env.lua new file mode 100644 index 0000000..d671da6 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/env.lua @@ -0,0 +1,15 @@ +local val = require("invk.lang.value") + +--- Environment +--- @enum invk.Env +local M = { + DEVELOPMENT = "development", + PRODUCTION = "production", +} + +--- @return boolean +function M.is_dev_mode() + return IsInToolsMode() or GameRules:IsDev() or val.non_nil(Convars:GetBool("developer"), false) +end + +return M diff --git a/game/scripts/vscripts/invk/lang/function.lua b/game/scripts/vscripts/invk/lang/function.lua new file mode 100644 index 0000000..c3d2e07 --- /dev/null +++ b/game/scripts/vscripts/invk/lang/function.lua @@ -0,0 +1,95 @@ +local tbl = require("invk.lang.table") + +--- Function helpers. +--- @class invk.lang.function +local M = {} + +--- @generic Bound, Unbound, Ret +--- @param f fun(...: Bound, ...: Unbound): Ret... +--- @param ... Bound # Bound arguments +--- @return fun(...: Unbound): Ret... +function M.bind(f, ...) + --- @type Bound[] + local bound_args = { ... } + + --- @param ... Unbound + --- @return Ret... + return function(...) + local args = tbl.append(bound_args, { ... }) + + return f(table.unpack(args)) + end +end + +--- @generic T +--- @return fun(left: T, right: T): boolean +function M.eq() + --- @param left T + --- @param right T + --- @return boolean + return function(left, right) + return left == right + end +end + +--- @generic T +--- @param left T +--- @return fun(right: T): boolean +function M.is_eq(left) + return M.bind(M.eq(), left) +end + +--- @generic T, U +--- @return fun(left: T, right: U): (T | U) +function M.sum() + --- @param left T + --- @param right U + --- @return T | U + return function(left, right) + return left + right + end +end + +--- Creates a wrapper function that performs method lookup by name on a table. +--- +--- The created function will perform method lookup by name on the given table, +--- then call the method passing all parameters it received. +--- +--- ```lua +--- local t = {} +--- function t.greet(name) return "Greetings, " .. name end +--- print(t.greet) +--- -- => function: 0x7fffc9367cc0 +--- local fn = lookupbyname(t, "greet") +--- -- Equivalent to calling `t["greet"]("Alice")` +--- print(fn("Alice")) +--- -- => "Greetings, Alice" +--- -- t.greet() can be overridden and is still looked up by name: +--- function t.greet(name) return "Welcome, " .. name end +--- print(t.greet) +--- -- => function: 0x7fffc9367ef0 +--- print(fn("Alice")) +--- -- => "Welcome, Alice" +--- ``` +--- +--- @param t table # Table object +--- @param name string # Method name +--- @return fun(...: any): any... # Wrapper function +function M.lookupbyname(t, name) + return function(...) + return t[name](...) + end +end + +--- @generic Args, T +--- @param class T | { new: (fun(self: T, ...: Args): T) } +--- @return fun(...: Args): T +function M.ctor(class) + --- @param ... Args + --- @return T + return function(...) + return class:new(...) + end +end + +return M diff --git a/game/scripts/vscripts/invk/lang/global.lua b/game/scripts/vscripts/invk/lang/global.lua new file mode 100644 index 0000000..95bdd0d --- /dev/null +++ b/game/scripts/vscripts/invk/lang/global.lua @@ -0,0 +1,24 @@ +--# selene: allow(global_usage) + +_G.F = string.format +_G.S = tostring + +--- Single-value [assert] with string formatted message. +--- @generic T +--- @param expr T? +--- @param fmt string +--- @param ... any +--- @return T - ? +function assertf(expr, fmt, ...) + -- pin single-value return + local value = assert(expr, F(fmt, ...)) + + return value +end + +--- [error] with string formatted message. +--- @param fmt string +--- @param ... any +function errorf(fmt, ...) + error(F(fmt, ...), 2) +end diff --git a/game/scripts/vscripts/invk/lang/random.lua b/game/scripts/vscripts/invk/lang/random.lua new file mode 100644 index 0000000..7d9c32e --- /dev/null +++ b/game/scripts/vscripts/invk/lang/random.lua @@ -0,0 +1,18 @@ +--- Random helpers. +--- @class invk.lang.random +local M = {} + +--- Seeds random generation. +--- @param seed? integer # Seed value (default: `Time()`) +--- @return integer # Seed number +function M.seed(seed) + seed = seed or ( + Time() --[[@as integer]] + ) + + math.randomseed(seed) + + return seed +end + +return M diff --git a/game/scripts/vscripts/invk/lang/string.lua b/game/scripts/vscripts/invk/lang/string.lua new file mode 100644 index 0000000..4f43baf --- /dev/null +++ b/game/scripts/vscripts/invk/lang/string.lua @@ -0,0 +1,79 @@ +--- @class invk.lang.string +local M = {} + +--- Remove whitespace from start and end of a string. +--- @param s string +--- @return string +function M.trim(s) + -- ignore multi-value return + s = s:gsub("^%s*", ""):gsub("%s*$", "") + + return s +end + +--- Split a string at separator. +--- @param s string +--- @param sep string +--- @param count? integer +--- @return string[] +function M.split(s, sep, count) + if count == nil then + count = -1 + end + + if count == 1 then + return { s } + end + + local res = {} + + local n = 0 + --- @type integer? + local i = 1 + --- @type integer? + local j + + i, j = s:find(sep, 1, true) + + while i and j do + res[#res + 1] = s:sub(1, i - 1) + n = n + 1 + s = s:sub(j + 1) + + if count > 1 and n == (count - 1) then + res[#res + 1] = s + s = "" + + break + end + + i, j = s:find(sep, 1, true) + end + + if #s > 0 then + res[#res + 1] = s + end + + if #res == 0 then + res = { s } + end + + return res +end + +--- Return the maximum string length in a list of strings. +--- @param t string[] +--- @return integer +function M.max_len(t) + local max = 0 + + for _, s in ipairs(t) do + if #s > max then + max = #s + end + end + + return max +end + +return M diff --git a/game/scripts/vscripts/invokation/lang/stub.lua b/game/scripts/vscripts/invk/lang/stub.lua similarity index 86% rename from game/scripts/vscripts/invokation/lang/stub.lua rename to game/scripts/vscripts/invk/lang/stub.lua index 996e990..9a74a2e 100644 --- a/game/scripts/vscripts/invokation/lang/stub.lua +++ b/game/scripts/vscripts/invk/lang/stub.lua @@ -1,5 +1,4 @@ --- Stubs for stdlib modules not present in Dota's Lua VM. --- @module invokation.lang.stub -- selene: allow(global_usage) if _G.io == nil then diff --git a/game/scripts/vscripts/invk/lang/table.lua b/game/scripts/vscripts/invk/lang/table.lua new file mode 100644 index 0000000..532c855 --- /dev/null +++ b/game/scripts/vscripts/invk/lang/table.lua @@ -0,0 +1,370 @@ +--- @class invk.lang.table +local M = {} + +--- Count the number of items in a table. +--- @param t table +--- @return integer +function M.size(t) + local i = 0 + + for _, _ in pairs(t) do + i = i + 1 + end + + return i +end + +--- Check if table is empty. +--- @param t table +--- @return boolean +function M.is_empty(t) + return M.size(t) == 0 +end + +--- Clone a table. +--- @generic K, V +--- @param t { [K]: V } +--- @param deep? boolean +--- @return { [K]: V } +function M.clone(t, deep) + local res = {} + + for k, v in pairs(t) do + if type(v) == "table" and deep then + res[k] = M.clone(v, deep) + else + res[k] = v + end + end + + return res +end + +--- Collect table keys. +--- @generic K, V +--- @param t { [K]: V } +--- @return K[] +--- @overload fun(t: V[]): integer[] +function M.keys(t) + local res = {} + + for k, _ in pairs(t) do + res[#res + 1] = k + end + + return res +end + +--- Collect table values. +--- @generic K, V +--- @param t { [K]: V } +--- @return V[] +function M.values(t) + local res = {} + + for _, v in pairs(t) do + res[#res + 1] = v + end + + return res +end + +--- Get the maximum value in a table. +--- @generic K, V +--- @param t { [K]: V } +--- @return V +function M.max(t) + --- @type V + local max = nil + + for _, v in pairs(t) do + if max == nil or v > max then + max = v + end + end + + return max +end + +--- @generic K, V +--- @param t { [K]: V } +--- @param value V | (fun(v: V): boolean) +--- @return K? +--- @overload fun(t: V[], value: V | (fun(v: V): boolean)): integer? +function M.index(t, value) + --- @type fun(elem: V): boolean + local matcher + + if type(value) == "function" then + matcher = value + else + matcher = function(elem) + return elem == value + end + end + + for k, v in pairs(t) do + if matcher(v) then + return k + end + end + + return nil +end + +--- Pick values at given indices. +--- @generic T +--- @param t T[] +--- @param ... integer +--- @return T[] +function M.at(t, ...) + --- @type T[] + local res = {} + + for i = 1, select("#", ...) do + local index = select(i, ...) + + res[#res + 1] = t[index] + end + + return res +end + +--- Pick values at given keys. +--- @generic K, V +--- @param t { [K]: V } +--- @param ... K +--- @return { [K]: V } +function M.select(t, ...) + local res = {} + + for i = 1, select("#", ...) do + local key = select(i, ...) + + res[key] = t[key] + end + + return res +end + +--- Slices a list with given range. +--- @generic T +--- @param t T[] +--- @param i? integer +--- @param j? integer +--- @return T[] +function M.slice(t, i, j) + i = i or 1 + j = j or #t + + local res = {} + + for n = i, j do + res[#res + 1] = t[n] + end + + return res +end + +--- Append values to list. +--- @generic T +--- @param t T[] +--- @param ... T[] +--- @return T[] +function M.append(t, ...) + local tt = { ... } + + table.insert(tt, 1, t) + + --- @type T[] + local res = {} + + for _, src in ipairs(tt) do + for _, value in ipairs(src) do + res[#res + 1] = value + end + end + + return res +end + +--- Converts a sparse list to continous list. +--- @generic T +--- @param t { [integer]: T } +--- @return T[] +function M.compact(t) + --- @type T[] + local res = {} + local indices = M.keys(t) + + table.sort(indices) + + for _, i in ipairs(indices) do + res[#res + 1] = t[i] + end + + return res +end + +--- Extend a table with other tables. +--- +--- **Modifies `t` in-place!** +--- @generic T1: table +--- @generic T2: table +--- @param t T1 +--- @param ... T2 +--- @return T1 | T2 +function M.extend(t, ...) + local tt = { ... } + + for _, src in ipairs(tt) do + for k, v in pairs(src) do + t[k] = v + end + end + + return t +end + +--- Filter table entries that matches a predicate. +--- @generic K, V +--- @param t { [K]: V } +--- @param filter fun(value: V, key: K): boolean +--- @return { [K]: V } +--- @overload fun(t: V[], filter: (fun(value: V, index: integer): boolean)): V[] +function M.filter(t, filter) + return M.map(t, function(value, key) + if filter(value, key) then + return value + else + return nil + end + end) +end + +--- Map table entries with the given map function. +--- @generic K1, V1, K2, V2 +--- @param t { [K1]: V1 } +--- @param map (fun(value: V1, key: K1): V2?) +--- @return { [K2]: V2 } +--- @overload fun(t: V1[], map: (fun(value: V1, index: integer): V2?)): V2[] +function M.map(t, map) + if t == nil then + return {} + end + + --- @type { [K2]: V2 } + local res = {} + + for k1, v1 in pairs(t) do + -- if `map` doesn't return (key, value), the return type is (value,) + local kv, v2 = map(v1, k1) + local key = v2 and kv or k1 + local value = v2 or kv + + res[key] = value + end + + return res +end + +--- Alias of [map]. +--- @generic K1, V1, K2, V2 +--- @param t { [K1]: V1 } +--- @param transform (fun(value: V1, key: K1): K2?, V2?) +--- @return { [K2]: V2 } +--- @overload fun(t: V1[], map: (fun(value: V1, index: integer): K2?, V2?)): { [K2]: V2 } +function M.transform(t, transform) + return M.map(t, transform) +end + +--- Reduce table values with the given reduce function. +--- @generic K, V, R +--- @param t { [K]: V } +--- @param reduce fun(acc: R, value: V, key: K): R +--- @param init? R +--- @return R +--- @overload fun(t: V[], reduce: (fun(acc: R, value: V, index: integer): R), init: R): R +--- @overload fun(t: V[], reduce: (fun(acc: V, value: V): V)): V +function M.reduce(t, reduce, init) + if t == nil then + return init + end + + local acc = init + local first = true + + for k, v in pairs(t) do + if first and not init then + acc = v + else + acc = reduce(acc, v, k) + end + + first = false + end + + return acc +end + +--- Returns the difference between two lists. +--- @generic T +--- @param left T[] +--- @param right T[] +--- @return T[] +function M.diff(left, right) + return M.filter(left, function(value) + return not M.contains(right, value) + end) +end + +--- Tests if a table contains a value. +--- @generic K, V +--- @param t { [K]: V } +--- @param value V +--- @param eq? fun(left: V, right: V): boolean +--- @return boolean +--- @overload fun(t: V[], value: V): boolean +function M.contains(t, value, eq) + if t == nil then + return false + end + + for _, v in pairs(t) do + --- @type boolean + local is_eq + + if eq then + is_eq = eq(value, v) + else + is_eq = value == v + end + + if is_eq then + return true + end + end + + return false +end + +--- Tests if every entry of a table matches a predicate. +--- @generic K, V +--- @param t { [K]: V } +--- @param predicate fun(value: V, key: K): boolean +--- @return boolean +function M.all(t, predicate) + if t == nil then + return true + end + + for k, v in pairs(t) do + if not predicate(k, v) then + return false + end + end + + return true +end + +return M diff --git a/game/scripts/vscripts/invk/lang/value.lua b/game/scripts/vscripts/invk/lang/value.lua new file mode 100644 index 0000000..4775381 --- /dev/null +++ b/game/scripts/vscripts/invk/lang/value.lua @@ -0,0 +1,21 @@ +--- Value helpers. +--- @class invk.lang.value +local M = {} + +--- Returns the first non-nil value +--- @generic T +--- @param ... T +--- @return T - ? +function M.non_nil(...) + for i = 1, select("#", ...) do + local value = select(i, ...) + + if value ~= nil then + return value + end + end + + return nil +end + +return M diff --git a/game/scripts/vscripts/invk/logger.lua b/game/scripts/vscripts/invk/logger.lua new file mode 100644 index 0000000..f0ed344 --- /dev/null +++ b/game/scripts/vscripts/invk/logger.lua @@ -0,0 +1,230 @@ +local class = require("middleclass") +local inspect = require("inspect") + +--- Logger class. +--- @class invk.Logger : middleclass.Class, invk.log.LevelHelpers +--- @field name string +--- @field level invk.log.Level +--- @field format string +local M = class("invk.Logger") + +--- @enum invk.log.Level +M.Level = { + --- Debug + DEBUG = 10, + --- Info + INFO = 20, + --- Warning + WARNING = 30, + --- Error + ERROR = 40, + --- Critical + CRITICAL = 50, +} + +--- Level names +--- @type { [invk.log.Level]: string } +M.LevelName = { + [M.Level.DEBUG] = "debug", + [M.Level.INFO] = "info", + [M.Level.WARNING] = "warning", + [M.Level.ERROR] = "error", + [M.Level.CRITICAL] = "critical", +} + +--- Default level. (`INFO`) +M.DEFAULT_LEVEL = M.Level.INFO +--- Default format. (`"{timestamp} ({severity}) [{name}] {message}"`) +M.DEFAULT_FORMAT = "{timestamp} ({severity}) [{name}] {message}" + +--- @param i integer +--- @param value any +--- @return string +local function format_value(i, value) + -- Treat first string argument as the title text for the log message and + -- return it as is. All other strings are serialized. + if i == 1 and type(value) == "string" then + return value + end + + return inspect(value) +end + +--- Constructor. +--- @param name (string | string[]) Log name +--- @param level? integer One of the logger levels (default: [DEFAULT_LEVEL]) +--- @param format? string Log entry format (default: [DEFAULT_FORMAT]) +function M:initialize(name, level, format) + self.level = level or M.DEFAULT_LEVEL + self.format = format or M.DEFAULT_FORMAT + + if type(name) == "table" then + name = table.concat(name, ".") + end + + self.name = name +end + +--- Creates a new Logger instance that inherits from the current instance. +--- @param name string Child log name +--- @return invk.Logger Child instance +function M:child(name) + return M:new({ self.name, name }, self.level, self.format) +end + +--- Logs a message if the current logger level is lower than the given level. +--- +--- It generates all log entry components (timestamp, severity, ame and message) +--- and replaces in the message template format. +--- +--- Components: +--- +--- * `timestamp`: current date and time +--- * `severity`: logger level name +--- * `name`: name given in constructor +--- * `message`: serializes all vararg values in a pretty format and joins them +--- with a single space +--- @param level invk.log.Level # One of the logger levels +--- @param ... any # Values +function M:log(level, ...) + if level < self.level then + return + end + + --- @type string[] + local formatted = {} + + -- Explicitly iterate with actual arguments array size to correctly print `nil` + -- values at the end of the array which are ignored in `{...}` + for i = 1, select("#", ...) do + local value = select(i, ...) + + table.insert(formatted, format_value(i, value)) + end + + local values = { + ["{timestamp}"] = GetSystemDate() .. " " .. GetSystemTime(), + ["{severity}"] = M.LevelName[level], + ["{name}"] = self.name, + ["{message}"] = table.concat(formatted, " "), + } + + local message = self.format:gsub("%b{}", values) + + print(message) +end + +--- Logs a formatted message if the current logger level is lower than the given level. +--- @param level invk.log.Level # One of the logger levels +--- @param fmt string # Format string +--- @param ... any # Values +function M:logf(level, fmt, ...) + if level < self.level then + return + end + + return self:log(level, F(fmt, ...)) +end + +--- @class invk.log.LogApi +--- @field log fun(self: self, level: invk.log.Level, ...: any) +--- @field logf fun(self: self, level: invk.log.Level, fmt: string, ...: any) + +--- @class invk.log.LevelHelpers : invk.log.LogApi +--- Logs a message with DEBUG level +--- @field debug fun(self: self, ...: any) +--- Logs a formatted message with DEBUG level +--- @field debugf fun(self: self, fmt: string, ...: any) +--- Logs a message with INFO level +--- @field info fun(self: self, ...: any) +--- Logs a formatted message with INFO level +--- @field infof fun(self: self, fmt: string, ...: any) +--- Logs a message with WARNING level +--- @field warning fun(self: self, ...: any) +--- Logs a formatted message with WARNING level +--- @field warningf fun(self: self, fmt: string, ...: any) +--- Logs a message with ERROR level +--- @field error fun(self: self, ...: any) +--- Logs a formatted message with ERROR level +--- @field errorf fun(self: self, fmt: string, ...: any) +--- Logs a message with CRITICAL level +--- @field critical fun(self: self, ...: any) +--- Logs a formatted message with CRITICAL level +--- @field criticalf fun(self: self, fmt: string, ...: any) + +--- @param mod invk.log.LogApi +local function create_level_methods(mod) + for _, level in pairs(M.Level) do + local name = M.LevelName[level] + local fn_name = name + local fn_name_f = name .. "f" + + -- function M:debug(...) ... end + --- @param self invk.log.LogApi + --- @param ... any + mod[fn_name] = function(self, ...) + self:log(level, ...) + end + + -- function M:debugf(...) ... end + --- @param self invk.log.LogApi + --- @param fmt string + --- @param ... any + mod[fn_name_f] = function(self, fmt, ...) + self:logf(level, fmt, ...) + end + end +end + +create_level_methods(M) + +--- Helpers Mixin. +--- Requires a `self.logger` [invk.Logger] field. +--- @class invk.log.Mixin : { logger: invk.Logger? }, invk.log.LevelHelpers +M.Mixin = {} + +--- @param level invk.log.Level # One of the logger levels +--- @param ... any # Values +function M.Mixin:log(level, ...) + if not self.logger then + return + end + + self.logger:log(level, ...) +end + +--- @param level invk.log.Level # One of the logger levels +--- @param fmt string # Format string +--- @param ... any # Values +function M.Mixin:logf(level, fmt, ...) + if not self.logger then + return + end + + self.logger:logf(level, fmt, ...) +end + +--- Shortcut for [invk.Logger:debug] +--- @param ... any +function M.Mixin:d(...) + if not self.logger then + return + end + + self.logger:debug(...) +end + +--- Shortcut for [invk.Logger:warningf] +--- @param fmt string +--- @param ... any +function M.Mixin:warnf(fmt, ...) + if not self.logger then + return + end + + self.logger:warningf(fmt, ...) +end + +create_level_methods(M.Mixin) + +return M diff --git a/game/scripts/vscripts/invokation/GameMode.lua b/game/scripts/vscripts/invokation/GameMode.lua deleted file mode 100644 index dfc471a..0000000 --- a/game/scripts/vscripts/invokation/GameMode.lua +++ /dev/null @@ -1,135 +0,0 @@ ---- Main class for the game. --- @classmod invokation.GameMode - -local class = require("pl.class") - --- selene: allow(global_usage) -if _G.GameMode == nil then - _G.GameMode = class() -end - -require("invokation.game_mode.net_tables") -require("invokation.game_mode.game_rules") -require("invokation.game_mode.game_mode") -require("invokation.game_mode.events") -require("invokation.game_mode.commands") -require("invokation.game_mode.convars") - -local Combos = require("invokation.combos.Combos") -local Env = require("invokation.game_mode.env") -local ItemsKeyValues = require("invokation.dota2.kv.ItemsKeyValues") -local Logger = require("invokation.Logger") -local NetTable = require("invokation.dota2.NetTable") -local Timers = require("invokation.dota2.timers") -local func = require("invokation.lang.function") -local m = require("moses") -local rand = require("invokation.lang.random") - -local NET_TABLE = require("invokation.const.net_table") -local PRECACHE = require("invokation.const.precache") - -local LOGGER_PROGNAME = "invokation" - ---- Initialization --- @section init - --- selene: allow(unscoped_variables) -GameMode.META = require("invokation.const.metadata") --- selene: allow(unscoped_variables) -GameMode._VERSION = GameMode.META.version - -Logger.Extend(GameMode) - ---- Precaches resources/units/items/abilities that will be needed for sure in --- your game and that will not be precached by hero selection. --- --- When a hero is selected from the hero selection screen, the game will --- precache that hero's assets, any equipped cosmetics, and perform the --- data-driven precaching defined in that hero's `precache{}` block, as well as --- the `precache{}` block for any equipped abilities. -function GameMode.Precache(context) - for _, name in ipairs(PRECACHE.UNITS) do - PrecacheUnitByNameSync(name, context) - end - - for path, resType in pairs(PRECACHE.RESOURCES) do - PrecacheResource(resType, path, context) - end -end - ---- Constructor. --- @tparam[opt] table options Options table --- @tparam[opt] string options.env Environment -function GameMode:_init(options) - options = options or {} - options.env = options.env or (IsInToolsMode() and Env.DEVELOPMENT or Env.PRODUCTION) - - self.users = {} - self.players = {} - self.env = Env(options.env) - self.logger = Logger(LOGGER_PROGNAME, self.env.development and Logger.DEBUG or Logger.INFO) - self.itemsKV = ItemsKeyValues() - - self.netTables = m.map(NET_TABLE, function(t) - return NetTable(t.NAME) - end) - - self.combos = Combos(self.netTables.MAIN, { logger = self.logger }) -end - -function GameMode:fnHandler(methodName) - return self.env.development and func.lookupbyname(GameMode, methodName) or GameMode[methodName] -end - -function GameMode:methodHandler(methodName) - return m.bind(self:fnHandler(methodName), self) -end - ---- Entry-point for the game initialization. -function GameMode:Activate() - if GameMode._reentrantCheck then - return - end - - self:d("Loading GameMode...") - - self:setupModules() - self:setupNetTables() - self:setupGameRules() - self:setupGameMode() - self:registerGameEvents() - self:registerCustomEvents() - self:registerCommands() - self:registerConVars() - - self:d("Done loading GameMode!") -end - -function GameMode:setupModules() - Timers:Start() - self:d(" setup Timers") - rand.seed() - self:d(" setup random") -end - ---- Used to set up async precache calls at the beginning of the gameplay. --- --- In this function, place all of your `PrecacheItemByNameAsync` and --- `PrecacheUnitByNameAsync`. These calls will be made after all players have --- loaded in, but before they have selected their heroes. --- `PrecacheItemByNameAsync` can also be used to precache dynamically-added --- datadriven abilities instead of items. `PrecacheUnitByNameAsync` will --- precache the `precache{}` block statement of the unit and all `precache{}` --- block statements for every `Ability#` defined on the unit. --- --- This function should only be called once. If you want to/need to precache --- more items/abilities/units at a later time, you can call the functions --- individually (for example if you want to precache units in a new wave of --- holdout). --- --- This function should generally only be used if @{Precache} is not working. -function GameMode:PostLoadPrecache() - self:d("Performing Post-Load precache") -end - -return GameMode diff --git a/game/scripts/vscripts/invokation/Logger.lua b/game/scripts/vscripts/invokation/Logger.lua deleted file mode 100644 index d4a8ac7..0000000 --- a/game/scripts/vscripts/invokation/Logger.lua +++ /dev/null @@ -1,283 +0,0 @@ ---- Logger class. --- @classmod invokation.Logger -local class = require("pl.class") -local moses = require("moses") -local pp = require("pl.pretty") -local stringx = require("pl.stringx") -local text = require("pl.text") - -local M = class() - ---- Logger Levels --- @section levels - ---- Unknown (outputs everything) --- @tfield int UNKNOWN -M.UNKNOWN = 0 ---- Debug --- @tfield int DEBUG -M.DEBUG = 10 ---- Info --- @tfield int INFO -M.INFO = 20 ---- Warning --- @tfield int WARNING -M.WARNING = 30 ---- Error --- @tfield int ERROR -M.ERROR = 40 ---- Critical --- @tfield int CRITICAL -M.CRITICAL = 50 - ---- Level names --- @table LEVEL_NAMES --- @tfield string UNKNOWN UNKNOWN --- @tfield string DEBUG DEBUG --- @tfield string INFO INFO --- @tfield string WARNING WARNING --- @tfield string ERROR ERROR --- @tfield string CRITICAL CRITICAL -M.LEVEL_NAMES = { - [M.UNKNOWN] = "UNKNOWN", - [M.DEBUG] = "DEBUG", - [M.INFO] = "INFO", - [M.WARNING] = "WARNING", - [M.ERROR] = "ERROR", - [M.CRITICAL] = "CRITICAL", -} - ---- Defaults --- @section defaults - ---- Default level. (`INFO`) -M.DEFAULT_LEVEL = M.INFO ---- Default format. (`"$timestamp ($severity) [$progname] $message"`) -M.DEFAULT_FORMAT = "$timestamp ($severity) [$progname] $message" - -local function formatValue(i, value) - -- Treat first string argument as the title text for the log message and - -- return it as is. All other strings are serialized. - if i == 1 and type(value) == "string" then - return value - end - - -- ignore multi-value return - local serialized = pp.write(value) - - return serialized -end - ---- Methods --- @section methods - ---- Constructor. --- @tparam string|{string,...} progname Program name --- @tparam[opt=DEFAULT_LEVEL] int level One of the logger levels --- @tparam[opt=DEFAULT_FORMAT] string format Log entry format -function M:_init(progname, level, format) - self.level = level or M.DEFAULT_LEVEL - self.format = format or M.DEFAULT_FORMAT - self.template = text.Template(self.format) - - if type(progname) == "table" then - progname = moses.join(progname, ".") - end - - self.progname = progname -end - ---- Creates a new Logger instance that inherits from the current instance. --- @tparam string progname Child program name --- @treturn Logger Child instance -function M:Child(progname) - return M({ self.progname, progname }, self.level, self.format) -end - ---- Logs a message if the current logger level is lower than the given level. --- --- It generates all log entry components (timestamp, severity, progname and --- message) and replaces in the message template format. --- --- Components: --- --- * `timestamp`: current date and time --- * `severity`: logger level name (@{LEVEL_NAMES}) --- * `progname`: progname given in constructor --- * `message`: serializes all vararg values in a pretty format and joins them --- with a single space --- @tparam int level One of the logger levels --- @param[opt] ... Values -function M:Log(level, ...) - if level < self.level then - return - end - - local values = { ... } - local formatted = {} - - -- Explicitly iterate with actual arguments array size to correctly print `nil` - -- values at the end of the array which are ignored in `{...}` - for i = 1, select("#", ...) do - table.insert(formatted, formatValue(i, values[i])) - end - - local tmplValues = { - timestamp = GetSystemDate() .. " " .. GetSystemTime(), - severity = M.LEVEL_NAMES[level], - progname = self.progname, - message = moses.join(formatted, " "), - } - - return print(self.template:substitute(tmplValues)) -end - ---- Logs a formatted message if the current logger level is lower than the --- given level. --- @tparam int level One of the logger levels --- @tparam string format Format string --- @param[opt] ... Values -function M:Logf(level, format, ...) - if level < self.level then - return - end - - return self:Log(level, format:format(...)) -end - ---- Logs a message with DEBUG level --- @function M:Debug --- @param[opt] ... Values - ---- Logs a formatted message with DEBUG level --- @function M:Debugf --- @tparam string format Format string --- @param[opt] ... Values - ---- Logs a message with INFO level --- @function M:Info --- @param[opt] ... Values - ---- Logs a formatted message with INFO level --- @function M:Infof --- @tparam string format Format string --- @param[opt] ... Values - ---- Logs a message with WARNING level --- @function M:Warning --- @param[opt] ... Values - ---- Logs a formatted message with WARNING level --- @function M:Warningf --- @tparam string format Format string --- @param[opt] ... Values - ---- Logs a message with ERROR level --- @function M:Error --- @param[opt] ... Values - ---- Logs a formatted message with ERROR level --- @function M:Errorf --- @tparam string format Format string --- @param[opt] ... Values - ---- Logs a message with CRITICAL level --- @function M:Critical --- @param[opt] ... Values - ---- Logs a formatted message with CRITICAL level --- @function M:Criticalf --- @tparam string format Format string --- @param[opt] ... Values - -local function createLevelMethods(levelName) - if levelName == "UNKNOWN" then - return - end - - local title = stringx.title(levelName) - - -- function M:Debug(...) ... end - M[title] = function(self, ...) - return self:Log(self[levelName], ...) - end - - -- function M:Debugf(...) ... end - M[title .. "f"] = function(self, ...) - return self:Logf(self[levelName], ...) - end -end - -for _, levelName in pairs(M.LEVEL_NAMES) do - createLevelMethods(levelName) -end - ---- HelpersMixin --- @section helpers_mixin - ---- Mixes @{HelpersMixin} into a class. --- @function invokation.Logger.Extend --- @tparam table cls Target class -function M.Extend(cls) - moses.extend(cls, M.HelpersMixin) -end - ---- Helpers Mixin. --- Assumes `self.logger` instance attribute holds a `Logger` instance. -M.HelpersMixin = {} - ---- Shortcut for `Logger.Debug` --- @function invokation.Logger.HelpersMixin:d -function M.HelpersMixin:d(...) - if not self.logger then - return - end - return self.logger:Debug(...) -end - ---- Shortcut for `Logger.Debugf` --- @function invokation.Logger.HelpersMixin:debugf -function M.HelpersMixin:debugf(...) - if not self.logger then - return - end - return self.logger:Debugf(...) -end - ---- Shortcut for `Logger.Warning` --- @function invokation.Logger.HelpersMixin:warn -function M.HelpersMixin:warn(...) - if not self.logger then - return - end - return self.logger:Warning(...) -end - ---- Shortcut for `Logger.Warningf` --- @function invokation.Logger.HelpersMixin:warnf -function M.HelpersMixin:warnf(...) - if not self.logger then - return - end - return self.logger:Warningf(...) -end - ---- Shortcut for `Logger.Error` --- @function invokation.Logger.HelpersMixin:err -function M.HelpersMixin:err(...) - if not self.logger then - return - end - return self.logger:Error(...) -end - ---- Shortcut for `Logger.Errorf` --- @function invokation.Logger.HelpersMixin:errf -function M.HelpersMixin:errf(...) - if not self.logger then - return - end - return self.logger:Errorf(...) -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/BaseCombo.lua b/game/scripts/vscripts/invokation/combos/BaseCombo.lua deleted file mode 100644 index 67498b0..0000000 --- a/game/scripts/vscripts/invokation/combos/BaseCombo.lua +++ /dev/null @@ -1,114 +0,0 @@ ---- BaseCombo is a base class for combos. --- @classmod invokation.combos.BaseCombo -local Logger = require("invokation.Logger") -local class = require("pl.class") -local moses = require("moses") - -local M = class() - -local LOGGER_PROGNAME = "combo" - -Logger.Extend(M) - -M.ERR_NOT_IMPLEMENTED = "Not implemented" - ---- Combo specification. --- @table Spec --- @tfield string id id --- @tfield string specialty Specialty --- @tfield string stance Stance --- @tfield int heroLevel Hero level --- @tfield int damageRating Damage rating --- @tfield int difficultyRating Difficulty rating --- @tfield int gold Hero starting gold --- @tfield {string,...} tags Tags --- @tfield {string,...} items Array of required items names --- @tfield {int,...} orbs Array of recommended orb abilities levels (`{quas, wex, exort}`) --- @tfield int talents Bitmap of recommended talent abilities --- @tfield {ComboStep.Spec,...} sequence Array of steps data - ---- Constructor. --- @tparam Spec spec Combo data --- @tparam[opt] table options Options --- @tparam Logger options.logger Logger instance -function M:_init(spec, options) - options = options or {} - - moses.extend(self, spec) - - self.started = false - self.failed = false - self.preFinished = false - self.finished = false - self.count = 0 - self.damage = 0 - - if options.logger then - self.logger = options.logger:Child(LOGGER_PROGNAME) - end -end - ---- Returns the current step id. --- @treturn ?int The current step id or `nil` --- @abstract Subclasses must override it. -function M:CurrentStepId() - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Returns the current step. --- @treturn ?combos.ComboStep The current step or `nil` --- @abstract Subclasses must override it. -function M:CurrentStep() - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Returns the current next steps ids. --- @treturn {int,...} Array of next steps ids --- @abstract Subclasses must override it. -function M:NextStepsIds() - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Returns the current next steps. --- @treturn {ComboStep,...} Array of next steps --- @abstract Subclasses must override it. -function M:NextSteps() - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Progresses the combo with the given ability if possible. --- @tparam dota2.Ability ability Ability instance --- @treturn bool `true` if succeeded, `false` otherwise --- @abstract Subclasses must override it. -function M:Progress(_ability) - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Marks the combo as failed. -function M:Fail() - self.failed = true -end - ---- Progresses combo to pre finish if possible. --- @treturn bool `true` if succeeded, `false` otherwise --- @abstract Subclasses must override it. -function M:PreFinish() - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Finishes the combo if possible. --- @treturn bool `true` if succeeded, `false` otherwise --- @abstract Subclasses must override it. -function M:Finish() - error(M.ERR_NOT_IMPLEMENTED) -end - ---- Increments the total amount of damage dealt during this combo session. --- @tparam int amount Damage amount --- @treturn int Accumulated damage amount -function M:IncrementDamage(amount) - self.damage = self.damage + amount - return self.damage -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/Combo.lua b/game/scripts/vscripts/invokation/combos/Combo.lua deleted file mode 100644 index aaa046b..0000000 --- a/game/scripts/vscripts/invokation/combos/Combo.lua +++ /dev/null @@ -1,128 +0,0 @@ ---- Combo class. --- @classmod invokation.combos.Combo -local BaseCombo = require("invokation.combos.BaseCombo") -local ComboSequence = require("invokation.combos.ComboSequence") -local class = require("pl.class") -local moses = require("moses") -local tablex = require("pl.tablex") - -local M = class(BaseCombo) - -local STATES = ComboSequence.STATES - -local WAIT_ABILITY_SPECIALS = { - invoker_alacrity = { "duration" }, - invoker_chaos_meteor = { "land_time", "burn_duration" }, - invoker_cold_snap = { "duration" }, - invoker_deafening_blast = { "disarm_duration" }, - invoker_emp = { "delay" }, - invoker_ice_wall = { "duration" }, - invoker_sun_strike = { "delay" }, - invoker_tornado = { "lift_duration" }, - item_black_king_bar = { "duration" }, - item_cyclone = { "cyclone_duration" }, - item_sheepstick = { "sheep_duration" }, - item_shivas_guard = { "blast_debuff_duration" }, -} - -local function abilityWait(ability) - if WAIT_ABILITY_SPECIALS[ability.name] == nil then - return ability:GetDuration() or 0 - end - - local function getSpecialValue(specialKey) - return ability:GetSpecialValueFor(specialKey) or 0 - end - - local values = moses.map(WAIT_ABILITY_SPECIALS[ability.name], getSpecialValue) - - return tablex.reduce("+", values) -end - ---- Constructor. --- @tparam BaseCombo.Spec spec Combo data --- @tparam[opt] table options Options --- @tparam Logger options.logger Logger instance --- @tparam function options.clock Clock function that returns the current time -function M:_init(spec, options) - self:super(spec, options) - - options = options or {} - - self.clock = options.clock or Time - self.sequence = ComboSequence(self.id, self.sequence, { clock = self.clock }) - self.waitQueue = {} -end - ---- Generates a DOT formatted string from the combo's FSM. --- @treturn string DOT string -function M:todot() - return self.sequence:todot() -end - ---- Returns the current step id. --- @treturn ?int The current step id or `nil` -function M:CurrentStepId() - return self.sequence.currentId -end - ---- Returns the current step. --- @treturn ?combos.ComboStep The current step or `nil` -function M:CurrentStep() - return self.sequence.current -end - ---- Returns the current next steps ids. --- @treturn {int,...} Array of next steps ids -function M:NextStepsIds() - return self.sequence.nextIds -end - ---- Returns the current next steps. --- @treturn {ComboStep,...} Array of next steps -function M:NextSteps() - return self.sequence.next -end - ---- Progresses the combo with the given ability if possible. --- @tparam dota2.Ability ability Ability instance --- @treturn bool `true` if succeeded, `false` otherwise -function M:Progress(ability) - local progressed = self.sequence:Progress(ability.name) - - if progressed then - self.started = true - self.count = self.count + 1 - - table.insert(self.waitQueue, self.clock() + abilityWait(ability)) - end - - return progressed -end - ---- Progresses combo to pre finish if possible. --- @treturn bool `true` if succeeded, `false` otherwise -function M:PreFinish() - self.preFinished = self.sequence:PreFinish() - - if self.preFinished then - self.waitTime = math.max(unpack(self.waitQueue)) - self.waitDuration = self.waitTime - self.sequence:EnterTime(STATES.PRE_FINISH) - end - - return self.preFinished -end - ---- Finishes combo if possible. --- @treturn bool `true` if succeeded, `false` otherwise -function M:Finish() - self.finished = self.sequence:Finish() - - if self.finished then - self.duration = self.sequence.duration - end - - return self.finished -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/ComboSequence.lua b/game/scripts/vscripts/invokation/combos/ComboSequence.lua deleted file mode 100644 index 41215d1..0000000 --- a/game/scripts/vscripts/invokation/combos/ComboSequence.lua +++ /dev/null @@ -1,151 +0,0 @@ ---- ComboSequence class. --- @classmod invokation.combos.ComboSequence -local ComboStep = require("invokation.combos.ComboStep") -local Logger = require("invokation.Logger") -local class = require("pl.class") -local fsm = require("fsm") -local m = require("moses") - -local M = class() - -Logger.Extend(M) - ---- Sequence states --- @table STATES --- @tfield string INITIAL Initial --- @tfield string PRE_FINISH Pre finish --- @tfield string FINISH Finish -M.STATES = { INITIAL = "start", PRE_FINISH = "pre_finish", FINISH = "finish" } - -local EVENTS = { PRE_FINISH = "pre_finish", FINISH = "finish" } - --- @todo Use an LRU cache -local CACHE = {} - -local function stepEvents(sequence, step) - return m.map(step.next or {}, function(nextId) - local nextStep = sequence[nextId] - - return { name = nextStep.event, from = step.state, to = nextStep.state } - end) -end - -local function fsmDef(sequence) - local firstStep = { name = M.STATES.INITIAL, state = M.STATES.INITIAL, next = { sequence[1].id } } - local preFinishStep = { - name = EVENTS.PRE_FINISH, - from = sequence[#sequence].state, - to = M.STATES.PRE_FINISH, - } - - local finishStep = { name = EVENTS.FINISH, from = M.STATES.PRE_FINISH, to = M.STATES.FINISH } - local steps = m.append({ firstStep }, sequence) - local events = m.chain(steps):map(m.partial(stepEvents, sequence)):flatten(true) - - events = events:push(preFinishStep):push(finishStep):value() - - return { initial = M.STATES.INITIAL, events = events } -end - ---- Constructor. --- @tparam int id Combo id --- @tparam {ComboStep.Spec,...} sequence Sequence of steps --- @tparam[opt] table options Options --- @tparam Logger options.logger Logger instance --- @tparam function options.clock Clock function that returns the current time -function M:_init(id, sequence, options) - options = options or {} - - self.id = id - self.logger = options.logger - self.clock = options.clock - self.sequence = m.map(sequence, ComboStep) - self.nextIds = { self.sequence[1].id } - self.next = { self.sequence[1] } - self.enterTimes = {} - self.leaveTimes = {} - - self:createFSM() -end - -function M:createFSM() - if CACHE[self.id] == nil then - CACHE[self.id] = fsmDef(self.sequence) - end - - self.fsm = fsm.create(CACHE[self.id]) - - self.fsm.onstatechange = function(_, _, from, to) - local now = self.clock() - - self.leaveTimes[from] = now - self.enterTimes[to] = now - self.currentId = ComboStep.StepId(to) - self.current = self.sequence[self.currentId] - self.nextIds = (self.current and self.current.next) or {} - self.next = m.at(self.sequence, unpack(self.nextIds)) - - self:debugState("state_change") - end - - self:debugState("start") -end - ---- Generates a DOT formatted string from the sequence's FSM. --- @treturn string DOT string -function M:todot() - return self.fsm:todot() -end - -function M:debugState(message) - local state = - { state = self.fsm.current, current = self.currentId or "", next = self.nextIds } - self:d(message, state) -end - ---- Returns the time when the sequence entered the given state. --- @tparam string state State name --- @treturn ?int Time or `nil` if state is invalid -function M:EnterTime(state) - return self.enterTimes[state] -end - ---- Returns the time when the sequence left the given state. --- @tparam string state State name --- @treturn ?int Time or `nil` if state is invalid -function M:LeaveTime(state) - return self.leaveTimes[state] -end - ---- Progresses the sequence with the given event if possible. --- @tparam string event Event --- @treturn bool `true` if succeeded, `false` otherwise -function M:Progress(event) - local eventFn = self.fsm[event] - - if eventFn == nil then - return false - end - - return eventFn(self.fsm) -end - ---- Progresses the sequence to pre finish if possible. --- @treturn bool `true` if succeeded, `false` otherwise -function M:PreFinish() - return self.fsm[EVENTS.PRE_FINISH](self.fsm) -end - ---- Finishes the sequence if possible. --- @treturn bool `true` if succeeded, `false` otherwise -function M:Finish() - local finished = self.fsm[EVENTS.FINISH](self.fsm) - - if finished then - self.duration = self:EnterTime(M.STATES.FINISH) - self:LeaveTime(M.STATES.INITIAL) - end - - return finished -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/ComboStep.lua b/game/scripts/vscripts/invokation/combos/ComboStep.lua deleted file mode 100644 index 94ade9e..0000000 --- a/game/scripts/vscripts/invokation/combos/ComboStep.lua +++ /dev/null @@ -1,47 +0,0 @@ ---- ComboStep class. --- @classmod invokation.combos.ComboStep -local class = require("pl.class") -local tablex = require("pl.tablex") - -local M = class() - ---- ComboStep specification. --- @table Spec --- @tfield int id Step id --- @tfield string name Step name (ability or item name) --- @tfield[opt=false] bool required Is step required or optional? --- @tfield[opt] {int,...} next Next steps ids (`nil` if it's the last step in the sequence) - ---- Generates a state name from a given step. --- @tparam ComboStep step Step instance --- @treturn string State name -function M.StateName(step) - return string.format("%d:%s", step.id, step.name) -end - ---- Extracts a step id from a given state name. --- @tparam string stateName State name --- @treturn int Step id, if state name is valid --- @treturn nil otherwise -function M.StepId(stateName) - local id = stateName:match("^(%d+):") - return id and tonumber(id) -end - ---- Generates an event name from a given step. --- @tparam ComboStep step Step instance --- @treturn string Event name -function M.EventName(step) - return step.name -end - ---- Constructor. --- @tparam Spec data Step data -function M:_init(data) - tablex.update(self, data) - - self.state = M.StateName(self) - self.event = M.EventName(self) -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/Combos.lua b/game/scripts/vscripts/invokation/combos/Combos.lua deleted file mode 100644 index 64461f8..0000000 --- a/game/scripts/vscripts/invokation/combos/Combos.lua +++ /dev/null @@ -1,426 +0,0 @@ ---- Combos manager. --- @classmod invokation.combos.Combos -local Combo = require("invokation.combos.Combo") -local CombosComm = require("invokation.combos.communication") -local CombosHero = require("invokation.combos.hero") -local CombosSound = require("invokation.combos.sound") -local DummyTarget = require("invokation.dota2.DummyTarget") -local FreestyleCombo = require("invokation.combos.FreestyleCombo") -local Logger = require("invokation.Logger") -local PlayerStates = require("invokation.combos.PlayerStates") -local Timers = require("invokation.dota2.timers") -local class = require("pl.class") - -local ABILITY_LIST = require("invokation.const.ability_list") -local NET_TABLE = require("invokation.const.net_table") - -local M = class() - -local LOGGER_PROGNAME = "combos" - -local ERRF_COMBO_NOT_FOUND = "Combo %q not found" -local ERRF_COMBO_NOT_ACTIVE = "Player %d has no active combo" -local WARNF_COMBO_NOT_FINISHED = "Combo %q can't be finished for player %d" - -Logger.Extend(M) - ---- Purchase specification. --- @table Purchase --- @tfield string item Item name --- @tfield number cost Purchase cost - ---- Level up options specification. --- --- If no options are given, levels hero up one level. --- --- @table LevelUpOptions --- @tfield[opt] int level Level up to specified level --- @tfield[opt=false] bool maxLevel Level up to max level - -local function loadSpecs() - local specs = require("invokation.const.combos") - - for id, spec in pairs(specs) do - spec.id = id - - for stepId, step in pairs(spec.sequence) do - step.id = stepId - end - end - - return specs -end - -local function isIgnoredAbility(ability) - local switch = ABILITY_LIST[ability.name] - - if switch == nil then - return false - end - - return not ABILITY_LIST[ability.name] -end - -local function isProgressingAbilities(combo) - return combo and not combo.failed and not combo.preFinished -end - -local function isProgressingDamage(combo) - return combo and combo.started and not combo.failed and not combo.finished -end - -local function isFreestyle(combo) - return (combo and combo.id) == FreestyleCombo.COMBO_ID -end - -local function gameTime() - return GameRules:GetGameTime() -end - ---- Constructor. --- @tparam dota2.NetTable netTable NetTable instance --- @tparam table options Options table --- @tparam Logger options.logger Logger instance -function M:_init(netTable, options) - options = options or {} - - self.netTable = netTable - self.state = PlayerStates() - - if options.logger then - self.logger = options.logger:Child(LOGGER_PROGNAME) - end - - self:load() -end - -function M:load() - self:d("Loading") - self.specs = loadSpecs() - - self.netTable:Set(NET_TABLE.MAIN.KEYS.COMBOS, self.specs) -end - -function M:Create(id) - if id == FreestyleCombo.COMBO_ID then - return FreestyleCombo({ logger = self.logger }) - end - - local spec = self.specs[id] - - if spec == nil then - local err = ERRF_COMBO_NOT_FOUND:format(id) - - self:err(err) - error(err) - end - - return Combo(spec, { logger = self.logger, clock = gameTime }) -end - -function M:requireCombo(player) - local combo = self.state[player].combo - - if combo == nil then - local err = ERRF_COMBO_NOT_ACTIVE:format(player:GetPlayerID()) - - self:err(err) - error(err) - end - - return combo -end - -function M:setup(player, combo) - self.state[player].combo = combo - - CombosHero.setup(player, combo) - - local dummy = self.state[player].dummy - - if dummy == nil then - dummy = DummyTarget() - self.state[player].dummy = dummy - - CombosSound.onDummyCreate(dummy) - end - - dummy:Spawn() -end - -function M:teardown(player, options) - options = options or {} - - self.state[player].combo = nil - - CombosHero.teardown(player, options) - - local dummy = self.state[player].dummy - - if dummy ~= nil then - dummy:Kill() - end -end - -function M:start(player, combo) - self:setup(player, combo) - - CombosSound.onComboStart(player) - CombosComm.sendStarted(player, combo) -end - -function M:stop(player, combo) - self:teardown(player, { hardReset = true }) - - CombosSound.onComboStop(player) - CombosComm.sendStopped(player, combo) -end - ---- Handles ability usage. --- @tparam CDOTAPlayer player Player instance --- @tparam dota2.Unit unit Unit instance --- @tparam dota2.Ability ability Ability instance -function M:OnAbilityUsed(player, unit, ability) - if isIgnoredAbility(ability) then - self:d( - "OnAbilityUsed [ignored]", - { player = player:GetPlayerID(), unit = unit.name, ability = ability.name } - ) - - return - end - - self:d( - "OnAbilityUsed", - { player = player:GetPlayerID(), unit = unit.name, ability = ability.name } - ) - - self:CaptureAbility(player, ability) - self:Progress(player, ability) -end - ---- Handles damage instances being dealt to entities. --- @tparam dota2.DamageInstance damage DamageInstance instance -function M:OnEntityHurt(damage) - local player = damage:AttackerPlayerOwner() - - if player == nil then - self:d("OnEntityHurt [ignored]", { category = damage.category, amount = damage.amount }) - - return - end - - self:d("OnEntityHurt", { - category = damage.category, - amount = damage.amount, - victim = damage:VictimName(), - attacker = damage:AttackerName(), - inflictor = damage:InflictorName(), - }) - - self:ProgressDamage(player, damage) -end - ---- Handles item purchases. --- @tparam CDOTAPlayer player Player instance --- @tparam Purchase purchase Purchase information -function M:OnItemPurchased(player, purchase) - local combo = self.state[player].combo - - if not isFreestyle(combo) then - self:d("OnItemPurchased [ignored]", { player = player:GetPlayerID(), purchase = purchase }) - - return - end - - self:d("OnItemPurchased", { player = player:GetPlayerID(), purchase = purchase }) - - CombosHero.refundPurchase(player, purchase) -end - ---- Starts a combo for the given player. --- @tparam CDOTAPlayer player Player instance --- @tparam Combo combo Combo -function M:Start(player, combo) - self:d("Start", { player = player:GetPlayerID(), id = combo.id }) - - local current = self.state[player].combo - - if current ~= nil and current.id ~= combo.id then - self:stop(player, current) - else - self:teardown(player, { hardReset = current == nil }) - end - - self:start(player, combo) -end - ---- Stops currently active combo for the given player. --- @tparam CDOTAPlayer player Player instance -function M:Stop(player) - self:d("Stop", { player = player:GetPlayerID() }) - - local combo = self:requireCombo(player) - - self:stop(player, combo) -end - ---- Restarts a combo for the given player. --- @tparam CDOTAPlayer player Player instance --- @tparam table options Options table --- @tparam[opt=false] bool options.hardReset Hard reset -function M:Restart(player, options) - self:d("Restart", { player = player:GetPlayerID(), options = options }) - - local combo = self:requireCombo(player) - - self:teardown(player, options) - - combo = self:Create(combo.id) - - self:start(player, combo) -end - ---- Progresses the currently active combo for the given player. --- @tparam CDOTAPlayer player Player instance --- @tparam dota2.Ability ability Ability instance -function M:Progress(player, ability) - local combo = self.state[player].combo - - if not isProgressingAbilities(combo) then - self:d("Progress [ignored]", { player = player:GetPlayerID(), ability = ability.name }) - - return - end - - self:d("Progress", { player = player:GetPlayerID(), ability = ability.name }) - - if combo:Progress(ability) then - if combo.count == 1 then - CombosComm.sendInProgress(player, combo) - end - - CombosComm.sendProgress(player, combo) - - if combo:PreFinish() then - self:PreFinish(player) - end - elseif not ability:IsInvocationAbility() then - self:Fail(player, ability) - end -end - ---- Increments the damage amount of the currently active combo for the given player. --- @tparam CDOTAPlayer player Player instance --- @tparam dota2.DamageInstance damage DamageInstance instance -function M:ProgressDamage(player, damage) - local combo = self.state[player].combo - - if not isProgressingDamage(combo) then - self:d( - "ProgressDamage [ignored]", - { player = player:GetPlayerID(), category = damage.category, amount = damage.amount } - ) - - return - end - - self:d("ProgressDamage", { - player = player:GetPlayerID(), - category = damage.category, - amount = damage.amount, - victim = damage:VictimName(), - attacker = damage:AttackerName(), - inflictor = damage:InflictorName(), - }) - - -- @fixme Only increment damage coming from currently active spells (including - -- forged spirits) or autoattacks - combo:IncrementDamage(damage.amount) - CombosComm.sendProgress(player, combo) -end - ---- Fails and stops currently active combo for the given player. --- @tparam CDOTAPlayer player Player instance --- @tparam dota2.Ability ability Ability instance -function M:Fail(player, ability) - self:d("Fail", { player = player:GetPlayerID() }) - - local combo = self:requireCombo(player) - - combo:Fail() - - CombosSound.onComboStepError(player) - CombosComm.sendStepError(player, combo, ability) -end - ---- Preemptively finishes a combo for the given player. --- @tparam CDOTAPlayer player Player instance -function M:PreFinish(player) - self:d("PreFinish", { player = player:GetPlayerID() }) - - local combo = self:requireCombo(player) - - CombosComm.sendPreFinish(player, combo) - - Timers:Create({ delay = combo.waitDuration, callback = self.Finish, args = { self, player } }) -end - ---- Finishes a combo for the given player. --- @tparam CDOTAPlayer player Player instance -function M:Finish(player) - self:d("Finish", { player = player:GetPlayerID() }) - - local combo = self:requireCombo(player) - - if not combo:Finish() then - self:warnf(WARNF_COMBO_NOT_FINISHED, combo.id, player:GetPlayerID()) - return - end - - self:d("Finished", { id = combo.id, now = gameTime() }) - - CombosSound.onComboFinished(player) - CombosComm.sendFinished(player, combo) -end - ---- Starts capturing ability usage for the given player. --- @tparam CDOTAPlayer player Player instance -function M:StartCapturingAbilities(player) - self:d("StartCapturingAbilities", { player = player:GetPlayerID() }) - self.state[player].capturing = true -end - ---- Stops capturing ability usage for the given player. --- @tparam CDOTAPlayer player Player instance -function M:StopCapturingAbilities(player) - self:d("StopCapturingAbilities", { player = player:GetPlayerID() }) - self.state[player].capturing = nil -end - ---- Captures an instance of ability usage for the given player. --- @tparam CDOTAPlayer player Player instance --- @tparam dota2.Ability ability Ability instance -function M:CaptureAbility(player, ability) - if self.state[player].capturing then - CombosComm.sendAbilityUsed(player, ability) - end -end - ---- Handles freestyle hero level up. --- @tparam CDOTAPlayer player Player instance --- @tparam LevelUpOptions options -function M:FreestyleHeroLevelUp(player, options) - local combo = self.state[player].combo - - if not isFreestyle(combo) then - self:d("FreestyleHeroLevelUp [ignored]", { player = player:GetPlayerID(), options = options }) - return - end - - self:d("FreestyleHeroLevelUp", { player = player:GetPlayerID(), options = options }) - - CombosHero.levelUp(player, options) -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/FreestyleCombo.lua b/game/scripts/vscripts/invokation/combos/FreestyleCombo.lua deleted file mode 100644 index d8ecef6..0000000 --- a/game/scripts/vscripts/invokation/combos/FreestyleCombo.lua +++ /dev/null @@ -1,76 +0,0 @@ ---- FreestyleCombo is a Combo class that implements a freestyle sequence. --- @classmod invokation.combos.FreestyleCombo -local BaseCombo = require("invokation.combos.BaseCombo") -local class = require("pl.class") - -local M = class(BaseCombo) - ---- Hard-coded combo id. --- @tfield string COMBO_ID -M.COMBO_ID = "freestyle" - -local SPEC = { id = M.COMBO_ID, heroLevel = 1, gold = 99999, items = {} } - ---- Constructor. --- @tparam[opt] table options Options --- @tparam Logger options.logger Logger instance -function M:_init(options) - self:super(SPEC, options) - self.started = true -end - ---- Freestyle combos have no steps. --- @treturn nil -function M:CurrentStepId() - return nil -end - ---- Freestyle combos have no steps. --- @treturn nil -function M:CurrentStep() - return nil -end - ---- Freestyle combos have no steps. --- @treturn {int,...} Always returns an empty array -function M:NextStepsIds() - return {} -end - ---- Freestyle combos have no steps. --- @treturn {int,...} Always returns an empty array -function M:NextSteps() - return {} -end - ---- Always progresses the combo with the given ability. --- @tparam dota2.Ability ability Ability instance --- @treturn bool `true` -function M:Progress(ability) - if ability:IsInvocationAbility() then - return false - end - - self.count = self.count + 1 - - return true -end - ---- Freestyle combos never fail. -function M:Fail() - return -end - ---- Freestyle combos never pre finish. --- @treturn bool `false` -function M:PreFinish() - return false -end - ---- Freestyle combos never finish. --- @treturn bool `false` -function M:Finish() - return false -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/PlayerStates.lua b/game/scripts/vscripts/invokation/combos/PlayerStates.lua deleted file mode 100644 index 207ec26..0000000 --- a/game/scripts/vscripts/invokation/combos/PlayerStates.lua +++ /dev/null @@ -1,25 +0,0 @@ ---- PlayerStates class. --- @classmod invokation.combos.PlayerStates -local class = require("pl.class") - -local M = class() - ---- Constructor. -function M:_init() - self.states = {} -end - ---- Index metamethod. --- @tparam CDOTAPlayer player Player --- @treturn table Player state -function M:__index(player) - local id = player:GetPlayerID() - - if self.states[id] == nil then - self.states[id] = {} - end - - return self.states[id] -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/communication.lua b/game/scripts/vscripts/invokation/combos/communication.lua deleted file mode 100644 index d2b8623..0000000 --- a/game/scripts/vscripts/invokation/combos/communication.lua +++ /dev/null @@ -1,84 +0,0 @@ ---- Internal combos communication helpers. --- @module invokation.combos.communication -local CustomEvents = require("invokation.dota2.custom_events") - -local M = {} - -local function comboMetrics(combo) - return { count = combo.count, damage = combo.damage, duration = combo.duration } -end - ---- Sends a custom event notifying that an ability was used. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam dota2.Ability ability Ability -function M.sendAbilityUsed(player, ability) - local payload = { ability = ability.name } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBAT_LOG_ABILITY_USED, player, payload) -end - ---- Sends a custom event notifying that a combo started. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo -function M.sendStarted(player, combo) - local payload = { id = combo.id, next = combo:NextStepsIds() } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_STARTED, player, payload) -end - ---- Sends a custom event notifying that a combo stopped. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo -function M.sendStopped(player, combo) - local payload = { id = combo.id } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_STOPPED, player, payload) -end - ---- Sends a custom event notifying that a combo is in progress. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo -function M.sendInProgress(player, combo) - local payload = { id = combo.id } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_IN_PROGRESS, player, payload) -end - ---- Sends a custom event notifying that a combo progressed. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo -function M.sendProgress(player, combo) - local payload = { id = combo.id, metrics = comboMetrics(combo), next = combo:NextStepsIds() } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_PROGRESS, player, payload) -end - ---- Sends a custom event notifying about a combo step error. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo --- @tparam dota2.Ability ability Ability used that caused the error -function M.sendStepError(player, combo, ability) - local payload = { id = combo.id, expected = combo:NextStepsIds(), ability = ability.name } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_STEP_ERROR, player, payload) -end - ---- Sends a custom event notifying that a combo entered pre-finish state. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo -function M.sendPreFinish(player, combo) - local payload = { id = combo.id, metrics = comboMetrics(combo), wait = combo.waitDuration } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_PRE_FINISH, player, payload) -end - ---- Sends a custom event notifying that a combo finished. --- @tparam CDOTAPlayer player Player to send the event to --- @tparam Combo combo Combo -function M.sendFinished(player, combo) - local payload = { id = combo.id, metrics = comboMetrics(combo) } - - return CustomEvents.SendPlayer(CustomEvents.EVENT_COMBO_FINISHED, player, payload) -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/hero.lua b/game/scripts/vscripts/invokation/combos/hero.lua deleted file mode 100644 index 9af0135..0000000 --- a/game/scripts/vscripts/invokation/combos/hero.lua +++ /dev/null @@ -1,102 +0,0 @@ ---- Internal combos hero helpers. --- @module invokation.combos.hero -local Invoker = require("invokation.dota2.Invoker") -local Player = require("invokation.dota2.Player") -local Unit = require("invokation.dota2.Unit") - -local LIMITS = require("invokation.const.limits") -local SOUND_EVENTS = require("invokation.const.sound_events") -local UNITS = require("invokation.const.units") - -local M = {} - ---- Runs the setup phase of a combo. --- @tparam CDOTAPlayer player Player playing the combo --- @tparam Combo combo Combo -function M.setup(player, combo) - player = Player(player) - - local unit = Unit(player.hero) - - unit:HeroLevelUpTo(combo.heroLevel) - unit:AddItemsByName(combo.items or {}, { onlyMissing = true }) - - if combo.gold ~= nil then - unit:GiveGold(combo.gold) - end - - unit:Hold() -end - ---- Runs the teardown phase of a combo. --- @tparam CDOTAPlayer player Player playing the combo --- @tparam table options Options table --- @tparam bool options.hardReset Perform a full reset -function M.teardown(player, options) - options = options or {} - player = Player(player) - - local unit = Unit(player.hero) - - unit:StopSound(SOUND_EVENTS.SNDEVT_INVOKER_METEOR_LOOP) - unit:EndItemCooldowns() - unit:EndAbilityCooldowns() - unit:RemoveDroppedItems() - - for _, unitName in pairs(UNITS.INVOKER_SPAWNED) do - player:RemoveOwnedUnitsByName(unitName) - end - - if options.hardReset then - local invoker = Invoker(player.hero) - - unit:RemoveItems() - -- Orbs reset must come before hero replacement - invoker:ResetAbilities() - unit:SetAbilityPoints(1) - player:ReplaceHero(player.hero:GetUnitName()) - else - unit:Purge() - unit:GiveMaxHealth() - unit:GiveMaxMana() - end -end - ---- Refunds a purchase made by a player's hero. --- @tparam CDOTAPlayer player Player that made the purchase --- @tparam Combos.Purchase purchase Purchase information -function M.refundPurchase(player, purchase) - player = Player(player) - - local unit = Unit(player.hero) - - unit:GiveGold(purchase.cost) -end - ---- Levels a player's hero up. --- @tparam CDOTAPlayer player Player --- @tparam Combos.LevelUpOptions options -function M.levelUp(player, options) - options = options or {} - player = Player(player) - - local unit = Unit(player.hero) - local targetLevel - - if options.level ~= nil then - targetLevel = options.level - elseif options.maxLevel then - targetLevel = LIMITS.MAX_HERO_LEVEL - else - targetLevel = unit:GetLevel() + 1 - end - - unit:HeroLevelUpTo(targetLevel, { playEffects = true }) - - if targetLevel == LIMITS.MAX_HERO_LEVEL then - local invoker = Invoker(player.hero) - invoker:LevelUpAbilities({ maxLevel = true }) - end -end - -return M diff --git a/game/scripts/vscripts/invokation/combos/sound.lua b/game/scripts/vscripts/invokation/combos/sound.lua deleted file mode 100644 index 7ee3302..0000000 --- a/game/scripts/vscripts/invokation/combos/sound.lua +++ /dev/null @@ -1,62 +0,0 @@ ---- Internal combos sound helpers. --- @module invokation.combos.sound -local SoundEvents = require("invokation.dota2.sound_events") - -local M = {} - -local MUSIC = { - IDLE = { STATUS = DOTA_MUSIC_STATUS_PRE_GAME_EXPLORATION, INTENSITY = 1.0 }, - BATTLE = { STATUS = DOTA_MUSIC_STATUS_BATTLE, INTENSITY = 5.0 }, - VICTORY = { STATUS = DOTA_MUSIC_STATUS_EXPLORATION, INTENSITY = 10.0 }, - DEFEAT = { STATUS = DOTA_MUSIC_STATUS_DEAD, INTENSITY = 10.0 }, -} - -local function randomSoundEvent(events) - return events[RandomInt(1, #events)] -end - ---- Emits a random event on entity. --- @tparam CBaseEntity entity --- @tparam {string,...} events Array of event names from which to get a random sample -function M.emitRandomEventOnEntity(entity, events) - return SoundEvents.EmitOnEntity(randomSoundEvent(events), entity) -end - ---- Emits a random event on player. --- @tparam CDOTAPlayer player --- @tparam {string,...} events Array of event names from which to get a random sample -function M.emitRandomEventOnPlayer(player, events) - return SoundEvents.EmitOnPlayer(randomSoundEvent(events), player) -end - ---- Sets up sound for when a dummy target unit is created. --- @tparam dota2.DummyTarget dummy -function M.onDummyCreate(dummy) - M.emitRandomEventOnEntity(dummy.entity, SoundEvents.SNDEVTS_DUMMY_CREATE) -end - ---- Sets up sound for when a player starts a combo. --- @tparam CDOTAPlayer player -function M.onComboStart(player) - player:SetMusicStatus(MUSIC.BATTLE.STATUS, MUSIC.BATTLE.INTENSITY) -end - ---- Sets up sound for when a player stops a combo. --- @tparam CDOTAPlayer player -function M.onComboStop(player) - player:SetMusicStatus(MUSIC.IDLE.STATUS, MUSIC.IDLE.INTENSITY) -end - ---- Sets up sound for when a player commits an error in a combo. --- @tparam CDOTAPlayer player -function M.onComboStepError(player) - player:SetMusicStatus(MUSIC.DEFEAT.STATUS, MUSIC.DEFEAT.INTENSITY) -end - ---- Sets up sound for when a player finishes a combo. --- @tparam CDOTAPlayer player -function M.onComboFinished(player) - player:SetMusicStatus(MUSIC.VICTORY.STATUS, MUSIC.VICTORY.INTENSITY) -end - -return M diff --git a/game/scripts/vscripts/invokation/const/abilities.lua b/game/scripts/vscripts/invokation/const/abilities.lua deleted file mode 100644 index 39c2fe5..0000000 --- a/game/scripts/vscripts/invokation/const/abilities.lua +++ /dev/null @@ -1,11 +0,0 @@ ---- Abilities constants. --- @module invokation.const.abilities -local M = {} - -local KEY_VALUES_FILE = "scripts/npc/heroes/npc_dota_hero_invoker.txt" - ---- KeyValues table of all abilities. --- @table KEY_VALUES -M.KEY_VALUES = LoadKeyValues(KEY_VALUES_FILE) - -return M diff --git a/game/scripts/vscripts/invokation/const/combos.lua b/game/scripts/vscripts/invokation/const/combos.lua deleted file mode 100644 index 01429a7..0000000 --- a/game/scripts/vscripts/invokation/const/combos.lua +++ /dev/null @@ -1,519 +0,0 @@ ---- Combo specifications. --- @module invokation.const.combos -local Talents = require("invokation.dota2.talents") - -local M = { - [1] = { - specialty = "qw", - stance = "defensive", - heroLevel = 2, - damageRating = 0, - difficultyRating = 1, - orbs = { 1, 1, 0 }, - talents = Talents.NONE, - tags = { "laning-phase" }, - items = { "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_cold_snap", required = true, next = { 2 } }, - [2] = { name = "invoker_tornado", required = true }, - }, - }, - [2] = { - specialty = "qw", - stance = "defensive", - heroLevel = 2, - damageRating = 0, - difficultyRating = 1, - orbs = { 1, 1, 0 }, - talents = Talents.NONE, - tags = { "laning-phase" }, - items = { "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_quas", required = true, next = { 3 } }, - [3] = { name = "invoker_quas", required = true, next = { 4 } }, - [4] = { name = "invoker_wex", required = true, next = { 5 } }, - [5] = { name = "invoker_invoke", required = true, next = { 6, 9 } }, - [6] = { name = "invoker_wex", required = false, next = { 7 } }, - [7] = { name = "invoker_wex", required = false, next = { 8 } }, - [8] = { name = "invoker_wex", required = false, next = { 9 } }, - [9] = { name = "invoker_ghost_walk", required = true }, - }, - }, - [3] = { - specialty = "qw", - stance = "offensive", - heroLevel = 2, - damageRating = 1, - difficultyRating = 1, - orbs = { 1, 1, 0 }, - talents = Talents.NONE, - tags = { "laning-phase" }, - items = { "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_emp", required = true, next = { 2 } }, - [2] = { name = "invoker_tornado", required = true }, - }, - }, - [4] = { - specialty = "qe", - stance = "offensive", - heroLevel = 2, - damageRating = 1, - difficultyRating = 1, - orbs = { 1, 0, 1 }, - talents = Talents.NONE, - tags = { "laning-phase" }, - items = { "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_forge_spirit", required = true, next = { 2 } }, - [2] = { name = "invoker_cold_snap", required = true }, - }, - }, - [5] = { - specialty = "qe", - stance = "offensive", - heroLevel = 3, - damageRating = 1, - difficultyRating = 1, - orbs = { 1, 1, 1 }, - talents = Talents.NONE, - tags = { "laning-phase" }, - items = { "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_forge_spirit", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true }, - }, - }, - [6] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true }, - }, - }, - [7] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 3, - difficultyRating = 3, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_sun_strike", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true }, - }, - }, - [8] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_deafening_blast", required = true, next = { 2 } }, - [2] = { name = "invoker_cold_snap", required = true, next = { 3 } }, - [3] = { name = "invoker_chaos_meteor", required = true }, - }, - }, - [9] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 3, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_cold_snap", required = true }, - }, - }, - [10] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 3, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true }, - }, - }, - [11] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 3, - difficultyRating = 3, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_sun_strike", required = true }, - }, - }, - [12] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 3, - orbs = { 2, 2, 2 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_emp", required = true }, - }, - }, - [13] = { - specialty = "qw", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 3, 2, 1 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_cold_snap", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true }, - }, - }, - [14] = { - specialty = "qw", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 3, 2, 1 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true, next = { 3 } }, - [3] = { name = "invoker_cold_snap", required = true }, - }, - }, - [15] = { - specialty = "qw", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 3, 2, 1 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true }, - }, - }, - [16] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 2, 1, 3 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true, next = { 3 } }, - [3] = { name = "invoker_sun_strike", required = true }, - }, - }, - [17] = { - specialty = "qe", - stance = "offensive", - heroLevel = 6, - damageRating = 2, - difficultyRating = 2, - orbs = { 2, 2, 2 }, - talents = Talents.NONE, - tags = { "solo-pick" }, - items = { "item_null_talisman", "item_null_talisman" }, - sequence = { - [1] = { name = "invoker_ice_wall", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true, next = { 3 } }, - [3] = { name = "invoker_emp", required = true }, - }, - }, - [18] = { - specialty = "qw", - stance = "offensive", - heroLevel = 12, - damageRating = 2, - difficultyRating = 3, - orbs = { 5, 5, 2 }, - talents = Talents.NONE, - tags = { "teamfight" }, - items = { "item_boots", "item_null_talisman", "item_null_talisman", "item_ultimate_scepter" }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_ice_wall", required = true, next = { 3 } }, - [3] = { name = "invoker_cold_snap", required = true, next = { 4 } }, - [4] = { name = "invoker_emp", required = true }, - }, - }, - [19] = { - specialty = "qe", - stance = "offensive", - heroLevel = 12, - damageRating = 2, - difficultyRating = 3, - orbs = { 4, 3, 4 }, - talents = Talents.L10_LEFT, - tags = { "teamfight" }, - items = { "item_boots", "item_null_talisman", "item_null_talisman", "item_ultimate_scepter" }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true, next = { 4 } }, - [4] = { name = "invoker_cold_snap", required = true, next = { 5 } }, - [5] = { name = "invoker_ice_wall", required = true }, - }, - }, - [20] = { - specialty = "qe", - stance = "offensive", - heroLevel = 12, - damageRating = 3, - difficultyRating = 3, - orbs = { 4, 3, 4 }, - talents = Talents.L10_LEFT, - tags = { "teamfight" }, - items = { - "item_boots", - "item_null_talisman", - "item_null_talisman", - "item_ultimate_scepter", - "item_cyclone", - }, - sequence = { - [1] = { name = "item_cyclone", required = true, next = { 2 } }, - [2] = { name = "invoker_sun_strike", required = true, next = { 3 } }, - [3] = { name = "invoker_emp", required = true, next = { 4 } }, - [4] = { name = "invoker_chaos_meteor", required = true, next = { 5 } }, - [5] = { name = "invoker_deafening_blast", required = true }, - }, - }, - [21] = { - specialty = "qe", - stance = "offensive", - heroLevel = 12, - damageRating = 2, - difficultyRating = 3, - orbs = { 4, 3, 5 }, - talents = Talents.NONE, - tags = { "teamfight" }, - items = { "item_boots", "item_null_talisman", "item_null_talisman", "item_ultimate_scepter" }, - sequence = { - [1] = { name = "invoker_forge_spirit", required = true, next = { 2 } }, - [2] = { name = "invoker_alacrity", required = true, next = { 3 } }, - [3] = { name = "invoker_ice_wall", required = true, next = { 4 } }, - [4] = { name = "invoker_cold_snap", required = true, next = { 5 } }, - [5] = { name = "invoker_sun_strike", required = true }, - }, - }, - [22] = { - specialty = "qe", - stance = "offensive", - heroLevel = 20, - damageRating = 4, - difficultyRating = 4, - orbs = { 5, 7, 7 }, - talents = Talents.L10_LEFT, - tags = { "late-game" }, - items = { - "item_travel_boots", - "item_null_talisman", - "item_null_talisman", - "item_null_talisman", - "item_refresher", - "item_ultimate_scepter", - }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_chaos_meteor", required = true, next = { 3 } }, - [3] = { name = "invoker_deafening_blast", required = true, next = { 4 } }, - [4] = { name = "item_refresher", required = true, next = { 5 } }, - [5] = { name = "invoker_chaos_meteor", required = true, next = { 6 } }, - [6] = { name = "invoker_deafening_blast", required = true, next = { 7 } }, - [7] = { name = "invoker_sun_strike", required = true }, - }, - }, - [23] = { - specialty = "qe", - stance = "offensive", - heroLevel = 20, - damageRating = 4, - difficultyRating = 4, - orbs = { 5, 7, 7 }, - talents = Talents.L10_LEFT, - tags = { "late-game" }, - items = { - "item_travel_boots", - "item_null_talisman", - "item_null_talisman", - "item_ultimate_scepter", - "item_octarine_core", - "item_refresher", - }, - sequence = { - [1] = { name = "invoker_tornado", required = true, next = { 2 } }, - [2] = { name = "invoker_emp", required = true, next = { 3 } }, - [3] = { name = "invoker_sun_strike", required = true, next = { 4 } }, - [4] = { name = "invoker_chaos_meteor", required = true, next = { 5 } }, - [5] = { name = "invoker_deafening_blast", required = true, next = { 6 } }, - [6] = { name = "item_refresher", required = true, next = { 7 } }, - [7] = { name = "invoker_chaos_meteor", required = true, next = { 8 } }, - [8] = { name = "invoker_deafening_blast", required = true, next = { 9 } }, - [9] = { name = "invoker_sun_strike", required = true }, - }, - }, - [24] = { - specialty = "qe", - stance = "offensive", - heroLevel = 20, - damageRating = 4, - difficultyRating = 4, - orbs = { 5, 7, 7 }, - talents = Talents.L10_LEFT, - tags = { "late-game" }, - items = { - "item_travel_boots", - "item_null_talisman", - "item_refresher", - "item_ultimate_scepter", - "item_sheepstick", - "item_black_king_bar", - }, - sequence = { - [1] = { name = "item_sheepstick", required = true, next = { 2 } }, - [2] = { name = "invoker_tornado", required = true, next = { 3 } }, - [3] = { name = "item_black_king_bar", required = true, next = { 4 } }, - [4] = { name = "invoker_chaos_meteor", required = true, next = { 5 } }, - [5] = { name = "invoker_deafening_blast", required = true, next = { 6 } }, - [6] = { name = "item_refresher", required = true, next = { 7 } }, - [7] = { name = "invoker_chaos_meteor", required = true, next = { 8 } }, - [8] = { name = "invoker_deafening_blast", required = true, next = { 9 } }, - [9] = { name = "invoker_sun_strike", required = true, next = { 10 } }, - [10] = { name = "item_black_king_bar", required = true, next = { 11 } }, - [11] = { name = "item_sheepstick", required = true }, - }, - }, - [25] = { - specialty = "qe", - stance = "offensive", - heroLevel = 20, - damageRating = 4, - difficultyRating = 4, - orbs = { 5, 7, 7 }, - talents = Talents.L10_LEFT, - tags = { "late-game" }, - items = { - "item_travel_boots", - "item_black_king_bar", - "item_blink", - "item_sheepstick", - "item_refresher", - "item_ultimate_scepter", - }, - sequence = { - [1] = { name = "item_black_king_bar", required = true, next = { 2 } }, - [2] = { name = "item_blink", required = true, next = { 3 } }, - [3] = { name = "item_sheepstick", required = true, next = { 4 } }, - [4] = { name = "invoker_tornado", required = true, next = { 5 } }, - [5] = { name = "invoker_chaos_meteor", required = true, next = { 6 } }, - [6] = { name = "invoker_deafening_blast", required = true, next = { 7 } }, - [7] = { name = "item_refresher", required = true, next = { 8 } }, - [8] = { name = "item_black_king_bar", required = true, next = { 9 } }, - [9] = { name = "invoker_chaos_meteor", required = true, next = { 10 } }, - [10] = { name = "invoker_deafening_blast", required = true, next = { 11 } }, - [11] = { name = "invoker_sun_strike", required = true, next = { 12 } }, - [12] = { name = "item_sheepstick", required = true }, - }, - }, - [26] = { - specialty = "qe", - stance = "offensive", - heroLevel = 25, - damageRating = 5, - difficultyRating = 5, - orbs = { 7, 7, 7 }, - talents = Talents.Select( - Talents.L10_LEFT, - Talents.L15_RIGHT, - Talents.L20_RIGHT, - Talents.L25_RIGHT - ), - tags = { "late-game" }, - items = { - "item_travel_boots", - "item_black_king_bar", - "item_shivas_guard", - "item_refresher", - "item_octarine_core", - "item_ultimate_scepter", - }, - sequence = { - [1] = { name = "invoker_alacrity", required = true, next = { 2 } }, - [2] = { name = "invoker_forge_spirit", required = true, next = { 3 } }, - [3] = { name = "item_black_king_bar", required = true, next = { 4 } }, - [4] = { name = "invoker_tornado", required = true, next = { 5 } }, - [5] = { name = "invoker_emp", required = true, next = { 6 } }, - [6] = { name = "invoker_sun_strike", required = true, next = { 7 } }, - [7] = { name = "invoker_chaos_meteor", required = true, next = { 8 } }, - [8] = { name = "item_shivas_guard", required = true, next = { 9 } }, - [9] = { name = "invoker_deafening_blast", required = true, next = { 10 } }, - [10] = { name = "item_refresher", required = true, next = { 11 } }, - [11] = { name = "item_shivas_guard", required = true, next = { 12 } }, - [12] = { name = "invoker_chaos_meteor", required = true, next = { 13 } }, - [13] = { name = "invoker_deafening_blast", required = true, next = { 14 } }, - [14] = { name = "invoker_emp", required = true, next = { 15 } }, - [15] = { name = "invoker_sun_strike", required = true, next = { 16 } }, - [16] = { name = "invoker_ice_wall", required = true }, - }, - }, -} - -return M diff --git a/game/scripts/vscripts/invokation/const/heroes.lua b/game/scripts/vscripts/invokation/const/heroes.lua deleted file mode 100644 index c4e85ad..0000000 --- a/game/scripts/vscripts/invokation/const/heroes.lua +++ /dev/null @@ -1,11 +0,0 @@ ---- Heroes constants. --- @module invokation.const.heroes -local M = {} - -local KEY_VALUES_FILE = "scripts/npc/npc_heroes.txt" - ---- KeyValues table of all heroes. --- @table KEY_VALUES -M.KEY_VALUES = LoadKeyValues(KEY_VALUES_FILE) - -return M diff --git a/game/scripts/vscripts/invokation/const/inventory.lua b/game/scripts/vscripts/invokation/const/inventory.lua deleted file mode 100644 index 8174af5..0000000 --- a/game/scripts/vscripts/invokation/const/inventory.lua +++ /dev/null @@ -1,40 +0,0 @@ ---- Inventory constants. --- @module invokation.const.inventory -local m = require("moses") - -local M = {} - ---- Array of inventory slots indices. -M.INVENTORY_SLOTS = { - DOTA_ITEM_SLOT_1, - DOTA_ITEM_SLOT_2, - DOTA_ITEM_SLOT_3, - DOTA_ITEM_SLOT_4, - DOTA_ITEM_SLOT_5, - DOTA_ITEM_SLOT_6, - DOTA_ITEM_SLOT_7, - DOTA_ITEM_SLOT_8, - DOTA_ITEM_SLOT_9, -} - ---- Array of stash slots indices. -M.STASH_SLOTS = { - DOTA_STASH_SLOT_1, - DOTA_STASH_SLOT_2, - DOTA_STASH_SLOT_3, - DOTA_STASH_SLOT_4, - DOTA_STASH_SLOT_5, - DOTA_STASH_SLOT_6, -} - ---- Array of neutral slots indices. -M.NEUTRAL_SLOTS = { DOTA_ITEM_NEUTRAL_SLOT } - ---- Array of all non-neutral slots indices (union of @{INVENTORY_SLOTS} and @{STASH_SLOTS}). -M.NON_NEUTRAL_SLOTS = m.chain({}):append(M.INVENTORY_SLOTS):append(M.STASH_SLOTS):value() - ---- Array of all slots indices (union of @{INVENTORY_SLOTS}, @{STASH_SLOTS} and @{NEUTRAL_SLOTS}). -M.SLOTS = - m.chain({}):append(M.INVENTORY_SLOTS):append(M.STASH_SLOTS):append(M.NEUTRAL_SLOTS):value() - -return M diff --git a/game/scripts/vscripts/invokation/const/invoker.lua b/game/scripts/vscripts/invokation/const/invoker.lua deleted file mode 100644 index b93cb1a..0000000 --- a/game/scripts/vscripts/invokation/const/invoker.lua +++ /dev/null @@ -1,288 +0,0 @@ ---- Invoker constants. --- @module invokation.const.invoker -local AbilityKeyValues = require("invokation.dota2.kv.AbilityKeyValues") -local HeroKeyValues = require("invokation.dota2.kv.HeroKeyValues") -local Talents = require("invokation.dota2.talents") -local m = require("moses") - -local ABILITIES = require("invokation.const.abilities") -local HEROES = require("invokation.const.heroes") -local UNITS = require("invokation.const.units") - -local FMT_ABILITY_TALENT_CONST_NAME = "ABILITY_TALENT_L%d_%s" - ----@class invokation.const.Invoker -local M = { - _serialized = nil, -} - ----@return invokation.const.Invoker -function M:Serialize() - if self._serialized == nil then - local serialized = m.clone(self) - - serialized._serialized = nil - serialized.KEY_VALUES = nil - serialized.HERO_KEY_VALUES = nil - serialized.ABILITIES_KEY_VALUES = nil - - self._serialized = serialized - end - - return self._serialized -end - ---- Hero id --- @tfield int HERO_ID -M.HERO_ID = 74 - ---- Unit name --- @tfield string UNIT_NAME -M.UNIT_NAME = UNITS.INVOKER - ---- Units spawned by Invoker --- Copy of @{INVOKER_SPAWNED} -M.SPAWNED_UNITS = UNITS.INVOKER_SPAWNED - ---- Raw KeyValues table --- @table KEY_VALUES -M.KEY_VALUES = HEROES.KEY_VALUES[M.UNIT_NAME] - ---- `dota2.kv.HeroKeyValues` instance -M.HERO_KEY_VALUES = HeroKeyValues(M.UNIT_NAME, M.KEY_VALUES) - ---- Quas ability name --- @tfield string ABILITY_QUAS -M.ABILITY_QUAS = "invoker_quas" ---- Wex ability name --- @tfield string ABILITY_WEX -M.ABILITY_WEX = "invoker_wex" ---- Exort ability name --- @tfield string ABILITY_EXORT -M.ABILITY_EXORT = "invoker_exort" ---- Empty1 ability name --- @tfield string ABILITY_EMPTY1 -M.ABILITY_EMPTY1 = "invoker_empty1" ---- Empty2 ability name --- @tfield string ABILITY_EMPTY2 -M.ABILITY_EMPTY2 = "invoker_empty2" ---- Invoke ability name --- @tfield string ABILITY_INVOKE -M.ABILITY_INVOKE = "invoker_invoke" ---- Cold Snap ability name --- @tfield string ABILITY_COLD_SNAP -M.ABILITY_COLD_SNAP = "invoker_cold_snap" ---- Ghost Walk ability name --- @tfield string ABILITY_GHOST_WALK -M.ABILITY_GHOST_WALK = "invoker_ghost_walk" ---- Ice Wall ability name --- @tfield string ABILITY_ICE_WALL -M.ABILITY_ICE_WALL = "invoker_ice_wall" ---- EMP ability name --- @tfield string ABILITY_EMP -M.ABILITY_EMP = "invoker_emp" ---- Tornado ability name --- @tfield string ABILITY_TORNADO -M.ABILITY_TORNADO = "invoker_tornado" ---- Alacrity ability name --- @tfield string ABILITY_ALACRITY -M.ABILITY_ALACRITY = "invoker_alacrity" ---- Sun Strike ability name --- @tfield string ABILITY_SUN_STRIKE -M.ABILITY_SUN_STRIKE = "invoker_sun_strike" ---- Forge Spirit ability name --- @tfield string ABILITY_FORGE_SPIRIT -M.ABILITY_FORGE_SPIRIT = "invoker_forge_spirit" ---- Chaos Meteor ability name --- @tfield string ABILITY_CHAOS_METEOR -M.ABILITY_CHAOS_METEOR = "invoker_chaos_meteor" ---- Deafening Blast ability name --- @tfield string ABILITY_DEAFENING_BLAST -M.ABILITY_DEAFENING_BLAST = "invoker_deafening_blast" - ---- Level 10 right talent ability name --- @tfield string ABILITY_TALENT_L10_RIGHT - ---- Level 10 left talent ability name --- @tfield string ABILITY_TALENT_L10_LEFT - ---- Level 15 right talent ability name --- @tfield string ABILITY_TALENT_L15_RIGHT - ---- Level 15 left talent ability name --- @tfield string ABILITY_TALENT_L15_LEFT - ---- Level 20 right talent ability name --- @tfield string ABILITY_TALENT_L20_RIGHT - ---- Level 20 left talent ability name --- @tfield string ABILITY_TALENT_L20_LEFT - ---- Level 25 right talent ability name --- @tfield string ABILITY_TALENT_L25_RIGHT - ---- Level 25 left talent ability name --- @tfield string ABILITY_TALENT_L25_LEFT - -for enumValue, abilityName in pairs(M.HERO_KEY_VALUES:Talents()) do - local constName = FMT_ABILITY_TALENT_CONST_NAME:format(Talents.LevelAndSide(enumValue)) - - M[constName] = abilityName -end - ---- Array of orb abilities names. --- @table ORB_ABILITIES --- @tfield string 1 Quas --- @tfield string 2 Wex --- @tfield string 3 Exort -M.ORB_ABILITIES = { M.ABILITY_QUAS, M.ABILITY_WEX, M.ABILITY_EXORT } - ---- Array of orb abilities names. --- @table SPELL_ABILITIES --- @tfield string 1 Cold Snap --- @tfield string 2 Ghost Walk --- @tfield string 3 Ice Wall --- @tfield string 4 EMP --- @tfield string 5 Tornado --- @tfield string 6 Alacrity --- @tfield string 7 Sun Strike --- @tfield string 8 Forge Spirit --- @tfield string 9 Chaos Meteor --- @tfield string 10 Deafening Blast -M.SPELL_ABILITIES = { - M.ABILITY_COLD_SNAP, - M.ABILITY_GHOST_WALK, - M.ABILITY_ICE_WALL, - M.ABILITY_EMP, - M.ABILITY_TORNADO, - M.ABILITY_ALACRITY, - M.ABILITY_SUN_STRIKE, - M.ABILITY_FORGE_SPIRIT, - M.ABILITY_CHAOS_METEOR, - M.ABILITY_DEAFENING_BLAST, -} - ---- Array of talent abilities names. --- @table TALENT_ABILITIES --- @tfield string 1 Level 10 right --- @tfield string 2 Level 10 left --- @tfield string 3 Level 15 right --- @tfield string 4 Level 15 left --- @tfield string 5 Level 20 right --- @tfield string 6 Level 20 left --- @tfield string 7 Level 25 right --- @tfield string 8 Level 25 left -M.TALENT_ABILITIES = m.values(M.HERO_KEY_VALUES:Talents()) - ---- Abilities KeyValues --- @table ABILITIES_KEY_VALUES --- @tfield AbilityKeyValues ABILITY_QUAS --- @tfield AbilityKeyValues ABILITY_WEX --- @tfield AbilityKeyValues ABILITY_EXORT --- @tfield AbilityKeyValues ABILITY_COLD_SNAP --- @tfield AbilityKeyValues ABILITY_GHOST_WALK --- @tfield AbilityKeyValues ABILITY_ICE_WALL --- @tfield AbilityKeyValues ABILITY_EMP --- @tfield AbilityKeyValues ABILITY_TORNADO --- @tfield AbilityKeyValues ABILITY_ALACRITY --- @tfield AbilityKeyValues ABILITY_SUN_STRIKE --- @tfield AbilityKeyValues ABILITY_FORGE_SPIRIT --- @tfield AbilityKeyValues ABILITY_CHAOS_METEOR --- @tfield AbilityKeyValues ABILITY_DEAFENING_BLAST --- @tfield AbilityKeyValues ABILITY_TALENT_1 --- @tfield AbilityKeyValues ABILITY_TALENT_2 --- @tfield AbilityKeyValues ABILITY_TALENT_3 --- @tfield AbilityKeyValues ABILITY_TALENT_4 --- @tfield AbilityKeyValues ABILITY_TALENT_5 --- @tfield AbilityKeyValues ABILITY_TALENT_6 --- @tfield AbilityKeyValues ABILITY_TALENT_7 --- @tfield AbilityKeyValues ABILITY_TALENT_8 -M.ABILITIES_KEY_VALUES = {} - -for _, abilityName in ipairs(M.ORB_ABILITIES) do - M.ABILITIES_KEY_VALUES[abilityName] = - AbilityKeyValues(abilityName, ABILITIES.KEY_VALUES[abilityName]) -end - -for _, abilityName in ipairs(M.SPELL_ABILITIES) do - M.ABILITIES_KEY_VALUES[abilityName] = - AbilityKeyValues(abilityName, ABILITIES.KEY_VALUES[abilityName]) -end - -for _, abilityName in ipairs(M.TALENT_ABILITIES) do - M.ABILITIES_KEY_VALUES[abilityName] = - AbilityKeyValues(abilityName, ABILITIES.KEY_VALUES[abilityName]) -end - ---- Table of orb abilities composition ("recipes") of spell abilities. --- @table SPELL_COMPOSITION --- @tfield {string,...} ABILITY_COLD_SNAP Cold Snap --- @tfield {string,...} ABILITY_GHOST_WALK Ghost Walk --- @tfield {string,...} ABILITY_ICE_WALL Ice Wall --- @tfield {string,...} ABILITY_EMP EMP --- @tfield {string,...} ABILITY_TORNADO Tornado --- @tfield {string,...} ABILITY_ALACRITY Alacrity --- @tfield {string,...} ABILITY_SUN_STRIKE Sun Strike --- @tfield {string,...} ABILITY_FORGE_SPIRIT Forge Spirit --- @tfield {string,...} ABILITY_CHAOS_METEOR Chaos Meteor --- @tfield {string,...} ABILITY_DEAFENING_BLAST Deafening Blast -M.SPELL_COMPOSITION = { - [M.ABILITY_COLD_SNAP] = { M.ABILITY_QUAS, M.ABILITY_QUAS, M.ABILITY_QUAS }, - [M.ABILITY_GHOST_WALK] = { M.ABILITY_QUAS, M.ABILITY_QUAS, M.ABILITY_WEX }, - [M.ABILITY_ICE_WALL] = { M.ABILITY_QUAS, M.ABILITY_QUAS, M.ABILITY_EXORT }, - [M.ABILITY_EMP] = { M.ABILITY_WEX, M.ABILITY_WEX, M.ABILITY_WEX }, - [M.ABILITY_TORNADO] = { M.ABILITY_WEX, M.ABILITY_WEX, M.ABILITY_QUAS }, - [M.ABILITY_ALACRITY] = { M.ABILITY_WEX, M.ABILITY_WEX, M.ABILITY_EXORT }, - [M.ABILITY_SUN_STRIKE] = { M.ABILITY_EXORT, M.ABILITY_EXORT, M.ABILITY_EXORT }, - [M.ABILITY_FORGE_SPIRIT] = { M.ABILITY_EXORT, M.ABILITY_EXORT, M.ABILITY_QUAS }, - [M.ABILITY_CHAOS_METEOR] = { M.ABILITY_EXORT, M.ABILITY_EXORT, M.ABILITY_WEX }, - [M.ABILITY_DEAFENING_BLAST] = { M.ABILITY_QUAS, M.ABILITY_WEX, M.ABILITY_EXORT }, -} - --- empty1 and empty2 can change indices, we're using them only to reference spell slots - ---- Quas ability index. --- @tfield int INDEX_ABILITY_QUAS -M.INDEX_ABILITY_QUAS = 0 ---- Wex ability index. --- @tfield int INDEX_ABILITY_WEX -M.INDEX_ABILITY_WEX = 1 ---- Exort ability index. --- @tfield int INDEX_ABILITY_EXORT -M.INDEX_ABILITY_EXORT = 2 ---- Spell slot 1 ability index. --- @tfield int INDEX_ABILITY_EMPTY1 -M.INDEX_ABILITY_EMPTY1 = 3 ---- Spell slot 2 ability index. --- @tfield int INDEX_ABILITY_EMPTY2 -M.INDEX_ABILITY_EMPTY2 = 4 ---- Invoke ability index. --- @tfield int INDEX_ABILITY_INVOKE -M.INDEX_ABILITY_INVOKE = 5 - ---- Table of ability indices by ability name. --- @table ABILITY_INDICES --- @tfield int ABILITY_QUAS Quas --- @tfield int ABILITY_WEX Wex --- @tfield int ABILITY_EXORT Exort --- @tfield int ABILITY_EMPTY1 Spell slot 1 --- @tfield int ABILITY_EMPTY2 Spell slot 2 --- @tfield int ABILITY_INVOKE Invoke -M.ABILITY_INDICES = { - [M.ABILITY_QUAS] = M.INDEX_ABILITY_QUAS, - [M.ABILITY_WEX] = M.INDEX_ABILITY_WEX, - [M.ABILITY_EXORT] = M.INDEX_ABILITY_EXORT, - [M.ABILITY_EMPTY1] = M.INDEX_ABILITY_EMPTY1, - [M.ABILITY_EMPTY2] = M.INDEX_ABILITY_EMPTY2, - [M.ABILITY_INVOKE] = M.INDEX_ABILITY_INVOKE, -} - ---- Maximum index of the last visible ability. --- --- Abilities with index higher than this are hidden. ---- @tfield int MAX_VISIBLE_ABILITY_INDEX -M.MAX_VISIBLE_ABILITY_INDEX = 5 - -M.FACETS = M.KEY_VALUES["Facets"] - -return M diff --git a/game/scripts/vscripts/invokation/const/items.lua b/game/scripts/vscripts/invokation/const/items.lua deleted file mode 100644 index 4cdaac3..0000000 --- a/game/scripts/vscripts/invokation/const/items.lua +++ /dev/null @@ -1,11 +0,0 @@ ---- Items constants. --- @module invokation.const.items -local M = {} - -local KEY_VALUES_FILE = "scripts/npc/items.txt" - ---- KeyValues table of all items. --- @table KEY_VALUES -M.KEY_VALUES = LoadKeyValues(KEY_VALUES_FILE) - -return M diff --git a/game/scripts/vscripts/invokation/const/metadata.lua b/game/scripts/vscripts/invokation/const/metadata.lua deleted file mode 100644 index e3f6f70..0000000 --- a/game/scripts/vscripts/invokation/const/metadata.lua +++ /dev/null @@ -1,36 +0,0 @@ ---- Package metadata. --- --- This loosely follows the [Rockspec format][rockspec]. --- --- [rockspec]: https://github.com/luarocks/luarocks/wiki/Rockspec-format --- --- @module invokation.const.metadata - -local M = {} - ---- Package name --- @tfield string package -M.package = "Invokation" - ---- Package version --- @tfield string version -M.version = "0.5.3" - ---- Package description --- @table description --- @tfield string summary Package summary --- @tfield string license Package license --- @tfield string homepage Package homepage --- @tfield string issues_url Package issues URL --- @tfield string maintainer Package maintainer --- @tfield {string,...} labels Package labels -M.description = { - summary = "Invokation School of Arcane Arts", - license = "MIT", - homepage = "https://github.com/13k/invokation", - issues_url = "https://github.com/13k/invokation/issues", - maintainer = "Kiyoshi Murata ", - labels = { "dota2", "dota2-addon", "dota2-custom-game", "invoker", "invoker-trainer" }, -} - -return M diff --git a/game/scripts/vscripts/invokation/const/net_table.lua b/game/scripts/vscripts/invokation/const/net_table.lua deleted file mode 100644 index 17bd802..0000000 --- a/game/scripts/vscripts/invokation/const/net_table.lua +++ /dev/null @@ -1,25 +0,0 @@ ---- NetTable constants. --- @module invokation.const.net_tables -local M = { - MAIN = { - NAME = "invokation", - KEYS = { - COMBOS = "combos", - HERO_DATA = "hero_data", - }, - }, - HERO = { - NAME = "hero", - KEYS = { - KEY_VALUES = "kv", - }, - }, - ABILITIES = { - NAME = "abilities", - KEYS = { - KEY_VALUES = "kv", - }, - }, -} - -return M diff --git a/game/scripts/vscripts/invokation/dota2/Ability.lua b/game/scripts/vscripts/invokation/dota2/Ability.lua deleted file mode 100644 index 1ef91a7..0000000 --- a/game/scripts/vscripts/invokation/dota2/Ability.lua +++ /dev/null @@ -1,39 +0,0 @@ ---- Ability class that represents either an ability or item. --- @classmod invokation.dota2.Ability -local class = require("pl.class") -local delegation = require("invokation.lang.delegation") -local m = require("moses") - -local INVOKER = require("invokation.const.invoker") - -local M = class() - -local ORB_ABILITIES = m.map(INVOKER.ORB_ABILITIES, function(ability) - return ability, true -end) - -local DELEGATES = { "GetDuration", "GetSpecialValueFor", "IsItem" } - -delegation.delegate(M, "entity", DELEGATES) - ---- Constructor. --- @tparam CDOTABaseAbility|CDOTA_Item entity Ability or item entity -function M:_init(entity) - self.entity = entity - self.name = self.entity:GetAbilityName() - self.index = self.entity:GetAbilityIndex() -end - ---- Checks if this ability is an Invoker orb ability (quas, wex or exort). --- @treturn bool `true` if it's an orb ability, `false` otherwise -function M:IsOrbAbility() - return m.toBoolean(ORB_ABILITIES[self.name]) -end - ---- Checks if this ability is an Invoker "invocation" ability (quas, wex, exort or invoke). --- @treturn bool `true` if it's an invocation ability, `false` otherwise -function M:IsInvocationAbility() - return self:IsOrbAbility() or self.name == INVOKER.ABILITY_INVOKE -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/DamageInstance.lua b/game/scripts/vscripts/invokation/dota2/DamageInstance.lua deleted file mode 100644 index 52635db..0000000 --- a/game/scripts/vscripts/invokation/dota2/DamageInstance.lua +++ /dev/null @@ -1,44 +0,0 @@ ---- DamageInstance class. --- @classmod invokation.dota2.DamageInstance -local class = require("pl.class") - -local M = class() - ---- Constructor. --- @tparam Unit victim Victim unit instance --- @tparam number amount Damage amount --- @tparam[opt] Unit attacker Attacker unit instance --- @tparam[opt] Ability inflictor Inflictor ability instance -function M:_init(victim, amount, attacker, inflictor) - self.victim = victim - self.amount = amount - self.attacker = attacker - self.inflictor = inflictor - self.category = inflictor and DOTA_DAMAGE_CATEGORY_SPELL or DOTA_DAMAGE_CATEGORY_ATTACK -end - ---- Returns the victim unit name. --- @treturn string Victim unit name -function M:VictimName() - return self.victim.name -end - ---- Returns the attacker unit name if it exists. --- @treturn ?string Attacker unit name -function M:AttackerName() - return self.attacker and self.attacker.name -end - ---- Returns the player owner of the attacker unit if it exists. --- @treturn ?CDOTAPlayer Attacker player owner -function M:AttackerPlayerOwner() - return self.attacker and self.attacker:GetPlayerOwner() -end - ---- Returns the inflictor ability name if it exists. --- @treturn ?string Inflictor ability name -function M:InflictorName() - return self.inflictor and self.inflictor.name -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/DummyTarget.lua b/game/scripts/vscripts/invokation/dota2/DummyTarget.lua deleted file mode 100644 index d7201b1..0000000 --- a/game/scripts/vscripts/invokation/dota2/DummyTarget.lua +++ /dev/null @@ -1,73 +0,0 @@ ---- DummyTarget class. --- @classmod invokation.dota2.DummyTarget -local Units = require("invokation.dota2.units") -local class = require("pl.class") -local delegation = require("invokation.lang.delegation") -local m = require("moses") - -local M = class() - -local DELEGATES = { "Hold" } - -delegation.delegate(M, "entity", DELEGATES) - -local function createDummy(location) - local unit = Units.Create(Units.DUMMY_TARGET, { location = location, team = DOTA_TEAM_BADGUYS }) - - unit:SetIdleAcquire(false) - - return unit -end - ---- Constructor. --- @tparam table options Options table --- @tparam[opt=true] bool options.spawn Spawn dummy unit immediately -function M:_init(options) - self.spawn = Entities:FindByName(nil, Units.DUMMY_TARGET_SPAWN) - - options = m.extend({ spawn = true }, options or {}) - - if options.spawn then - self:Spawn() - end -end - ---- Checks if dummy unit is alive. --- @treturn bool -function M:IsAlive() - return m.toBoolean(self.entity and not self.entity:IsNull() and self.entity:IsAlive()) -end - ---- Checks if the dummy unit is dead. --- @treturn bool -function M:IsDead() - return not self:IsAlive() -end - ---- Spawns the dummy unit. -function M:Spawn() - if self:IsAlive() then - return - end - - self.entity = createDummy(self.spawn:GetAbsOrigin()) - - self:Hold() -end - ---- Kills the dummy unit. -function M:Kill() - if self:IsAlive() then - Units.Destroy(self.entity) - end - - self.entity = nil -end - ---- Resets the dummy unit. -function M:Reset() - self:Kill() - self:Spawn() -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/Invoker.lua b/game/scripts/vscripts/invokation/dota2/Invoker.lua deleted file mode 100644 index dc559b9..0000000 --- a/game/scripts/vscripts/invokation/dota2/Invoker.lua +++ /dev/null @@ -1,162 +0,0 @@ ---- Invoker class. --- @classmod invokation.dota2.Invoker -local Ability = require("invokation.dota2.Ability") -local List = require("pl.List") -local class = require("pl.class") -local m = require("moses") - -local INVOKER = require("invokation.const.invoker") - -local M = class() - -m.extend(M, INVOKER) - ---- Constructor. --- @tparam CDOTA_BaseNPC_Hero hero Hero entity -function M:_init(hero) - self.hero = hero -end - -function M:swapAbilities(ability1, ability2) - return self.hero:SwapAbilities( - ability1.name, - ability2.name, - ability2.index <= INVOKER.MAX_VISIBLE_ABILITY_INDEX, - ability1.index <= INVOKER.MAX_VISIBLE_ABILITY_INDEX - ) -end - ---- Invokes an ability by name. --- @tparam string abilityName Ability name -function M:Invoke(abilityName) - local invoked = Ability(self.hero:FindAbilityByName(abilityName)) - - -- I(i) : [i, s2], [s3, s4, s5] -> [i, s2], [s3, s4, s5] - if invoked.index == INVOKER.INDEX_ABILITY_EMPTY1 then - return - end - - local spell1 = Ability(self.hero:GetAbilityByIndex(INVOKER.INDEX_ABILITY_EMPTY1)) - - -- I(i) : [s1, i], [s2, s3, s4] -> [i, s1], [s2, s3, s4] - if invoked.index == INVOKER.INDEX_ABILITY_EMPTY2 then - self:swapAbilities(spell1, invoked) - return - end - - local spell2 = Ability(self.hero:GetAbilityByIndex(INVOKER.INDEX_ABILITY_EMPTY2)) - - -- I(i) : [s1, s2], [s3, s4, i] -> [s2, s1], [s3, s4, i] -> [i, s1], [s3, s4, s2] - self:swapAbilities(spell1, spell2) - self:swapAbilities(spell2, invoked) -end - ---[[ - This is a hack. "AbilitySpecial" values for Invoker spells that depend on - orb ability level (specials that have "levelkey" set to "quaslevel", - "wexlevel" or "exortlevel") don't change when orb ability levels are - manually changed (with `CDOTABaseAbility:SetLevel`). Since we're resetting - orb levels to zero, this hack "resets" spell abilities by removing and - reinserting them on the hero. - - WARNING: when removing an ability, make sure they aren't visible (invoked), - otherwise the whole ability slot will disappear from the UI. -]] -local function reinsertSpellAbility(hero, ability) - local name = ability:GetAbilityName() - - if not ability:IsHidden() then - error(string.format("Tried to remove visible ability %q.", name)) - end - - local index = ability:GetAbilityIndex() - local level = ability:GetLevel() - - hero:RemoveAbility(name) - - ability = hero:AddAbility(name) - ability:SetAbilityIndex(index) - ability:SetLevel(level) -end - -local function canLevelUpAbility(hero, ability, targetLevel) - return (ability:CanAbilityBeUpgraded() == ABILITY_CAN_BE_UPGRADED) - and (hero:GetAbilityPoints() > 0) - and (ability:GetLevel() < targetLevel) -end - ---- Ability level up option. --- --- If no option is given, level up the ability 1 level. --- --- @table AbilityLevelUpOption --- @tfield[opt] int level Specific level --- @tfield[opt] bool maxLevel Level up to max ability level - ---- Levels up orb abilities. --- @tparam table options Options table --- @tparam[opt=false] bool options.maxLevel Level up abilities to max level --- @tparam[opt] AbilityLevelUpOption const.invoker.ABILITY_QUAS Quas level up option --- @tparam[opt] AbilityLevelUpOption const.invoker.ABILITY_WEX Wex level up option --- @tparam[opt] AbilityLevelUpOption const.invoker.ABILITY_EXORT Exort level up option -function M:LevelUpAbilities(options) - options = options or {} - - for _, name in ipairs(INVOKER.ORB_ABILITIES) do - if options.maxLevel or options[name] then - local ability = self.hero:FindAbilityByName(name) - local abilityOption = options[name] or {} - local targetLevel - - if options.maxLevel or abilityOption.maxLevel then - targetLevel = ability:GetMaxLevel() - elseif abilityOption.level then - targetLevel = abilityOption.level - else - targetLevel = ability:GetLevel() + 1 - end - - while canLevelUpAbility(self.hero, ability, targetLevel) do - self.hero:UpgradeAbility(ability) - end - end - end -end - ---- Resets orb abilities levels to zero. --- @tparam table options Options table --- @tparam[opt=false] bool options.reinsertSpells Reinsert (reset) spell abilities --- This is a workaround to fix spells not scaling back (special values that --- depend on orb levels). Another way to fix this is to completely replace the --- player's hero with `PlayerResource:ReplaceHeroWith`. If hero replacement is --- being used, this option is not needed. --- @treturn int The number of ability points gained by downgrading orb abilities -function M:ResetAbilities(options) - options = options or {} - - local points = 0 - local resetAbilities = List.new(INVOKER.ORB_ABILITIES) .. List.new(INVOKER.TALENT_ABILITIES) - - for _, name in ipairs(resetAbilities) do - local ability = self.hero:FindAbilityByName(name) - - if ability ~= nil then - points = points + ability:GetLevel() - ability:SetLevel(0) - end - end - - if options.reinsertSpells then - self:Invoke(INVOKER.ABILITY_EMPTY2) - self:Invoke(INVOKER.ABILITY_EMPTY1) - - for _, name in ipairs(INVOKER.SPELL_ABILITIES) do - local ability = self.hero:FindAbilityByName(name) - reinsertSpellAbility(self.hero, ability) - end - end - - return points -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/NetTable.lua b/game/scripts/vscripts/invokation/dota2/NetTable.lua deleted file mode 100644 index edbf1b9..0000000 --- a/game/scripts/vscripts/invokation/dota2/NetTable.lua +++ /dev/null @@ -1,40 +0,0 @@ ---- NetTable class. --- @classmod invokation.dota2.NetTable -local class = require("pl.class") -local tablex = require("pl.tablex") - -local NET_TABLE = require("invokation.const.net_table") - -local M = class() - -tablex.update(M, NET_TABLE) - ---- Constructor. --- @tparam string name Net table name -function M:_init(name) - self.name = name -end - ---- Sets a net table value. --- @tparam string key Key --- @param value Value --- @treturn bool Setting success -function M:Set(key, value) - return CustomNetTables:SetTableValue(self.name, key, value) -end - ---- Gets a net table value. --- @tparam string key Key --- @param[opt=nil] defaultValue Default value in case the net table value is `nil` --- @return Value of `key` if it exists, `defaultValue` otherwise -function M:Get(key, defaultValue) - local value = CustomNetTables:GetTableValue(self.name, key) - - if value == nil then - return defaultValue - end - - return value -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/Player.lua b/game/scripts/vscripts/invokation/dota2/Player.lua deleted file mode 100644 index 2174684..0000000 --- a/game/scripts/vscripts/invokation/dota2/Player.lua +++ /dev/null @@ -1,81 +0,0 @@ ---- Player class. --- @classmod invokation.dota2.Player -local class = require("pl.class") - -local M = class() - ---- Constructor. --- --- Attributes: --- --- * `entity`: (`CDOTAPlayer`) player entity --- * `id`: (`int`) player id --- * `accountId`: (`int`) player's 32-bit account id --- * `steamId`: (`int`) player's 64-bit steam id --- * `hero`: (`CDOTA_BaseNPC_Hero`) player's assigned hero entity --- --- @tparam CDOTAPlayer entity Player entity -function M:_init(entity) - self.entity = entity - self.id = self.entity:GetPlayerID() - self.accountId = PlayerResource:GetSteamAccountID(self.id) - self.steamId = PlayerResource:GetSteamID(self.id) - self.hero = self.entity:GetAssignedHero() -end - ---- Replaces the player's hero with a new one. --- --- After replacing the hero, this Player instance's `hero` attribute will --- reference the new entity. --- --- @tparam string heroName Hero unit name --- @tparam table options Options table --- @tparam[opt=0] int options.gold New hero starting gold --- @tparam[opt=0] int options.xp New hero starting experience --- @tparam[opt=true] bool options.remove Remove old hero entity. Not removing --- the entity will make it linger under the player's ownership and control --- @treturn CDOTA_BaseNPC_Hero New hero entity -function M:ReplaceHero(heroName, options) - local oldHero = self.hero - - options = options or {} - options.gold = options.gold or 0 - options.xp = options.xp or 0 - options.remove = options.remove == nil and true or options.remove - - self.hero = PlayerResource:ReplaceHeroWith(self.id, heroName, options.gold, options.xp) - - if options.remove then - oldHero:RemoveSelf() - end - - return self.hero -end - ---- Remove the player's owned units with given name. --- @tparam string unitName Unit name --- @treturn int The number of units removed -function M:RemoveOwnedUnitsByName(unitName) - local toRemove = {} - local ent = Entities:FindByName(nil, unitName) - - while ent ~= nil do - if ent.GetPlayerOwner ~= nil then - local owner = ent:GetPlayerOwner() - - if owner:GetPlayerID() == self.id then - table.insert(toRemove, ent) - end - end - - ent = Entities:FindByName(ent, unitName) - end - - for _, entToRemove in ipairs(toRemove) do - entToRemove:RemoveSelf() - end - - return #toRemove -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/Unit.lua b/game/scripts/vscripts/invokation/dota2/Unit.lua deleted file mode 100644 index 9b909ab..0000000 --- a/game/scripts/vscripts/invokation/dota2/Unit.lua +++ /dev/null @@ -1,346 +0,0 @@ ---- Unit class. --- @classmod invokation.dota2.Unit -local class = require("pl.class") -local delegation = require("invokation.lang.delegation") -local m = require("moses") -local types = require("pl.types") - -local INVENTORY = require("invokation.const.inventory") -local LIMITS = require("invokation.const.limits") - -local M = class() - -local ERRF_UNIT_NO_INVENTORY = "Unit '%s' does not have an inventory" -local ERRF_UNIT_CANNOT_RESPAWN = "Unit '%s' cannot respawn" - -local DELEGATES = { - "AddItemByName", - "FindAbilityByName", - "GetAbilityByIndex", - "GetEntityIndex", - "GetItemInSlot", - "GetLevel", - "GetMaxHealth", - "GetMaxMana", - "GetPlayerOwner", - "GetPlayerOwnerID", - "GiveMana", - "HasAbility", - "HasInventory", - "HasItemInInventory", - "Heal", - "HeroLevelUp", - "Hold", - "Interrupt", - "IsAlive", - "IsHero", - "RemoveItem", - "RespawnHero", - "RespawnUnit", - "SetAbilityPoints", - "SetGold", - "StopSound", -} - -delegation.delegate(M, "entity", DELEGATES) - ---- Constructor. --- @tparam CDOTA_BaseNPC entity Unit entity -function M:_init(entity) - self.entity = entity - self.name = self.entity:GetUnitName() -end - ---- Respawns the unit. --- --- If the unit is a hero, uses `CDOTA_BaseNPC_Hero:RespawnHero` with given --- options, otherwise uses `CDOTA_BaseNPC:RespawnUnit`. --- --- @tparam[opt={}] table options Options table --- @tparam[opt=false] bool options.buyback Is buyback respawn? --- @tparam[opt=false] bool options.isFirst Is actually being spawned for the first time? --- @tparam[opt=false] bool options.penalty Apply respawn penalty? -function M:Respawn(options) - if not self.entity:UnitCanRespawn() then - error(ERRF_UNIT_CANNOT_RESPAWN:format(self.name)) - end - - options = options or {} - - if self:IsHero() then - return self:RespawnHero( - types.to_bool(options.buyback), - types.to_bool(options.isFirst), - types.to_bool(options.penalty) - ) - end - - return self:RespawnUnit() -end - ---- Purges the unit. --- @tparam[opt={}] table options Options table --- @tparam[opt=true] bool options.buffs Remove positive buffs --- @tparam[opt=true] bool options.debuffs Remove negative buffs --- @tparam[opt=true] bool options.stuns Remove stuns --- @tparam[opt=true] bool options.exceptions Remove exceptions --- @tparam[opt=false] bool options.frameOnly Remove buffs created this frame only -function M:Purge(options) - options = options or {} - options.buffs = options.buffs == nil and true or options.buffs - options.debuffs = options.debuffs == nil and true or options.debuffs - options.stuns = options.stuns == nil and true or options.stuns - options.exceptions = options.exceptions == nil and true or options.exceptions - - return self.entity:Purge( - types.to_bool(options.buffs), - types.to_bool(options.debuffs), - types.to_bool(options.frameOnly), - types.to_bool(options.stuns), - types.to_bool(options.exceptions) - ) -end - ---- Levels up the hero unit. --- @tparam int level Target level (if current level is higher, does nothing) --- @tparam[opt={}] table options Options table --- @tparam[opt=false] bool options.playEffects Play level up effects -function M:HeroLevelUpTo(level, options) - options = options or {} - - if level > LIMITS.MAX_HERO_LEVEL then - level = LIMITS.MAX_HERO_LEVEL - end - - while self:GetLevel() < level do - self:HeroLevelUp(types.to_bool(options.playEffects)) - end -end - ---- Heals the unit to the maximum health. --- @tparam[opt] CBaseEntity healSource Heal source entity -function M:GiveMaxHealth(healSource) - return self:Heal(self:GetMaxHealth(), healSource) -end - ---- Gives the unit maximum mana. -function M:GiveMaxMana() - return self:GiveMana(self:GetMaxMana()) -end - ---- Gives the hero unit a gold amount. --- @tparam int amount Gold amount (can be negative) --- @tparam table options Options table --- @tparam[opt=true] bool options.reliable Is this gold reliable? --- @tparam[opt=DOTA_ModifyGold_Unspecified] EDOTA_ModifyGold_Reason options.reason Reason flags -function M:GiveGold(amount, options) - options = options or {} - options.reliable = options.reliable == nil and true or options.reliable - options.reason = options.reason == nil and DOTA_ModifyGold_Unspecified or options.reason - - return self.entity:ModifyGold(amount, types.to_bool(options.reliable), options.reason) -end - ---- Iterates over the unit's inventory, yielding each non-nil item. --- @tparam function callback Iterator function --- @tparam[opt={}] table options Options table --- @tparam[opt={}] table options.sections Array of inventory sections to scan ("inventory", "stash", --- "neutral"). Scans the whole inventory if empty. -function M:ForEachItem(callback, options) - if not self:HasInventory() then - error(ERRF_UNIT_NO_INVENTORY:format(self.name)) - end - - options = options or {} - options.sections = options.sections or { "inventory", "stash", "neutral" } - - local slots = m.chain({}) - - for _, part in ipairs(options.sections) do - if part == "inventory" then - slots = slots:append(INVENTORY.INVENTORY_SLOTS) - elseif part == "stash" then - slots = slots:append(INVENTORY.STASH_SLOTS) - elseif part == "neutral" then - slots = slots:append(INVENTORY.NEUTRAL_SLOTS) - end - end - - slots = slots:value() - - for _, slot in ipairs(slots) do - local item = self:GetItemInSlot(slot) - - if item then - local ret = { callback(item) } - local continue = true - - if #ret > 0 then - continue = table.remove(ret, 1) - end - - if not continue then - return unpack(ret) - end - end - end - - return nil -end - ---- Returns an array of names of all items in the unit's inventory. --- @tparam[opt={}] table options Accepts the same options as @{ForEachItem} --- @tparam[opt=false] bool options.sort Sorts the resulting array. --- @treturn {string,...} Array of item names -function M:ItemNames(options) - local names = {} - - options = options or {} - - self:ForEachItem(function(item) - table.insert(names, item:GetAbilityName()) - end, options) - - if options.sort then - names = m.sort(names) - end - - return names -end - ---- Add items with given names. --- @tparam {string,...} items Array of item names --- @tparam[opt={}] table options Options table --- @tparam[opt=false] bool options.onlyMissing Only add missing items --- (the diff between the inventory and the array) --- @treturn {CDOTA_Item,...} Array of added item entities -function M:AddItemsByName(items, options) - if not self:HasInventory() then - error(ERRF_UNIT_NO_INVENTORY:format(self.name)) - end - - options = options or {} - items = m.chain(items) - - if options.onlyMissing then - items = items:difference(self:ItemNames()) - end - - items = items:map(function(name) - return self:AddItemByName(name) - end) - - return items:value() -end - ---- Finds item by name in inventory. --- @tparam string name Item name --- @tparam[opt={}] table options Accepts the same options as @{ForEachItem} --- @treturn ?CDOTA_Item Item if found, `nil` otherwise -function M:FindItemInInventory(name, options) - return self:ForEachItem(function(item) - if item:GetAbilityName() == name then - return false, item - end - end, options) -end - ---- Removes all items. --- @tparam[opt={}] table options Accepts the same options as @{ForEachItem} --- @tparam[opt=false] bool options.endCooldown Reset item cooldowns before removing --- @treturn {CDOTA_Item,...} An array of removed items -function M:RemoveItems(options) - options = options or {} - - local removed = {} - - self:ForEachItem(function(item) - if options.endCooldown then - item:EndCooldown() - end - - self:RemoveItem(item) - - table.insert(removed, item) - end, options) - - return removed -end - ---- Clears all items cooldowns. --- @tparam[opt={}] table options Accepts the same options as @{ForEachItem} -function M:EndItemCooldowns(options) - self:ForEachItem(function(item) - item:EndCooldown() - end, options) -end - ---- Removes all dropped items owned by this unit. -function M:RemoveDroppedItems() - local removed = {} - - for i = 0, GameRules:NumDroppedItems() - 1 do - local ent = GameRules:GetDroppedItem(i) - local item = EntityFramework:CreateEntity("CDOTA_Item", ent) - local purchaser = item:GetPurchaser() - local purchaserEntIdx = purchaser and purchaser:GetEntityIndex() - - if purchaserEntIdx == self:GetEntityIndex() then - table.insert(removed, item) - end - end - - for _, item in ipairs(removed) do - item:RemoveSelf() - end - - return removed -end - ---- Finds ability or item by name. --- @tparam string name Ability or item name --- @treturn CDOTABaseAbility|CDOTA_Item Ability or item entity if found --- @treturn nil otherwise -function M:FindAbilityOrItem(name) - if self:HasAbility(name) then - return self:FindAbilityByName(name) - end - - if self:HasInventory() and self:HasItemInInventory(name) then - return self:FindItemInInventory(name) - end - - return nil -end - ---- Iterates over the unit's abilities, yielding each non-nil ability. --- @tparam function callback Iterator function -function M:ForEachAbility(callback) - for i = 0, self.entity:GetAbilityCount() - 1 do - local ability = self:GetAbilityByIndex(i) - - if ability ~= nil then - local ret = { callback(ability) } - local continue = true - - if #ret > 0 then - continue = table.remove(ret, 1) - end - - if not continue then - return unpack(ret) - end - end - end - - return nil -end - ---- Clears all abilities cooldowns. -function M:EndAbilityCooldowns() - self:ForEachAbility(function(ability) - ability:EndCooldown() - end) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/classes.lua b/game/scripts/vscripts/invokation/dota2/classes.lua deleted file mode 100644 index 5c980e1..0000000 --- a/game/scripts/vscripts/invokation/dota2/classes.lua +++ /dev/null @@ -1,7 +0,0 @@ ---- Registers C++ proxy classes. --- @module invokation.dota2.classes -local ENTITY_CLASSES = { "CDOTABaseAbility", "CDOTA_Item", "CDOTA_BaseNPC", "CDOTA_BaseNPC_Hero" } - -for _, className in ipairs(ENTITY_CLASSES) do - EntityFramework:CreateCppClassProxy(className) -end diff --git a/game/scripts/vscripts/invokation/dota2/custom_events.lua b/game/scripts/vscripts/invokation/dota2/custom_events.lua deleted file mode 100644 index 1a97ab2..0000000 --- a/game/scripts/vscripts/invokation/dota2/custom_events.lua +++ /dev/null @@ -1,55 +0,0 @@ ---- Custom events helpers. --- @module invokation.dota2.custom_events -local tablex = require("pl.tablex") - -local EVENTS = require("invokation.const.custom_events") - -local M = {} - -tablex.update(M, EVENTS) - -local function createHandler(callback) - return function(playerEntIdx, ...) - local player = EntIndexToHScript(playerEntIdx) - return callback(player, ...) - end -end - ---- Register a callback to be called when a particular custom event arrives. --- @tparam string event --- @tparam function callback --- @treturn int Listener id that can be used to unregister later -function M.Subscribe(event, callback) - return CustomGameEventManager:RegisterListener(event, createHandler(callback)) -end - ---- Unregister a given listener. --- @tparam int listenerId -function M.Unsubscribe(listenerId) - return CustomGameEventManager:UnregisterListener(listenerId) -end - ---- Send event to all players. --- @tparam string event --- @tparam table payload -function M.SendAll(event, payload) - return CustomGameEventManager:Send_ServerToAllClients(event, payload or {}) -end - ---- Send event to player. --- @tparam string event --- @tparam CDOTAPlayer player --- @tparam table payload -function M.SendPlayer(event, player, payload) - return CustomGameEventManager:Send_ServerToPlayer(player, event, payload or {}) -end - ---- Send event to team. --- @tparam string event --- @tparam int team --- @tparam table payload -function M.SendTeam(event, team, payload) - return CustomGameEventManager:Send_ServerToTeam(team, event, payload or {}) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/hats.lua b/game/scripts/vscripts/invokation/dota2/hats.lua deleted file mode 100644 index 9ebf24b..0000000 --- a/game/scripts/vscripts/invokation/dota2/hats.lua +++ /dev/null @@ -1,32 +0,0 @@ ---- Hats helpers. --- @module invokation.dota2.hats --- @author Noya (09.08.2015) -local M = {} - ---- Hides all dem hats. --- @tparam CDOTA_BaseNPC unit -function M.HideWearables(unit) - -- Keep every wearable handle in a table to show them later - unit._hiddenWearables = unit._hiddenWearables or {} - - local model = unit:FirstMoveChild() - - while model ~= nil do - if model:GetClassname() == "dota_item_wearable" then - model:AddEffects(EF_NODRAW) -- Set model hidden - table.insert(unit._hiddenWearables, model) - end - - model = model:NextMovePeer() - end -end - ---- Shows all dem hats. --- @tparam CDOTA_BaseNPC unit -function M.ShowWearables(unit) - for _, v in pairs(unit._hiddenWearables) do - v:RemoveEffects(EF_NODRAW) - end -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/kv.lua b/game/scripts/vscripts/invokation/dota2/kv.lua deleted file mode 100644 index 01e284f..0000000 --- a/game/scripts/vscripts/invokation/dota2/kv.lua +++ /dev/null @@ -1,221 +0,0 @@ ---- KeyValue utils. --- @module invokation.dota2.kv - -local m = require("moses") -local stringx = require("pl.stringx") - -local ENUMS = require("invokation.const.enums") - -local M = {} - -local function warn(fmt, ...) - if not IsInToolsMode() then - return - end - - print("(WARNING) [kv] " .. fmt:format(...)) -end - ---- Transforms a KeyValue table value with numeric strings as keys into an array. --- @tparam {[string]=any,...} value String-keyed table --- @return Unmodified value if it's not a table --- @treturn {any,...} Array of values -function M.Array(value) - if not m.isTable(value) then - return value - end - - return m.map(value, function(v, k) - return tonumber(k), v - end) -end - ---- Transforms a KeyValue value into a boolean. --- @tparam any value Value --- @treturn bool `true` if the value equals to the number `1` --- @treturn bool `false` otherwise -function M.Bool(value) - return value == 1 -end - ---- Splits a KeyValue string value into an array of strings. --- @tparam string value String value --- @tparam string sep Separator --- @return Unmodified value if it's not a string --- @treturn {string,...} String array -function M.Strings(value, sep) - if not m.isString(value) then - return value - end - - value = stringx.split(value, sep) - - return m.map(value, m.unary(stringx.strip)) -end - ---- Splits a KeyValue string value into an array of numbers. --- @tparam string value String value --- @tparam[opt=" "] string sep Separator --- @return Unmodified value if it's not a string --- @treturn {number,...} Number array -function M.Numbers(value, sep) - sep = sep or " " - value = M.Strings(value, sep) - - if not m.isTable(value) then - return value - end - - return m.map(value, m.unary(tonumber)) -end - ---- Converts an enum name into an enum value (a global value defined by the engine). --- @tparam string name Enum name --- @treturn nil If name is `nil` --- @treturn int `0` if the enum name is invalid (not a string) or is not defined --- @treturn int The enum value if it exists -function M.EnumValue(name) - if name == nil then - return - end - - if not m.isString(name) then - warn("EnumValue(): invalid name %s [%s]", name, type(name)) - return 0 - end - - -- selene: allow(global_usage) - local value = _G[name] or ENUMS[name] - - if value == nil then - warn("EnumValue(): name %q not found", name) - return 0 - end - - return value -end - ---- Splits a KeyValue string value into an array of enum values. --- --- It uses the separator `"|"` to split the string, then converts the values --- using @{EnumValue}. --- --- @tparam string value String value --- @return Unmodified value if it's not a string --- @treturn {int,...} Array of enum values (integers) -function M.EnumValues(value) - value = M.Strings(value, "|") - - if not m.isTable(value) then - return value - end - - return m.map(value, M.EnumValue) -end - ---- Converts a KeyValue string value into a numeric bitmap flag. --- --- It uses the separator `"|"` to split the string, then converts the values --- using @{EnumValue} and reduces the values with bitwise OR. --- --- @tparam string value String value --- @return Unmodified value if it's not a string --- @treturn int OR'ed enum values -function M.Flags(value) - value = M.EnumValues(value) - - if not m.isTable(value) then - return value - end - - return m.reduce(value, bit.bor) -end - -local ABILITY_SPECIAL_CAST = { FIELD_FLOAT = M.Numbers, FIELD_INTEGER = M.Numbers } - ---- Table of known extra fields to be converted in @{AbilitySpecial}. --- @table ABILITY_SPECIAL_EXTRA -local ABILITY_SPECIAL_EXTRA = { - CalculateSpellDamageTooltip = M.Bool, -- bool - RequiresScepter = M.Bool, -- bool -} - -local function castAbilitySpecialField(key, value, varType) - if key == "var_type" then - return value - end - - local castFn = ABILITY_SPECIAL_EXTRA[key] - - if castFn then - return castFn(value) - end - - if m.isString(value) and value:match("%s") then - castFn = ABILITY_SPECIAL_CAST[varType] - - if castFn then - return castFn(value) - end - - warn("AbilitySpecial(): unknown 'var_type' value: %q", varType) - end - - return value -end - ---- AbilitySpecialEntry spec --- @table AbilitySpecialEntry --- @tfield string var_type --- @field[opt] ... variable number of special fields - ---- Parses a single ability special value (a single entry in an `AbilitySpecial` value). --- --- It converts the "main" special key value using the type provided in the --- `var_type` field and converts known extra fields to known types. --- --- For example, if `var_type` is `"FIELD_FLOAT"` and the main special key --- `cooldown` has the value `"10.5 7.3 5.1"`, it will set `cooldown` in the --- result with the value `{10.5, 7.3, 5.1}` (an array of actual floats). --- --- See @{ABILITY_SPECIAL_EXTRA} for the table of known extra fields. --- --- @tparam AbilitySpecialEntry value An `AbilitySpecial` entry --- @return Unmodified value if it's not a string --- @return Unmodified value if it does not contain a `var_type` field --- @treturn AbilitySpecialEntry Clone of original value with the "main" field --- converted to the appropriate type -function M.AbilitySpecial(value) - if not m.isTable(value) then - return value - end - - if not m.isString(value.var_type) then - return value - end - - local castField = - m.chain(castAbilitySpecialField):partialRight(value.var_type):rearg({ 2, 1 }):value() - - return m.map(value, castField) -end - ---- Parses a whole `AbilitySpecial` field. --- --- Converts the field into an array with @{Array}, then uses @{AbilitySpecial} --- to parse each entry in the field. --- --- @tparam {[string]=AbilitySpecialEntry,...} value `AbilitySpecial` field value --- @return Unmodified value if it's not a table --- @treturn {AbilitySpecialEntry,...} Array of parsed entries -function M.AbilitySpecials(value) - value = M.Array(value) - - if not m.isTable(value) then - return value - end - - return m.map(value, M.AbilitySpecial) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/kv/AbilityKeyValues.lua b/game/scripts/vscripts/invokation/dota2/kv/AbilityKeyValues.lua deleted file mode 100644 index f1fd0f0..0000000 --- a/game/scripts/vscripts/invokation/dota2/kv/AbilityKeyValues.lua +++ /dev/null @@ -1,45 +0,0 @@ ---- AbilityKeyValues class. --- @classmod invokation.dota2.kv.AbilityKeyValues -local KV = require("invokation.dota2.kv") -local class = require("pl.class") -local m = require("moses") - -local M = class() - ---- Constructor. --- @tparam string name Ability name --- @tparam {[string]=any,...} kv KeyValues data -function M:_init(name, kv) - local fields = m.extend({}, { Name = name }, kv) - - m.extend(self, fields) - - self.__data = fields - self.AbilitySpecial = KV.AbilitySpecials(kv.AbilitySpecial) - self.AbilityBehavior = KV.Flags(kv.AbilityBehavior) - self.AbilityUnitTargetFlags = KV.Flags(kv.AbilityUnitTargetFlags) - self.AbilityUnitTargetTeam = KV.EnumValues(kv.AbilityUnitTargetTeam) - self.AbilityUnitTargetType = KV.Flags(kv.AbilityUnitTargetType) - self.AbilityCastPoint = KV.Numbers(kv.AbilityCastPoint) - self.AbilityCastRange = KV.Numbers(kv.AbilityCastRange) - self.AbilityChannelTime = KV.Numbers(kv.AbilityChannelTime) - self.AbilityCooldown = KV.Numbers(kv.AbilityCooldown) - self.AbilityDamage = KV.Numbers(kv.AbilityDamage) - self.AbilityDuration = KV.Numbers(kv.AbilityDuration) - self.AbilityManaCost = KV.Numbers(kv.AbilityManaCost) - self.AbilityCastAnimation = KV.EnumValue(kv.AbilityCastAnimation) -end - ---- Serializes the KeyValues data --- @treturn {[string]=any,...} Serialized data -function M:Serialize() - return self.__data -end - ---- Returns an iterator function that iterates over the KeyValues entries. --- @treturn iter(string,any) -function M:Entries() - return pairs(self:Serialize()) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/kv/HeroKeyValues.lua b/game/scripts/vscripts/invokation/dota2/kv/HeroKeyValues.lua deleted file mode 100644 index e2bcb18..0000000 --- a/game/scripts/vscripts/invokation/dota2/kv/HeroKeyValues.lua +++ /dev/null @@ -1,69 +0,0 @@ ---- HeroKeyValues class. --- @classmod invokation.dota2.kv.HeroKeyValues -local Talents = require("invokation.dota2.talents") -local class = require("pl.class") -local m = require("moses") - -local M = class() - -local MAX_TALENTS_COUNT = 8 -local ABILITY_KEY_PATT = "^Ability(%d+)$" - ---- Constructor. --- @tparam string name Hero name --- @tparam {[string]=any,...} kv KeyValues data -function M:_init(name, kv) - local fields = m.extend({}, { Name = name }, kv) - - m.extend(self, fields) - - self.__data = fields -end - ---- Serializes the KeyValues data --- @treturn {[string]=any,...} Serialized data -function M:Serialize() - return self.__data -end - ---- Returns an iterator function that iterates over the KeyValues entries. --- @treturn iter(string,any) -function M:Entries() - return pairs(self:Serialize()) -end - -local function selectAbilityEntry(key, value) - local mAbilityId = key:match(ABILITY_KEY_PATT) - - if mAbilityId ~= nil and value ~= "" then - return tonumber(mAbilityId), value - end - - return nil, nil -end - ---- Returns an array of ability names. --- @treturn {string,...} Array of ability names -function M:Abilities() - if self.abilities == nil then - self.abilities = m.map(self:Serialize(), m.rearg(selectAbilityEntry, { 2, 1 })) - end - - return self.abilities -end - ---- Returns an array of talent ability names. --- @treturn talents.Talents Table of talent ability names -function M:Talents() - if self.talents == nil then - local start = self.AbilityTalentStart - local finish = start + MAX_TALENTS_COUNT - 1 - local abilities = m.chain(self:Abilities()):slice(start, finish):compact():value() - - self.talents = Talents.NamesArrayToEnumsTable(abilities) - end - - return self.talents -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/kv/ItemKeyValues.lua b/game/scripts/vscripts/invokation/dota2/kv/ItemKeyValues.lua deleted file mode 100644 index 8409883..0000000 --- a/game/scripts/vscripts/invokation/dota2/kv/ItemKeyValues.lua +++ /dev/null @@ -1,55 +0,0 @@ ---- ItemKeyValues class. --- @classmod invokation.dota2.kv.ItemKeyValues -local KV = require("invokation.dota2.kv") -local class = require("pl.class") -local m = require("moses") - -local M = class() - ---- Constructor. --- @tparam string name Item name --- @tparam {[string]=any,...} kv KeyValues data -function M:_init(name, kv) - local fields = m.extend({}, { Name = name }, kv) - - m.extend(self, fields) - - self.__data = fields - self.AbilitySpecial = KV.AbilitySpecials(kv.AbilitySpecial) - self.AbilityBehavior = KV.Flags(kv.AbilityBehavior) - self.ItemDeclarations = KV.Strings(kv.ItemDeclarations, "|") - self.ItemShopTags = KV.Strings(kv.ItemShopTags, ";") - self.ItemAliases = KV.Strings(kv.ItemAliases, ";") - self.ShouldBeSuggested = KV.Bool(kv.ShouldBeSuggested) - self.SideShop = KV.Bool(kv.SideShop) -end - ---- Serializes the KeyValues data --- @treturn {[string]=any,...} Serialized data -function M:Serialize() - return self.__data -end - ---- Returns an iterator function that iterates over the KeyValues entries. --- @treturn iter(string,any) -function M:Entries() - return pairs(self:Serialize()) -end - ---- Checks if the item matches the given search query. --- --- It searches for matches in these entries: --- --- * `ItemShopTags` --- * `ItemAliases` --- --- @tparam string query Query string --- @treturn bool -function M:MatchesQuery(query) - local matcher = m.chain(string.match):partialRight(query):unary():value() - - return (m.isTable(self.ItemShopTags) and m.findIndex(self.ItemShopTags, matcher)) - or (m.isTable(self.ItemAliases) and m.findIndex(self.ItemAliases, matcher)) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/kv/ItemsKeyValues.lua b/game/scripts/vscripts/invokation/dota2/kv/ItemsKeyValues.lua deleted file mode 100644 index 48f2d6e..0000000 --- a/game/scripts/vscripts/invokation/dota2/kv/ItemsKeyValues.lua +++ /dev/null @@ -1,47 +0,0 @@ ---- Collection of `ItemKeyValues`. --- @classmod invokation.dota2.kv.ItemsKeyValues -local ItemKeyValues = require("invokation.dota2.kv.ItemKeyValues") -local class = require("pl.class") -local m = require("moses") - -local ITEMS = require("invokation.const.items") - -local M = class() - -local ITEM_KEY_PATT = "^item_" - -local function selectItemEntry(name, kv) - if name:match(ITEM_KEY_PATT) and type(kv) == "table" then - return name, ItemKeyValues(name, kv) - end - - return nil, nil -end - ---- Constructor. -function M:_init() - self.__data = m.map(ITEMS.KEY_VALUES, m.rearg(selectItemEntry, { 2, 1 })) -end - ---- Returns an iterator function that iterates over the @{ItemKeyValues} entries. --- @treturn iter(string,ItemKeyValues) -function M:Entries() - return pairs(self.__data) -end - ---- Searches for item KeyValues matching the given query. --- @tparam string query Query string --- @treturn {[string]=ItemKeyValues,...} A table of found entries -function M:Search(query) - local items = {} - - for _, kv in self:Entries() do - if kv:MatchesQuery(query) then - items[kv.Name] = kv:Serialize() - end - end - - return items -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/sound_events.lua b/game/scripts/vscripts/invokation/dota2/sound_events.lua deleted file mode 100644 index cd90b2a..0000000 --- a/game/scripts/vscripts/invokation/dota2/sound_events.lua +++ /dev/null @@ -1,75 +0,0 @@ ---- Sound events helpers. --- @module invokation.dota2.sound_events -local tablex = require("pl.tablex") - -local EVENTS = require("invokation.const.sound_events") - -local M = {} - -tablex.update(M, EVENTS) - ---- Play named sound for all players. --- @tparam string event -function M.EmitGlobal(event) - return EmitGlobalSound(event) -end - ---- Play named sound only on the client for the passed in player. --- @tparam string event --- @tparam CDOTAPlayer player -function M.EmitOnPlayer(event, player) - return EmitSoundOnClient(event, player) -end - ---- Play named sound on entity. --- @tparam string event --- @tparam CBaseEntity entity -function M.EmitOnEntity(event, entity) - return EmitSoundOn(event, entity) -end - ---- Emit a sound on a location from a unit. --- @tparam string event --- @tparam CBaseEntity entity --- @tparam Vector location -function M.EmitOnLocationWithCaster(event, entity, location) - return EmitSoundOnLocationWithCaster(location, event, entity) -end - ---- Emit a sound on a location from a unit, only for players allied with that unit. --- @tparam string event --- @tparam CBaseEntity entity --- @tparam Vector location -function M.EmitOnLocationForAllies(event, entity, location) - return EmitSoundOnLocationForAllies(location, event, entity) -end - ---- Emit an announcer sound for all players. --- @tparam string event -function M.EmitAnnouncer(event) - return EmitAnnouncerSound(event) -end - ---- Emit an announcer sound for a player. --- @tparam string event --- @tparam CDOTAPlayer player -function M.EmitAnnouncerForPlayer(event, player) - return EmitAnnouncerSoundForPlayer(event, player:GetPlayerID()) -end - ---- Emit an announcer sound for a team. --- @tparam string event --- @tparam int team -function M.EmitAnnouncerForTeam(event, team) - return EmitAnnouncerSoundForTeam(event, team) -end - ---- Emit an announcer sound for a team at a specific location. --- @tparam string event --- @tparam int team --- @tparam Vector location -function M.EmitAnnouncerOnLocationForTeam(event, team, location) - return EmitAnnouncerSoundForTeamOnLocation(event, team, location) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/talents.lua b/game/scripts/vscripts/invokation/dota2/talents.lua deleted file mode 100644 index 2587f51..0000000 --- a/game/scripts/vscripts/invokation/dota2/talents.lua +++ /dev/null @@ -1,96 +0,0 @@ ---- Talents helpers. --- @module invokation.dota2.talents -local m = require("moses") - -local M = {} - ---- No talents selected -M.NONE = 0x00 ---- Level 10 right talent -M.L10_RIGHT = 0x01 ---- Level 10 left talent -M.L10_LEFT = 0x02 ---- Level 15 right talent -M.L15_RIGHT = 0x04 ---- Level 15 left talent -M.L15_LEFT = 0x08 ---- Level 20 right talent -M.L20_RIGHT = 0x10 ---- Level 20 left talent -M.L20_LEFT = 0x20 ---- Level 25 right talent -M.L25_RIGHT = 0x40 ---- Level 25 left talent -M.L25_LEFT = 0x80 - ---- Talents enum --- @table Enum --- @tfield int 1 L10_RIGHT --- @tfield int 2 L10_LEFT --- @tfield int 3 L15_RIGHT --- @tfield int 4 L15_LEFT --- @tfield int 5 L20_RIGHT --- @tfield int 6 L20_LEFT --- @tfield int 7 L25_RIGHT --- @tfield int 8 L25_LEFT -M.ENUM = { - M.L10_RIGHT, - M.L10_LEFT, - M.L15_RIGHT, - M.L15_LEFT, - M.L20_RIGHT, - M.L20_LEFT, - M.L25_RIGHT, - M.L25_LEFT, -} - -local LEVEL_SIDE = { - [M.L10_RIGHT] = { 10, "RIGHT" }, - [M.L10_LEFT] = { 10, "LEFT" }, - [M.L15_RIGHT] = { 15, "RIGHT" }, - [M.L15_LEFT] = { 15, "LEFT" }, - [M.L20_RIGHT] = { 20, "RIGHT" }, - [M.L20_LEFT] = { 20, "LEFT" }, - [M.L25_RIGHT] = { 25, "RIGHT" }, - [M.L25_LEFT] = { 25, "LEFT" }, -} - ---- Returns the bitwise OR'ed values --- @tparam {int,...} ... @{Enum} vararg values --- @treturn int OR'ed value -function M.Select(...) - return bit.bor(...) -end - ---- Talents table. --- --- Keys are @{Enum} values and values are ability names. --- --- @table Talents --- @tfield string L10_RIGHT Level 10 right talent ability name --- @tfield string L10_LEFT Level 10 left talent ability name --- @tfield string L15_RIGHT Level 15 right talent ability name --- @tfield string L15_LEFT Level 15 left talent ability name --- @tfield string L20_RIGHT Level 20 right talent ability name --- @tfield string L20_LEFT Level 20 left talent ability name --- @tfield string L25_RIGHT Level 25 right talent ability name --- @tfield string L25_LEFT Level 25 left talent ability name - ---- Maps an array of ability names to a table of talents enums and talent ability names --- @tparam {string,...} names Ability names --- @treturn Talents Talents table -function M.NamesArrayToEnumsTable(names) - return m.map(names, function(name, idx) - return M.ENUM[idx], name - end) -end - ---- Converts an enum value into level and side values. --- @tparam int value @{Enum} value --- @treturn ?int Level if value is valid, `nil` otherwise --- @treturn ?string Side if value is valid, `nil` otherwise -function M.LevelAndSide(value) - return unpack(LEVEL_SIDE[value] or { nil, nil }) -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/timers.lua b/game/scripts/vscripts/invokation/dota2/timers.lua deleted file mode 100644 index a0e9446..0000000 --- a/game/scripts/vscripts/invokation/dota2/timers.lua +++ /dev/null @@ -1,246 +0,0 @@ ---- Timers framework. --- --- Original code: [https://github.com/bmddota/barebones](https://github.com/bmddota/barebones) --- --- @module invokation.dota2.timers --- @author bmddota (original author) --- @author 13k (updates) --- @license Apache License 2.0 --- @copyright bmddota -local M = { _VERSION = "1.06" } - -local THINK_NAME = "timers" -local THINK_INTERVAL = 0.01 - -local ERRF_INVALID_TIMER_ID = "Invalid timer id: %s [%s]" -local ERRF_INVALID_TIMER_CALLBACK = "Invalid timer %q: callback must be a function" -local ERRF_INVALID_TIMER_ALREADY_REGISTERED = "Invalid timer %q: already registered" - ---- Default error handler. --- @tparam string msg Error message --- @treturn string Error message and stack trace. -function M.defaultErrorHandler(msg) - return msg .. "\n" .. debug.traceback() .. "\n" -end - -local function generateUniqueId() - return UniqueString("timer") -end - -local function handleError(timer, err) - print("[ERROR] Timer " .. timer.id .. ":") - print(err) -end - -local Timer = require("pl.class")() - -function Timer:_init(options) - self.id = options.id or generateUniqueId() - self.callback = options.callback - self.args = options.args or {} - self.realtime = options.realtime - self.delay = options.delay or 0 - self.onError = options.onError or M.defaultErrorHandler - self.paused = options.paused - self.at = (options.at or self:now()) + self.delay - - assert(type(self.id) == "string", ERRF_INVALID_TIMER_ID:format(self.id, type(self.id))) - assert(type(self.callback) == "function", ERRF_INVALID_TIMER_CALLBACK:format(self.id)) - - self.callbackWrapper = function() - return self.callback(unpack(self.args)) - end -end - -function Timer:now() - return self.realtime and Time() or GameRules:GetGameTime() -end - ---- Initializes timers. --- --- Should be placed inside the custom game's `Activate` function. --- --- @tparam[opt=0.01] float interval Timer processing interval -function M:Start(interval) - self.interval = interval or THINK_INTERVAL - self.timers = {} - - GameRules:GetGameModeEntity():SetThink("think", self, THINK_NAME, self.interval) -end - -function M:think() - for _, timer in pairs(self.timers) do - self:processTimer(timer) - end - - return self.interval -end - -function M:processTimer(timer) - if timer.paused then - return - end - - if timer.at > timer:now() then - return - end - - local removeTimer = true - local success, result = xpcall(timer.callbackWrapper, timer.onError) - - if not success then - handleError(timer, result) - elseif type(result) == "number" then - timer.at = timer.at + result - removeTimer = false - end - - if removeTimer then - self.timers[timer.id] = nil - end -end - ---[[-- - Creates a timer with the given options. - - @usage - -- Immediately calls `obj.fn(obj, 13)` (equivalent to `obj:fn(13)`), - -- if `fn` returns a number, repeats at that interval - Create({callback = obj.fn, args = {obj, 13}}) - - -- 10 seconds delayed, run once using game time (respect pauses) - Create({ - delay = 10.0, - callback = function() - print("Hello. I'm running 10 seconds after when I was started.") - end - }) - - -- 10 second delayed, run once regardless of pauses - Create({ - delay = 10.0, - realtime = true, - callback = function() - print("Hello. I'm running 10 seconds after I was started even if someone paused the game.") - end - }) - - -- At a specific time, run once using game time (respect pauses) - Create({ - at = GameRules:GetGameTime() + 10.0, - callback = function() - print("Hello. I'm running when I was scheduled to run.") - end - }) - - -- At a specific time, run once using real time (regardless of pauses) - Create({ - at = Time() + 10.0, - realtime = true, - callback = function() - print("Hello. I'm running when I was scheduled to run, even if someone paused the game.") - end - }) - - -- At a specific time, 10 second delay from that time, run once using game time (respect pauses) - Create({ - at = GameRules:GetGameTime() + 30.0, - delay = 10.0, - callback = function() - print("Hello. I'm running 10 seconds after when I was scheduled to run.") - end - }) - - -- A timer running every second that starts 5 seconds in the future. - -- Uses game time, respecting pauses. - Create({ - delay = 5.0, - callback = function() - print("Hello. I'm running 5 seconds after you called me and then every second thereafter.") - return 1.0 - end - }) - - -- A timer running every second that starts after 2 minutes regardless of pauses - Create({ - id = "uniqueTimerId", - delay = 120.0, - realtime = true, - callback = function() - print("Hello. I'm running after 2 minutes and then every second thereafter.") - return 1.0 - end - }) - - @tparam table options Options table - @tparam function options.callback Timer function - @tparam[opt] string options.id Timer id - @tparam[opt] list options.args List of arguments to pass to the callback - @tparam[opt] number options.at Specific start time (timestamp in seconds). - `nil`, `0` or negative number means it starts immediately - @tparam[opt] number options.delay Delay start time (in seconds). - `nil`, `0` or negative number means it starts immediately - @tparam[opt=false] bool options.realtime If `true`, uses real clock (ignores pauses) - @tparam[opt=false] bool options.paused If `true`, the timer starts paused and must be manually - unpaused with @{Unpause} - @tparam[opt=nil] function options.onError Error handler function. - If `nil`, uses @{defaultErrorHandler} -]] -function M:Create(options) - local timer = Timer(options) - - assert(self.timers[timer.id] == nil, ERRF_INVALID_TIMER_ALREADY_REGISTERED:format(timer.id)) - - self.timers[timer.id] = timer - - return timer.id -end - -function M:setPaused(id, value) - local timer = self.timers[id] - - if timer == nil then - return nil - end - - timer.paused = value - return id -end - ---- Pauses a timer. --- @tparam string id Timer id --- @treturn ?string Id of paused timer or `nil` if the id isn't registered -function M:Pause(id) - return self:setPaused(id, true) -end - ---- Unpauses a timer. --- @tparam string id Timer id --- @treturn ?string Id of paused timer or `nil` if the id isn't registered -function M:Unpause(id) - return self:setPaused(id, false) -end - ---- Cancels a timer. --- @tparam string id Timer id --- @treturn ?string Id of canceled timer or `nil` if the id isn't registered -function M:Cancel(id) - local timer = self.timers[id] - self.timers[id] = nil - return timer and id -end - ---- Cancels all timers. --- @treturn {string,...} Array of timer ids that were canceled -function M:CancelAll() - local canceled = {} - - for id, _ in pairs(self.timers) do - self.timers[id] = nil - table.insert(canceled, id) - end - - return canceled -end - -return M diff --git a/game/scripts/vscripts/invokation/dota2/units.lua b/game/scripts/vscripts/invokation/dota2/units.lua deleted file mode 100644 index 70dd5a0..0000000 --- a/game/scripts/vscripts/invokation/dota2/units.lua +++ /dev/null @@ -1,72 +0,0 @@ ---- Units helpers. --- @module invokation.dota2.units -local m = require("moses") - -local NAMES = require("invokation.const.units") - -local M = {} - -m.extend(M, NAMES) - ---- Creates an unit by name. --- @tparam string name Unit name --- @tparam table options Options table --- @tparam Vector options.location Target location --- @tparam int options.team Team number --- @tparam[opt=true] bool options.findClearSpace Find clear space for the unit --- @tparam[opt] CDOTA_BaseNPC options.npcOwner NPC owner --- @tparam[opt] CDOTA_BaseNPC options.unitOwner Unit Owner --- @treturn CDOTA_BaseNPC Created unit -function M.Create(name, options) - options = m.extend({ findClearSpace = true }, options or {}) - - return CreateUnitByName( - name, - options.location, - m.toBoolean(options.findClearSpace), - options.npcOwner, - options.unitOwner, - options.team - ) -end - ---- Creates an unit by name (async). --- @tparam string name Unit name --- @tparam table options Options table --- @tparam Vector options.location Target location --- @tparam int options.team Team number --- @tparam function options.callback Callback function --- @tparam[opt=true] bool options.findClearSpace Find clear space for the unit --- @tparam[opt] CDOTA_BaseNPC options.npcOwner NPC owner --- @tparam[opt] CDOTA_BaseNPC options.unitOwner Unit Owner --- @treturn int Some kind of async registration id? -function M.CreateAsync(name, options) - options = m.extend({ findClearSpace = true }, options or {}) - - return CreateUnitByNameAsync( - name, - options.location, - m.toBoolean(options.findClearSpace), - options.npcOwner, - options.unitOwner, - options.team, - options.callback - ) -end - ---- Creates a new data-driven unit with the given table. --- @tparam table definition Unit definition table --- @tparam Vector location Target location --- @treturn CDOTA_BaseNPC Created unit -function M.CreateFromTable(definition, location) - return CreateUnitFromTable(definition, location) -end - ---- Kills and removes the given unit. --- @tparam unit CDOTA_BaseNPC unit Unit entity -function M.Destroy(unit) - unit:ForceKill(false) - unit:RemoveSelf() -end - -return M diff --git a/game/scripts/vscripts/invokation/game_mode/commands.lua b/game/scripts/vscripts/invokation/game_mode/commands.lua deleted file mode 100644 index 0d82955..0000000 --- a/game/scripts/vscripts/invokation/game_mode/commands.lua +++ /dev/null @@ -1,281 +0,0 @@ ---- Console Commands --- @submodule invokation.GameMode - -local Invoker = require("invokation.dota2.Invoker") -local Logger = require("invokation.Logger") -local pp = require("pl.pretty") -local tablex = require("pl.tablex") - -local COMMANDS = require("invokation.const.commands") - ---- Console Commands --- @section commands - -local function createHandler(gameMode, methodName) - return function(command, ...) - gameMode:d(command, methodName, ...) - - local callback = gameMode:methodHandler(methodName) - local player = Convars:GetDOTACommandClient() - - return callback(player, ...) - end -end - -function GameMode:registerCommand(command, methodName, help, flags) - return Convars:RegisterCommand(command, createHandler(self, methodName), help, flags or 0) -end - -function GameMode:registerCommands() - for _, spec in ipairs(COMMANDS) do - if not spec.dev or (spec.dev and self.env.development) then - self:registerCommand(spec.name, spec.method, spec.help, spec.flags) - end - end - - self:d(" register commands") -end - ---- Sets debugging on/off. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam ?string arg `"1"`: enables debugging, `"0"`: disables debugging, --- `nil`: prints debugging value. -function GameMode:CommandSetDebug(_player, arg) - if arg == "1" then - self.logger.level = Logger.DEBUG - elseif arg == "0" then - self.logger.level = Logger.INFO - else - print(string.format("inv_debug = %d", self.logger.level <= Logger.DEBUG and 1 or 0)) - end -end - ---- Placeholder command to run miscellaneous debug code. --- --- Use `script_reload` to reload after changes. --- --- @tparam CDOTAPlayer player Player who issued this console command. --- @param[opt] ... varargs. --- selene: allow(unused_variable) -function GameMode:CommandDebugMisc(_player, ...) end - ---- Dumps Lua version. --- @tparam CDOTAPlayer player Player who issued this console command -function GameMode:CommandDumpLuaVersion() - print(_VERSION) -end - ---- Dumps global value. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string name Dot-separated value name -function GameMode:CommandDumpGlobal(_player, name) - if not name then - return - end - - -- selene: allow(global_usage) - local value = _G - - for segment in name:gmatch("([^.]+)%.?") do - value = value[segment] - end - - local typ = type(value) - local repr = pp.write(value) - - print(string.format("%q (%s): %s", name, typ, repr)) - - if typ == "function" then - local info = debug.getinfo(value) - print(string.format("source: %s:%d", info.source, info.linedefined)) - end -end - ---- Searches a global value. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string pattern Name pattern (uses `string.match` for matching) -function GameMode:CommandFindGlobal(_player, pattern) - if not pattern then - return - end - - local matches = {} - - -- selene: allow(global_usage) - for name, _ in pairs(_G) do - if name:match(pattern) then - table.insert(matches, name) - end - end - - table.sort(matches) - - print(string.format("Globals matching pattern %q:", pattern)) - - for _, match in ipairs(matches) do - print(string.format(" * %s", match)) - end - - print("---") -end - ---- Queries items. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string query Query string -function GameMode:CommandItemQuery(_player, query) - if not query then - return - end - - local items = self.itemsKV:Search(query) - - if tablex.size(items) == 0 then - print("No items found.") - return - end - - for name, kv in pairs(items) do - local repr = pp.write(kv) - print(name, repr) - end -end - -local function debugAbility(a, simple) - if a == nil then - return nil - end - - if simple then - return { a:GetAbilityIndex(), a:GetAbilityName(), a:GetLevel() } - end - - return { - name = a:GetAbilityName(), - index = a:GetAbilityIndex(), - type = a:GetAbilityType(), - level = a:GetLevel(), - maxLevel = a:GetMaxLevel(), - damage = a:GetAbilityDamage(), - damageType = a:GetAbilityDamageType(), - isCastable = a:IsFullyCastable(), - isActivated = a:IsActivated(), - isHidden = a:IsHidden(), - isAttributeBonus = a:IsAttributeBonus(), - isItem = a:IsItem(), - isPassive = a:IsPassive(), - procsMagicStick = a:ProcsMagicStick(), - isTrained = a:IsTrained(), - canBeUpgraded = a:CanAbilityBeUpgraded(), - heroLevelToUpgrade = a:GetHeroLevelRequiredToUpgrade(), - duration = a:GetDuration(), - castRange = a:GetCastRange(), - castPoint = a:GetCastPoint(), - backswingTime = a:GetBackswingTime(), - channelTime = a:GetChannelTime(), - } -end - ---- Dumps current hero abilities. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam[opt] string simple Simple version or verbose -function GameMode:CommandDumpAbilities(player, simple) - local hero = player:GetAssignedHero() - - for i = 0, hero:GetAbilityCount() - 1 do - local a = hero:GetAbilityByIndex(i) - local repr = pp.write(debugAbility(a, simple)) - print(i, repr) - end -end - ---- Invokes ability by name. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string ability Ability name -function GameMode:CommandInvokeAbility(player, ability) - if not ability then - return - end - - local hero = player:GetAssignedHero() - local invoker = Invoker(hero) - - invoker:Invoke(ability) -end - ---- Dumps combo graph in DOT format. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string id Combo id -function GameMode:CommandDumpComboGraph(_player, id) - if not id then - return - end - - local combo = self.combos:createCombo(tonumber(id)) - - if combo == nil then - print("Could not find combo") - return - end - - print(combo:todot()) -end - ---- Changes music status. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string status Music status --- @tparam string intensity Music intensity -function GameMode:CommandChangeMusicStatus(player, status, intensity) - if not status or not intensity then - return - end - - status = tonumber(status) - intensity = tonumber(intensity) - - player:SetMusicStatus(status, intensity) -end - ---- Dumps Invoker ability specials values. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam[opt] string onlyScaling Dump only values that scale, ignoring fixed values -function GameMode:CommandDumpSpecials(player, onlyScaling) - local cmd = require("invokation.game_mode.commands.dump_specials") - cmd.dump(player, { onlyScaling = onlyScaling ~= nil }) -end - ---- Debug operations on ability specials KeyValues. --- --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string op Operation name (dump, findKeys, findValues) --- @tparam string query Operation query (dump: path, findKeys: pattern, findValues: pattern) -function GameMode:CommandDebugSpecials(_player, op, query) - local cmd = require("invokation.game_mode.commands.debug_specials") - - if op == "dump" then - cmd.dump(query) - elseif op == "findKeys" then - cmd.findKeys(query) - elseif op == "findValues" then - cmd.findValues(query) - end -end - ---- Reinserts an ability into the current hero. --- @tparam CDOTAPlayer player Player who issued this console command --- @tparam string name Ability name -function GameMode:CommandReinsertAbility(player, name) - if not name then - return - end - - local hero = player:GetAssignedHero() - local ability = hero:FindAbilityByName(name) - local index = ability:GetAbilityIndex() - local level = ability:GetLevel() - - hero:RemoveAbility(name) - - ability = hero:AddAbility(name) - ability:SetAbilityIndex(index) - ability:SetLevel(level) -end diff --git a/game/scripts/vscripts/invokation/game_mode/commands/dump_specials.lua b/game/scripts/vscripts/invokation/game_mode/commands/dump_specials.lua deleted file mode 100644 index 8fe3b7c..0000000 --- a/game/scripts/vscripts/invokation/game_mode/commands/dump_specials.lua +++ /dev/null @@ -1,86 +0,0 @@ -local Invoker = require("invokation.dota2.Invoker") -local m = require("moses") - -local M = {} - -local FIELD_TYPES = { FIELD_INTEGER = "number", FIELD_FLOAT = "number" } - -local function isSpecialKey(key, value, luaType) - if key == "var_type" then - return nil - end - - if not key:match("^[a-z_]+$") then - return nil - end - - if type(value) == luaType then - return true - end - - if m.isTable(value) then - local isLuaType = m.chain(m.isEqual):partial(luaType):overArgs(type):value() - - if m.all(value, isLuaType) then - return true - end - end - - return nil -end - -local function isScalingSpecialKey(key, value) - return m.isTable(value) and key or nil -end - -local function extractSpecialKey(special) - if not m.isString(special.var_type) then - return nil - end - - local luaType = FIELD_TYPES[special.var_type] - local selectSpecialKey = m.chain(isSpecialKey):partialRight(luaType):rearg({ 2, 1 }):value() - - return m.chain(special):map(selectSpecialKey):keys():value()[1] -end - -local function extractScalingSpecialKey(special) - local selectScalingSpecialKey = m.rearg(isScalingSpecialKey, { 2, 1 }) - return m.chain(special):map(selectScalingSpecialKey):keys():value()[1] -end - -local function extractSpecials(kv) - return m.chain(kv.AbilitySpecial or {}):map(extractSpecialKey):compact():value() -end - -local function extractScalingSpecials(kv) - return m.chain(kv.AbilitySpecial or {}):map(extractScalingSpecialKey):compact():value() -end - -local SPECIALS = m.map(Invoker.ABILITIES_KEY_VALUES, extractSpecials) -local SCALING = m.map(Invoker.ABILITIES_KEY_VALUES, extractScalingSpecials) - -local function maxLen(strings) - return m.chain(strings):map(m.unary(string.len)):max():value() -end - -function M.dump(player, options) - options = options or {} - - local hero = player:GetAssignedHero() - local specials = options.onlyScaling and SCALING or SPECIALS - local maxAbilityLen = maxLen(m.keys(specials)) - local maxSpecialLen = m.chain(specials):map(maxLen):max():value() - local fmt = string.format("%%-%ds %%-%ds %%s", maxAbilityLen, maxSpecialLen) - - for aName, sNames in pairs(specials) do - local ability = hero:FindAbilityByName(aName) - - for _, sName in ipairs(sNames) do - local sValue = ability:GetSpecialValueFor(sName) - print(fmt:format(aName, sName, sValue)) - end - end -end - -return M diff --git a/game/scripts/vscripts/invokation/game_mode/convars.lua b/game/scripts/vscripts/invokation/game_mode/convars.lua deleted file mode 100644 index afcbddb..0000000 --- a/game/scripts/vscripts/invokation/game_mode/convars.lua +++ /dev/null @@ -1,7 +0,0 @@ ---- Console Variables --- @submodule invokation.GameMode - --- selene: allow(unused_variable) -function GameMode:registerConVars() - self:d(" register convars") -end diff --git a/game/scripts/vscripts/invokation/game_mode/env.lua b/game/scripts/vscripts/invokation/game_mode/env.lua deleted file mode 100644 index a471932..0000000 --- a/game/scripts/vscripts/invokation/game_mode/env.lua +++ /dev/null @@ -1,29 +0,0 @@ ---- Env class. --- @classmod invokation.game_mode.Env -local class = require("pl.class") - -local M = class() - ---- Environment modes --- @section modes - ---- Development --- @tfield string DEVELOPMENT -M.DEVELOPMENT = "development" - ---- Production --- @tfield string PRODUCTION -M.PRODUCTION = "production" - ---- Methods --- @section methods - ---- Constructor. --- @tparam[opt=PRODUCTION] string name Environment name. -function M:_init(name) - self.name = name or M.PRODUCTION - self.development = self.name == M.DEVELOPMENT - self.production = self.name == M.PRODUCTION -end - -return M diff --git a/game/scripts/vscripts/invokation/game_mode/events.lua b/game/scripts/vscripts/invokation/game_mode/events.lua deleted file mode 100644 index 11e0336..0000000 --- a/game/scripts/vscripts/invokation/game_mode/events.lua +++ /dev/null @@ -1,57 +0,0 @@ ---- Events Setup --- @submodule invokation.GameMode -require("invokation.game_mode.events.internal") -require("invokation.game_mode.events.game_events") -require("invokation.game_mode.events.custom_events") - -local CUSTOM_EVENTS = require("invokation.const.custom_events") -local CustomEvents = require("invokation.dota2.custom_events") - ---- Events Setup --- @section events - -function GameMode:listenToGameEvent(event, methodName) - return ListenToGameEvent(event, self:fnHandler(methodName), self) -end - ---- @param event string ---- @param methodName string ---- @return CustomGameEventListenerID -function GameMode:subscribeToCustomEvent(event, methodName) - return CustomEvents.Subscribe(event, self:methodHandler(methodName)) -end - -function GameMode:registerGameEvents() - self:listenToGameEvent("dota_ability_channel_finished", "OnAbilityChannelFinished") - self:listenToGameEvent("dota_item_purchased", "OnItemPurchased") - self:listenToGameEvent("dota_non_player_used_ability", "OnNonPlayerUsedAbility") - self:listenToGameEvent("dota_player_begin_cast", "OnAbilityCastBegins") - self:listenToGameEvent("dota_player_used_ability", "OnAbilityUsed") - self:listenToGameEvent("entity_hurt", "OnEntityHurt") - self:listenToGameEvent("entity_killed", "_OnEntityKilled") - self:listenToGameEvent("game_rules_state_change", "_OnGameRulesStateChange") - self:listenToGameEvent("npc_spawned", "_OnNPCSpawned") - self:listenToGameEvent("player_connect_full", "_OnConnectFull") - - self:d(" register game events listeners") -end - -function GameMode:registerCustomEvents() - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_PLAYER_QUIT_REQUEST, "OnPlayerQuitRequest") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_COMBO_START, "OnComboStart") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_COMBO_STOP, "OnComboStop") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_COMBO_RESTART, "OnComboRestart") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_FREESTYLE_HERO_LEVEL_UP, "OnFreestyleHeroLevelUp") - - self:subscribeToCustomEvent( - CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_START, - "OnCombatLogCaptureStart" - ) - - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_STOP, "OnCombatLogCaptureStop") - self:subscribeToCustomEvent(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_REQUEST, "OnItemPickerQuery") - - self:d(" register custom events listeners") -end diff --git a/game/scripts/vscripts/invokation/game_mode/events/custom_events.lua b/game/scripts/vscripts/invokation/game_mode/events/custom_events.lua deleted file mode 100644 index 11fd90a..0000000 --- a/game/scripts/vscripts/invokation/game_mode/events/custom_events.lua +++ /dev/null @@ -1,94 +0,0 @@ ---- Custom Events Listeners --- @submodule invokation.GameMode -local CustomEvents = require("invokation.dota2.custom_events") - ---- Custom Events Listeners --- @section custom_events - ---- Handles player quit request events. --- @tparam CDOTAPlayerController player --- @tparam const.custom_events.PlayerQuitRequest payload -function GameMode:OnPlayerQuitRequest(player, payload) - self:d("OnPlayerQuitRequest", { player = player:GetPlayerID(), payload = payload }) - - SendToServerConsole("disconnect") -end - ---- Handles combos reload events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.CombosReloadPayload payload -function GameMode:OnCombosReload(player, payload) - self:d("OnCombosReload", { player = player:GetPlayerID(), payload = payload }) - self.combos:load() -end - ---- Handles combo start events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.ComboStartPayload payload -function GameMode:OnComboStart(player, payload) - self:d("OnComboStart", { player = player:GetPlayerID(), payload = payload }) - - local combo = self.combos:Create(payload.id) - - self.combos:Start(player, combo) -end - ---- Handles combo stop events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.ComboStopPayload payload -function GameMode:OnComboStop(player, payload) - self:d("OnComboStop", { player = player:GetPlayerID(), payload = payload }) - - self.combos:Stop(player) -end - ---- Handles combo restart events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.ComboRestartPayload payload -function GameMode:OnComboRestart(player, payload) - self:d("OnComboRestart", { player = player:GetPlayerID(), payload = payload }) - - local options = { hardReset = payload.hardReset == 1 } - - self.combos:Restart(player, options) -end - ---- Handles freestyle hero level up events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.FreestyleHeroLevelUpPayload payload -function GameMode:OnFreestyleHeroLevelUp(player, payload) - self:d("OnFreestyleHeroLevelUp", { player = player:GetPlayerID(), payload = payload }) - - local options = { level = payload.level, maxLevel = payload.maxLevel == 1 } - - self.combos:FreestyleHeroLevelUp(player, options) -end - ---- Handles combat log capture start events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.CombatLogCaptureStartPayload payload -function GameMode:OnCombatLogCaptureStart(player, payload) - self:d("OnCombatLogCaptureStart", { player = player:GetPlayerID(), payload = payload }) - - self.combos:StartCapturingAbilities(player) -end - ---- Handles combat log capture stop events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.CombatLogCaptureStopPayload payload -function GameMode:OnCombatLogCaptureStop(player, payload) - self:d("OnCombatLogCaptureStop", { player = player:GetPlayerID(), payload = payload }) - - self.combos:StopCapturingAbilities(player) -end - ---- Handles item picker query events. --- @tparam CDOTAPlayer player --- @tparam const.custom_events.ItemPickerQueryPayload payload -function GameMode:OnItemPickerQuery(player, payload) - self:d("OnItemPickerQuery", { player = player:GetPlayerID(), payload = payload }) - - local response = { items = self.itemsKV:Search(payload.query) } - - CustomEvents.SendPlayer(CustomEvents.EVENT_ITEM_PICKER_QUERY_RESPONSE, player, response) -end diff --git a/game/scripts/vscripts/invokation/game_mode/events/game_events.lua b/game/scripts/vscripts/invokation/game_mode/events/game_events.lua deleted file mode 100644 index fb725af..0000000 --- a/game/scripts/vscripts/invokation/game_mode/events/game_events.lua +++ /dev/null @@ -1,174 +0,0 @@ ---- Game Events Listeners --- @submodule invokation.GameMode -local Ability = require("invokation.dota2.Ability") -local CustomEvents = require("invokation.dota2.custom_events") -local DamageInstance = require("invokation.dota2.DamageInstance") -local Unit = require("invokation.dota2.Unit") - -local ERRF_ABILITY_OR_ITEM_NOT_FOUND = "Could not find ability or item named '%q' on unit '%s'" - ---- Game Events Listeners --- @section game_events - ---- The overall game state has changeds. --- @tparam string state --- @tparam table payload -function GameMode:OnGameRulesStateChange(state, payload) - self:d("OnGameRulesStateChange", { state = state, payload = payload }) -end - ---- Called once when the player fully connects and becomes "Ready" during --- loading. --- @tparam CDOTAPlayer player -function GameMode:OnConnectFull(player, user_id) - self:d("OnConnectFull", { player = player:GetPlayerID() }) - - self.users[user_id] = player - self.players[player:GetPlayerID()] = player -end - ---- Called once and only once as soon as the first player (almost certain to be --- the server in local lobbies) loads in. --- --- It can be used to initialize state that isn't initializeable in @{Activate} --- but needs to be done before everyone loads in. -function GameMode:OnFirstPlayerLoaded() - self:d("OnFirstPlayerLoaded") -end - ---- Called once and only once after all players have loaded into the game, --- right as the hero selection time begins. --- --- It can be used to initialize non-hero player state or adjust the hero --- selection (i.e. force random etc) -function GameMode:OnAllPlayersLoaded() - self:d("OnAllPlayersLoaded") -end - ---- Called once and only once for every player when they spawn into the game --- for the first time. --- --- It is also called if the player's hero is replaced with a new hero for any --- reason. This function is useful for initializing heroes, such as adding --- levels, changing the starting gold, removing/adding abilities, adding --- physics, etc. --- --- @tparam CDOTA_BaseNPC_Hero hero -function GameMode:OnHeroInGame(hero) - self:d("OnHeroInGame", { hero = hero:GetUnitName() }) - - local player_id = hero:GetPlayerID() - local player = PlayerResource:GetPlayer(player_id) - local payload = { - id = hero:GetHeroID(), - name = hero:GetUnitName(), - variant = hero:GetHeroFacetID(), - } - - CustomEvents.SendPlayer(CustomEvents.EVENT_PLAYER_HERO_IN_GAME, player, payload) -end - ---- Called once and only once when the game completely begins (about 0:00 on the clock). -function GameMode:OnGameInProgress() - self:d("OnGameInProgress") -end - ---- An entity has been hurt. --- @tparam table payload --- @tparam number payload.damage Damage amount --- @tparam int payload.entindex_killed Victim (unit) entity index --- @tparam[opt] int payload.entindex_attacker Attacker (unit) entity index --- @tparam[opt] int payload.entindex_inflictor Inflictor (item, ability, etc) entity index -function GameMode:OnEntityHurt(payload) - self:d("OnEntityHurt", { payload = payload }) - - local victim = Unit(EntIndexToHScript(payload.entindex_killed)) - - local attacker - if payload.entindex_attacker ~= nil then - attacker = Unit(EntIndexToHScript(payload.entindex_attacker)) - end - - local inflictor - -- FIXME: This is a hack to fix an issue when an entity is killed with `ForceKill`, - -- FIXME: which will trigger this event. I'm not sure which enum `damagebits` is using, - -- FIXME: but regular damage seems to always set it to 0 while `ForceKill` sets it to 4096 - if payload.entindex_inflictor ~= nil and payload.damagebits == 0 then - inflictor = Ability(EntIndexToHScript(payload.entindex_inflictor)) - end - - local damage = DamageInstance(victim, payload.damage, attacker, inflictor) - - self.combos:OnEntityHurt(damage) -end - ---- An item was purchased by a player. --- @tparam table payload --- @tparam int payload.PlayerID Player id --- @tparam string payload.itemname Item name --- @tparam number payload.itemcost Item cost -function GameMode:OnItemPurchased(payload) - self:d("OnItemPurchased", { payload = payload }) - - local player = PlayerResource:GetPlayer(payload.PlayerID) - - self.combos:OnItemPurchased(player, { item = payload.itemname, cost = payload.itemcost }) -end - ---- Called whenever an ability begins its PhaseStart phase (but before it is actually cast). --- @tparam table payload --- @tparam int payload.PlayerID Player id --- @tparam string payload.abilityname Ability name -function GameMode:OnAbilityCastBegins(payload) - self:d("OnAbilityCastBegins", { payload = payload }) -end - ---- An ability was used by a player (including items). --- @tparam table payload --- @tparam int payload.PlayerID Player id --- @tparam int payload.caster_entindex Caster (unit) entity index --- @tparam string payload.abilityname Ability name -function GameMode:OnAbilityUsed(payload) - self:d("OnAbilityUsed", { payload = payload }) - - local player = PlayerResource:GetPlayer(payload.PlayerID) - local caster = Unit(EntIndexToHScript(payload.caster_entindex)) - local abilityEnt = caster:FindAbilityOrItem(payload.abilityname) - - if abilityEnt == nil then - local err = ERRF_ABILITY_OR_ITEM_NOT_FOUND:format(payload.abilityname, caster.name) - error(err) - end - - local ability = Ability(abilityEnt) - - self.combos:OnAbilityUsed(player, caster, ability) -end - ---- A non-player entity (necro-book, chen creep, etc) used an ability. --- @tparam table payload --- @tparam int payload.caster_entindex Caster (unit) entity index --- @tparam string payload.abilityname Ability name -function GameMode:OnNonPlayerUsedAbility(payload) - self:d("OnNonPlayerUsedAbility", { payload = payload }) -end - ---- A channelled ability finished by either completing or being interrupted. --- @tparam table payload --- @tparam string payload.abilityname Ability name --- @tparam int payload.interrupted `1` if ability was interrupted -function GameMode:OnAbilityChannelFinished(payload) - self:d("OnAbilityChannelFinished", { payload = payload }) -end - ---- An entity died. --- @tparam CDOTA_BaseNPC killed Killed unit --- @tparam[opt] CDOTA_BaseNPC attacker Attacker unit --- @tparam[opt] CDOTABaseAbility inflictor Inflictor ability -function GameMode:OnEntityKilled(killed, attacker, inflictor) - self:d("OnEntityKilled", { - killed = killed:GetName(), - attacker = attacker and attacker:GetName(), - inflictor = inflictor and inflictor:GetName(), - }) -end diff --git a/game/scripts/vscripts/invokation/game_mode/events/internal.lua b/game/scripts/vscripts/invokation/game_mode/events/internal.lua deleted file mode 100644 index 0bb5083..0000000 --- a/game/scripts/vscripts/invokation/game_mode/events/internal.lua +++ /dev/null @@ -1,115 +0,0 @@ ---- Internal Game Events Listeners --- @submodule invokation.GameMode -local S = require("invokation.const.settings") - -local WARNF_MISSING_TEAM_COLOR = - "Attempted to set custom player color for player %d and team %d, but the team color is not configured." - ---- Internal Game Events Listeners --- @section internal_game_events - ---- Called when the overall game state has changed. --- @tparam table payload -function GameMode:_OnGameRulesStateChange(payload) - if GameMode._reentrantCheck then - return - end - - local state = GameRules:State_Get() - - GameMode._reentrantCheck = true - self:OnGameRulesStateChange(state, payload) - GameMode._reentrantCheck = false - - if state == DOTA_GAMERULES_STATE_HERO_SELECTION then - self:PostLoadPrecache() - self:OnAllPlayersLoaded() - - if S.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS then - for i = 0, DOTA_DEFAULT_MAX_TEAM_PLAYERS do - if PlayerResource:IsValidPlayer(i) then - local team = PlayerResource:GetTeam(i) - local color = S.TEAM_COLORS[team] - - if color ~= nil then - PlayerResource:SetCustomPlayerColor(i, color[1], color[2], color[3]) - else - self:warnf(WARNF_MISSING_TEAM_COLOR, i, team) - end - end - end - end - elseif state == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then - self:OnGameInProgress() - end -end - ---- Called once when the player fully connects and becomes "Ready" during loading. --- @tparam table payload --- @tparam int payload.PlayerID Player id --- @tparam int payload.userid User id -function GameMode:_OnConnectFull(payload) - self:d("_OnConnectFull", { payload = payload }) - - if GameMode._reentrantCheck then - return - end - - local player = PlayerResource:GetPlayer(payload.PlayerID) - - GameMode._reentrantCheck = true - self:OnConnectFull(player, payload.userid) - GameMode._reentrantCheck = false - - if not self.firstPlayerLoaded then - self.firstPlayerLoaded = true - self:OnFirstPlayerLoaded() - end -end - ---- Called when an NPC has spawned somewhere in game, including heroes. --- @tparam table payload --- @tparam int payload.entindex Unit entity index -function GameMode:_OnNPCSpawned(payload) - self:d("_OnNPCSpawned", { payload = payload }) - - if GameMode._reentrantCheck then - return - end - - local npc = EntIndexToHScript(payload.entindex) --[[@as CDOTA_BaseNPC]] - - if npc and npc:IsRealHero() and not self.firstSpawned then - self.firstSpawned = true - self:OnHeroInGame(npc) - end -end - ---- Called when an entity was killed. --- @tparam table payload --- @tparam int payload.entindex_killed Victim (unit) entity index --- @tparam[opt] int payload.entindex_attacker Attacker (unit) entity index --- @tparam[opt] int payload.entindex_inflictor Inflictor (item, ability, etc) entity index -function GameMode:_OnEntityKilled(payload) - self:d("_OnEntityKilled", { payload = payload }) - - if GameMode._reentrantCheck then - return - end - - local killed = EntIndexToHScript(payload.entindex_killed) - local attacker = nil - local inflictor = nil - - if payload.entindex_attacker ~= nil then - attacker = EntIndexToHScript(payload.entindex_attacker) - end - - if payload.entindex_inflictor ~= nil then - inflictor = EntIndexToHScript(payload.entindex_inflictor) - end - - GameMode._reentrantCheck = true - self:OnEntityKilled(killed, attacker, inflictor) - GameMode._reentrantCheck = false -end diff --git a/game/scripts/vscripts/invokation/game_mode/game_mode.lua b/game/scripts/vscripts/invokation/game_mode/game_mode.lua deleted file mode 100644 index 572513e..0000000 --- a/game/scripts/vscripts/invokation/game_mode/game_mode.lua +++ /dev/null @@ -1,83 +0,0 @@ ---- GameMode Setup --- @submodule invokation.GameMode - -local S = require("invokation.const.settings") - ---- GameMode Setup --- @section game_mode - --- selene: allow(unused_variable) -function GameMode:setupGameMode() - self.gameMode = GameRules:GetGameModeEntity() - - self.gameMode:SetAlwaysShowPlayerInventory(S.ALWAYS_SHOW_PLAYER_INVENTORY) - self.gameMode:SetAlwaysShowPlayerNames(S.ALWAYS_SHOW_PLAYER_NAMES) - self.gameMode:SetAnnouncerDisabled(S.DISABLE_ANNOUNCER) - self.gameMode:SetBotThinkingEnabled(S.USE_STANDARD_DOTA_BOT_THINKING) - self.gameMode:SetBotsAlwaysPushWithHuman(S.BOTS_ALWAYS_PUSH_WITH_HUMAN) - self.gameMode:SetBotsInLateGame(S.BOTS_LATE_GAME_BEHAVIOR) - self.gameMode:SetBotsMaxPushTier(S.BOTS_MAX_PUSH_TIER) - self.gameMode:SetBountyRuneSpawnInterval(S.BOUNTY_RUNE_SPAWN_INTERVAL) - self.gameMode:SetBuybackEnabled(S.BUYBACK_ENABLED) - self.gameMode:SetCameraDistanceOverride(S.CAMERA_DISTANCE_OVERRIDE) - self.gameMode:SetCameraSmoothCountOverride(S.CAMERA_SMOOTH_COUNT) - self.gameMode:SetCustomBackpackCooldownPercent(S.CUSTOM_BACKPACK_COOLDOWN_PERCENT) - self.gameMode:SetCustomBackpackSwapCooldown(S.CUSTOM_BACKPACK_SWAP_COOLDOWN) - self.gameMode:SetCustomBuybackCooldownEnabled(S.CUSTOM_BUYBACK_COOLDOWN_ENABLED) - self.gameMode:SetCustomBuybackCostEnabled(S.CUSTOM_BUYBACK_COST_ENABLED) - self.gameMode:SetCustomGlyphCooldown(S.CUSTOM_GLYPH_COOLDOWN) - self.gameMode:SetCustomScanCooldown(S.CUSTOM_SCAN_COOLDOWN) - self.gameMode:SetDaynightCycleDisabled(S.DISABLE_DAY_NIGHT_CYCLE) - self.gameMode:SetDeathOverlayDisabled(S.DISABLE_DEATH_OVERLAY) - self.gameMode:SetDraftingBanningTimeOverride(S.DRAFTING_BANNING_TIME) - self.gameMode:SetDraftingHeroPickSelectTimeOverride(S.DRAFTING_HERO_PICK_SELECTION_TIME) - self.gameMode:SetFixedRespawnTime(S.FIXED_RESPAWN_TIME) - self.gameMode:SetFogOfWarDisabled(S.DISABLE_FOG_OF_WAR) - self.gameMode:SetFountainConstantManaRegen(S.FOUNTAIN_CONSTANT_MANA_REGEN) - self.gameMode:SetFountainPercentageHealthRegen(S.FOUNTAIN_PERCENTAGE_HEALTH_REGEN) - self.gameMode:SetFountainPercentageManaRegen(S.FOUNTAIN_PERCENTAGE_MANA_REGEN) - self.gameMode:SetFriendlyBuildingMoveToEnabled(S.ENABLE_FRIENDLY_BUILDING_MOVE_TO_CLICK) - self.gameMode:SetGoldSoundDisabled(S.DISABLE_GOLD_SOUNDS) - self.gameMode:SetHudCombatEventsDisabled(S.DISABLE_COMBAT_EVENTS_HUD) - self.gameMode:SetKillingSpreeAnnouncerDisabled(S.DISABLE_KILLING_SPREE_ANNOUNCER) - self.gameMode:SetLoseGoldOnDeath(S.LOSE_GOLD_ON_DEATH) - self.gameMode:SetMaximumAttackSpeed(S.MAXIMUM_ATTACK_SPEED) - self.gameMode:SetMinimumAttackSpeed(S.MINIMUM_ATTACK_SPEED) - self.gameMode:SetPauseEnabled(S.ENABLE_PAUSE) - self.gameMode:SetPowerRuneSpawnInterval(S.POWER_RUNE_SPAWN_INTERVAL) - self.gameMode:SetRecommendedItemsDisabled(S.RECOMMENDED_BUILDS_DISABLED) - self.gameMode:SetRemoveIllusionsOnDeath(S.REMOVE_ILLUSIONS_ON_DEATH) - self.gameMode:SetRespawnTimeScale(S.RESPAWN_TIME_SCALE) - self.gameMode:SetSelectionGoldPenaltyEnabled(S.ENABLE_SELECTION_GOLD_PENALTY) - self.gameMode:SetStashPurchasingDisabled(S.DISABLE_STASH_PURCHASING) - self.gameMode:SetStickyItemDisabled(S.DISABLE_STICKY_ITEM) - self.gameMode:SetTopBarTeamValuesOverride(S.USE_CUSTOM_TOP_BAR_VALUES) - self.gameMode:SetTopBarTeamValuesVisible(S.TOP_BAR_VISIBLE) - self.gameMode:SetTowerBackdoorProtectionEnabled(S.ENABLE_TOWER_BACKDOOR_PROTECTION) - self.gameMode:SetUnseenFogOfWarEnabled(S.USE_UNSEEN_FOG_OF_WAR) - self.gameMode:SetUseDefaultDOTARuneSpawnLogic(S.USE_DEFAULT_DOTA_RUNE_SPAWN_LOGIC) - self.gameMode:SetWeatherEffectsDisabled(S.DISABLE_WEATHER_EFFECTS) - - -- Must be set before `SetUseCustomHeroLevels` - self.gameMode:SetCustomXPRequiredToReachNextLevel(S.XP_PER_LEVEL_TABLE) - self.gameMode:SetUseCustomHeroLevels(S.USE_CUSTOM_HERO_LEVELS) - - -- self.gameMode:SetCustomAttributeDerivedStatValue(nStatType, flNewValue) - -- self.gameMode:SetHUDVisible(iHUDElement, bVisible) - -- self.gameMode:SetKillableTombstones(S.KILLABLE_TOMBSTONES) - -- self.gameMode:SetTopBarTeamValue(iTeam, nValue) - - if S.FORCE_PICKED_HERO ~= nil then - self.gameMode:SetCustomGameForceHero(S.FORCE_PICKED_HERO) - end - - if S.CUSTOM_TERRAIN_WEATHER_EFFECT ~= nil then - self.gameMode:SetCustomTerrainWeatherEffect(S.CUSTOM_TERRAIN_WEATHER_EFFECT) - end - - for rune, spawn in pairs(S.ENABLED_RUNES) do - self.gameMode:SetRuneEnabled(rune, spawn) - end - - self:d(" setup GameMode") -end diff --git a/game/scripts/vscripts/invokation/game_mode/game_rules.lua b/game/scripts/vscripts/invokation/game_mode/game_rules.lua deleted file mode 100644 index 885d546..0000000 --- a/game/scripts/vscripts/invokation/game_mode/game_rules.lua +++ /dev/null @@ -1,76 +0,0 @@ ---- GameRules Setup --- @submodule invokation.GameMode - -local S = require("invokation.const.settings") - ---- GameRules Setup --- @section game_rules - --- selene: allow(unused_variable) -function GameMode:setupGameRules() - GameRules:SetCreepMinimapIconScale(S.MINIMAP_CREEP_ICON_SCALE) - GameRules:SetCreepSpawningEnabled(S.ENABLE_CREEP_SPAWN) - GameRules:SetCustomGameAllowBattleMusic(S.ENABLE_BATTLE_MUSIC) - GameRules:SetCustomGameAllowHeroPickMusic(S.ENABLE_HERO_PICK_MUSIC) - GameRules:SetCustomGameAllowMusicAtGameStart(S.ENABLE_GAME_START_MUSIC) - GameRules:SetCustomGameEndDelay(S.GAME_END_DELAY) - GameRules:SetCustomGameSetupRemainingTime(S.GAME_SETUP_TIME) - GameRules:SetCustomGameSetupTimeout(S.GAME_SETUP_TIMEOUT) - GameRules:SetCustomVictoryMessage(S.VICTORY_MESSAGE) - GameRules:SetCustomVictoryMessageDuration(S.VICTORY_MESSAGE_DURATION) - GameRules:SetFirstBloodActive(S.ENABLE_FIRST_BLOOD) - GameRules:SetGoldPerTick(S.GOLD_PER_TICK) - GameRules:SetGoldTickTime(S.GOLD_TICK_TIME) - GameRules:SetHeroMinimapIconScale(S.MINIMAP_HERO_ICON_SCALE) - GameRules:SetHeroRespawnEnabled(S.ENABLE_HERO_RESPAWN) - GameRules:SetHeroSelectionTime(S.HERO_SELECTION_TIME) - GameRules:SetHeroSelectPenaltyTime(S.HERO_SELECTION_PENALTY_TIME) - GameRules:SetHideKillMessageHeaders(S.HIDE_KILL_BANNERS) - GameRules:SetPostGameTime(S.POST_GAME_TIME) - GameRules:SetPreGameTime(S.PRE_GAME_TIME) - GameRules:SetRuneMinimapIconScale(S.MINIMAP_RUNE_ICON_SCALE) - GameRules:SetRuneSpawnTime(S.RUNE_SPAWN_TIME) - GameRules:SetSameHeroSelectionEnabled(S.ALLOW_SAME_HERO_SELECTION) - GameRules:SetShowcaseTime(S.SHOWCASE_TIME) - GameRules:SetStartingGold(S.STARTING_GOLD) - GameRules:SetStrategyTime(S.STRATEGY_TIME) - GameRules:SetTreeRegrowTime(S.TREE_REGROW_TIME) - GameRules:SetUseBaseGoldBountyOnHeroes(S.USE_BASE_HERO_GOLD_BOUNTY) - GameRules:SetUseCustomHeroXPValues(S.USE_CUSTOM_XP_VALUES) - GameRules:SetUseUniversalShopMode(S.UNIVERSAL_SHOP_MODE) - - if self.env.development then - GameRules:EnableCustomGameSetupAutoLaunch(true) - GameRules:LockCustomGameSetupTeamAssignment(true) - GameRules:SetCustomGameSetupAutoLaunchDelay(0) - else - GameRules:EnableCustomGameSetupAutoLaunch(S.ENABLE_AUTO_LAUNCH) - GameRules:LockCustomGameSetupTeamAssignment(S.LOCK_TEAM_SETUP) - GameRules:SetCustomGameSetupAutoLaunchDelay(S.AUTO_LAUNCH_DELAY) - end - - for team, number in pairs(S.CUSTOM_TEAM_PLAYER_COUNT) do - GameRules:SetCustomGameTeamMaxPlayers(team, number) - end - - if S.USE_CUSTOM_TEAM_COLORS then - for team, color in pairs(S.TEAM_COLORS) do - SetTeamCustomHealthbarColor(team, color[1], color[2], color[3]) - end - end - - -- Sets a callback to handle saving custom game account records (callback is - -- passed a player id and should return a flat simple table) [Preview/Unreleased] - -- GameRules:SetCustomGameAccountRecordSaveFunction(handle, handle) - - -- Set the difficulty level of the custom game mode - -- GameRules:SetCustomGameDifficulty(int) - - -- Event-only (table hMetadataTable) - -- GameRules:SetEventMetadataCustomTable(handle) - - -- Event-only (table hMetadataTable) - -- GameRules:SetEventSignoutCustomTable(handle) - - self:d(" setup GameRules") -end diff --git a/game/scripts/vscripts/invokation/game_mode/net_tables.lua b/game/scripts/vscripts/invokation/game_mode/net_tables.lua deleted file mode 100644 index 896f0d9..0000000 --- a/game/scripts/vscripts/invokation/game_mode/net_tables.lua +++ /dev/null @@ -1,43 +0,0 @@ ---- NetTables --- @submodule invokation.GameMode - -local m = require("moses") - -local INVOKER = require("invokation.const.invoker") -local NET_TABLE = require("invokation.const.net_table") - ---- NetTables --- @section net_tables - -function GameMode:setupNetTables() - self:setupNetTableMain() - self:setupNetTableHeroKV() - self:setupNetTableAbilitiesKV() -end - -function GameMode:setupNetTableMain() - self:setupNetTableHeroData() -end - -function GameMode:setupNetTableHeroData() - self.netTables.MAIN:Set(NET_TABLE.MAIN.KEYS.HERO_DATA, INVOKER:Serialize()) - - self:d(" setup net tables: hero data") -end - -function GameMode:setupNetTableHeroKV() - self.netTables.HERO:Set(NET_TABLE.HERO.KEYS.KEY_VALUES, INVOKER.HERO_KEY_VALUES:Serialize()) - - self:d(" setup net tables: hero keyvalues") -end - -function GameMode:setupNetTableAbilitiesKV() - self.netTables.ABILITIES:Set( - NET_TABLE.ABILITIES.KEYS.KEY_VALUES, - m.map(INVOKER.ABILITIES_KEY_VALUES, function(kv) - return kv:Serialize() - end) - ) - - self:d(" setup net tables: abilities keyvalues") -end diff --git a/game/scripts/vscripts/invokation/lang/debug.lua b/game/scripts/vscripts/invokation/lang/debug.lua deleted file mode 100644 index 164834f..0000000 --- a/game/scripts/vscripts/invokation/lang/debug.lua +++ /dev/null @@ -1,28 +0,0 @@ ---- Debugging helpers. --- @module invokation.lang.debug - -local M = {} - ---- Toggles function call debugging. --- selene: allow(global_usage) -function M.debugcalls() - if not _G.__debugCalls then - print("Starting DebugCalls") - _G.__debugCalls = true - - debug.sethook(function() - local info = debug.getinfo(2) - local src = tostring(info.short_src) - local name = tostring(info.name) - if name ~= "__index" then - print("Call: " .. src .. " -- " .. name .. " -- " .. info.currentline) - end - end, "c") - else - print("Stopped DebugCalls") - _G.__debugCalls = false - debug.sethook(nil, "c") - end -end - -return M diff --git a/game/scripts/vscripts/invokation/lang/delegation.lua b/game/scripts/vscripts/invokation/lang/delegation.lua deleted file mode 100644 index 9681ccb..0000000 --- a/game/scripts/vscripts/invokation/lang/delegation.lua +++ /dev/null @@ -1,59 +0,0 @@ ---- Method delegation helpers. --- @module invokation.lang.delegation -local M = {} - ---- Creates delegator instance methods in a class. --- --- Creates methods in the given class object that simply delegate --- to the respective methods in the named attribute object. --- --- @usage --- delegate(Class, "attribute", "method") --- -- is equivalent to --- function Class:method(...) --- self.attribute:method(...) --- end --- --- @usage --- local class = require("pl.class") --- local Engine = class() --- --- function Engine:start() --- print("engine started") --- end --- --- function Engine:shutdown() --- print("engine stopped") --- end --- --- local Car = class() --- --- delegate(Car, "engine", {"start", "shutdown"}) --- --- function Car:_init(engine) --- self.engine = engine --- end --- --- local engine = Engine() --- local car = Car(engine) --- --- car:start() --> engine started --- car:shutdown() --> engine stopped --- --- @tparam table classObject Class object --- @tparam string delegateTo Attribute name that methods are delegated to --- @tparam string|{string,...} methods Method name or array of names to delegate -function M.delegate(classObject, delegateTo, methods) - if type(methods) == "string" then - methods = { methods } - end - - for _, method in ipairs(methods) do - classObject[method] = function(self, ...) - local attr = self[delegateTo] - return attr[method](attr, ...) - end - end -end - -return M diff --git a/game/scripts/vscripts/invokation/lang/function.lua b/game/scripts/vscripts/invokation/lang/function.lua deleted file mode 100644 index 0108afc..0000000 --- a/game/scripts/vscripts/invokation/lang/function.lua +++ /dev/null @@ -1,34 +0,0 @@ ---- Function helpers. --- @module invokation.lang.function -local M = {} - ---- Creates a wrapper function that performs method lookup by name on a table. --- --- The created function will perform method lookup by name on the given table, --- then call the method passing all parameters it received. --- --- @tparam table t Table object --- @tparam string name Method name --- @treturn function Wrapper function --- @usage --- local t = {} --- function t.greet(name) return "Greetings, " .. name end --- print(t.greet) --- -- => function: 0x7fffc9367cc0 --- local fn = lookupbyname(t, "greet") --- -- Equivalent to calling `t["greet"]("Alice")` --- print(fn("Alice")) --- -- => "Greetings, Alice" --- -- t.greet() can be overridden and is still looked up by name: --- function t.greet(name) return "Welcome, " .. name end --- print(t.greet) --- -- => function: 0x7fffc9367ef0 --- print(fn("Alice")) --- -- => "Welcome, Alice" -function M.lookupbyname(t, name) - return function(...) - return t[name](...) - end -end - -return M diff --git a/game/scripts/vscripts/invokation/lang/random.lua b/game/scripts/vscripts/invokation/lang/random.lua deleted file mode 100644 index c44c81e..0000000 --- a/game/scripts/vscripts/invokation/lang/random.lua +++ /dev/null @@ -1,14 +0,0 @@ ---- Random helpers. --- @module invokation.lang.random -local M = {} - ---- Seeds random generation. --- @tparam[opt=Time()] int seed Seed value --- @treturn int Seed number -function M.seed(seed) - seed = seed or Time() - math.randomseed(seed) - return seed -end - -return M diff --git a/game/scripts/vscripts/middleclass.lua b/game/scripts/vscripts/middleclass.lua new file mode 100644 index 0000000..a88f0fb --- /dev/null +++ b/game/scripts/vscripts/middleclass.lua @@ -0,0 +1,193 @@ +local middleclass = { + _VERSION = 'middleclass v4.1.1', + _DESCRIPTION = 'Object Orientation for Lua', + _URL = 'https://github.com/kikito/middleclass', + _LICENSE = [[ + MIT LICENSE + + Copyright (c) 2011 Enrique García Cota + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ]] +} + +local function _createIndexWrapper(aClass, f) + if f == nil then + return aClass.__instanceDict + elseif type(f) == "function" then + return function(self, name) + local value = aClass.__instanceDict[name] + + if value ~= nil then + return value + else + return (f(self, name)) + end + end + else -- if type(f) == "table" then + return function(self, name) + local value = aClass.__instanceDict[name] + + if value ~= nil then + return value + else + return f[name] + end + end + end +end + +local function _propagateInstanceMethod(aClass, name, f) + f = name == "__index" and _createIndexWrapper(aClass, f) or f + aClass.__instanceDict[name] = f + + for subclass in pairs(aClass.subclasses) do + if rawget(subclass.__declaredMethods, name) == nil then + _propagateInstanceMethod(subclass, name, f) + end + end +end + +local function _declareInstanceMethod(aClass, name, f) + aClass.__declaredMethods[name] = f + + if f == nil and aClass.super then + f = aClass.super.__instanceDict[name] + end + + _propagateInstanceMethod(aClass, name, f) +end + +local function _tostring(self) return "class " .. self.name end +local function _call(self, ...) return self:new(...) end + +local function _createClass(name, super) + local dict = {} + dict.__index = dict + + local aClass = { name = name, super = super, static = {}, + __instanceDict = dict, __declaredMethods = {}, + subclasses = setmetatable({}, {__mode='k'}) } + + if super then + setmetatable(aClass.static, { + __index = function(_,k) + local result = rawget(dict,k) + if result == nil then + return super.static[k] + end + return result + end + }) + else + setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) end }) + end + + setmetatable(aClass, { __index = aClass.static, __tostring = _tostring, + __call = _call, __newindex = _declareInstanceMethod }) + + return aClass +end + +local function _includeMixin(aClass, mixin) + assert(type(mixin) == 'table', "mixin must be a table") + + for name,method in pairs(mixin) do + if name ~= "included" and name ~= "static" then aClass[name] = method end + end + + for name,method in pairs(mixin.static or {}) do + aClass.static[name] = method + end + + if type(mixin.included)=="function" then mixin:included(aClass) end + return aClass +end + +local DefaultMixin = { + __tostring = function(self) return "instance of " .. tostring(self.class) end, + + initialize = function(self, ...) end, + + isInstanceOf = function(self, aClass) + return type(aClass) == 'table' + and type(self) == 'table' + and (self.class == aClass + or type(self.class) == 'table' + and type(self.class.isSubclassOf) == 'function' + and self.class:isSubclassOf(aClass)) + end, + + static = { + allocate = function(self) + assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'") + return setmetatable({ class = self }, self.__instanceDict) + end, + + new = function(self, ...) + assert(type(self) == 'table', "Make sure that you are using 'Class:new' instead of 'Class.new'") + local instance = self:allocate() + instance:initialize(...) + return instance + end, + + subclass = function(self, name) + assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'") + assert(type(name) == "string", "You must provide a name(string) for your class") + + local subclass = _createClass(name, self) + + for methodName, f in pairs(self.__instanceDict) do + if not (methodName == "__index" and type(f) == "table") then + _propagateInstanceMethod(subclass, methodName, f) + end + end + subclass.initialize = function(instance, ...) return self.initialize(instance, ...) end + + self.subclasses[subclass] = true + self:subclassed(subclass) + + return subclass + end, + + subclassed = function(self, other) end, + + isSubclassOf = function(self, other) + return type(other) == 'table' and + type(self.super) == 'table' and + ( self.super == other or self.super:isSubclassOf(other) ) + end, + + include = function(self, ...) + assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'") + for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end + return self + end + } +} + +function middleclass.class(name, super) + assert(type(name) == 'string', "A name (string) is needed for the new class") + return super and super:subclass(name) or _includeMixin(_createClass(name), DefaultMixin) +end + +setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end }) + +return middleclass diff --git a/game/scripts/vscripts/moses.lua b/game/scripts/vscripts/moses.lua deleted file mode 100644 index eef3534..0000000 --- a/game/scripts/vscripts/moses.lua +++ /dev/null @@ -1,3114 +0,0 @@ ---- Utility-belt library for functional programming in Lua ([source](http://github.com/Yonaba/Moses)) --- @author [Roland Yonaba](http://github.com/Yonaba) --- @copyright 2012-2018 --- @license [MIT](http://www.opensource.org/licenses/mit-license.php) --- @release 2.1.0 --- @module moses --- @set sort=true - -local _MODULEVERSION = '2.1.0' - --- Internalisation -local next, type, pcall = next, type, pcall -local setmetatable, getmetatable = setmetatable, getmetatable -local t_insert, t_sort = table.insert, table.sort -local t_remove,t_concat = table.remove, table.concat -local randomseed, random, huge = math.randomseed, math.random, math.huge -local floor, max, min, ceil = math.floor, math.max, math.min, math.ceil -local wrap = coroutine.wrap -local yield = coroutine.yield -local rawget = rawget -local unpack = table.unpack or unpack -local pairs,ipairs = pairs,ipairs -local error = error -local clock = os.clock -local M = {} - - --- ======== Private helpers - -local function f_max(a,b) return a>b end -local function f_min(a,b) return a0 then - while (#s < n and pad) do s[#s+1] = pad end - f(s) - end - end -end - -local function partgen2(t, n, f, pad) -- generates overlapping array partitions - for i = 0, #t, n-1 do - local s = M.slice(t, i+1, i+n) - if #s>0 and i+1<#t then - while (#s < n and pad) do s[#s+1] = pad end - f(s) - end - end -end - -local function partgen3(t, n, f, pad) -- generates sliding array partitions - for i = 0, #t, 1 do - local s = M.slice(t, i+1, i+n) - if #s>0 and i+n<=#t then - while (#s < n and pad) do s[#s+1] = pad end - f(s) - end - end -end - -local function permgen(t, n, f) -- taken from PiL: http://www.lua.org/pil/9.3.html - if n == 0 then f(t) end - for i = 1,n do - t[n], t[i] = t[i], t[n] - permgen(t, n-1, f) - t[n], t[i] = t[i], t[n] - end -end - -local function signum(a) return a>=0 and 1 or -1 end - --- Internal counter for unique ids generation -local unique_id_counter = -1 - ---- Operator functions --- @section Operator functions - -M.operator = {} ---- Returns a + b. Aliased as `op.add`. --- @name operator.add --- @param a a value --- @param b a value --- @return a + b -M.operator.add = function(a,b) return a + b end - ---- Returns a - b. Aliased as `op.sub`. --- @name operator.sub --- @param a a value --- @param b a value --- @return a - b -M.operator.sub = function(a,b) return a - b end - ---- Returns a * b. Aliased as `op.mul`. --- @name operator.mul --- @param a a value --- @param b a value --- @return a * b -M.operator.mul = function(a,b) return a * b end - ---- Returns a / b. Aliased as `op.div`. --- @name operator.div --- @param a a value --- @param b a value --- @return a / b -M.operator.div = function(a,b) return a / b end - ---- Returns a % b. Aliased as `op.mod`. --- @name operator.mod --- @param a a value --- @param b a value --- @return a % b -M.operator.mod = function(a,b) return a % b end - ---- Returns a ^ b. Aliased as `op.exp`, `op.pow`. --- @name operator.exp --- @param a a value --- @param b a value --- @return a ^ b -M.operator.exp = function(a,b) return a ^ b end -M.operator.pow = M.operator.exp - ---- Returns -a. Aliased as `op.unm`, `op.neg`. --- @name operator.unm --- @param a a value --- @return -a -M.operator.unm = function(a) return -a end -M.operator.neg = M.operator.unm - ---- Performs floor division (//) between `a` and `b`. It rounds the quotient towards minus infinity. --- Aliased as `op.floordiv`. --- @name operator.floordiv --- @param a a value --- @param b a value --- @return a // b -M.operator.floordiv = function(a, b) return floor(a/b) end - ---- Performs integer division between `a` and `b`. Aliased as `op.intdiv`. --- @name operator.intdiv --- @param a a value --- @param b a value --- @return a / b -M.operator.intdiv = function(a,b) - return a>=0 and floor(a/b) or ceil(a/b) -end - ---- Checks if a equals b. Aliased as `op.eq`. --- @name operator.eq --- @param a a value --- @param b a value --- @return a == b -M.operator.eq = function(a,b) return a == b end - ---- Checks if a not equals b. Aliased as `op.neq`. --- @name operator.neq --- @param a a value --- @param b a value --- @return a ~= b -M.operator.neq = function(a,b) return a ~= b end - ---- Checks if a is strictly less than b. Aliased as `op.lt`. --- @name operator.lt --- @param a a value --- @param b a value --- @return a < b -M.operator.lt = function(a,b) return a < b end - ---- Checks if a is strictly greater than b. Aliased as `op.gt`. --- @name operator.gt --- @param a a value --- @param b a value --- @return a > b -M.operator.gt = function(a,b) return a > b end - ---- Checks if a is less or equal to b. Aliased as `op.le`. --- @name operator.le --- @param a a value --- @param b a value --- @return a <= b -M.operator.le = function(a,b) return a <= b end - ---- Checks if a is greater or equal to b. Aliased as `op.ge`. --- @name operator.ge --- @param a a value --- @param b a value --- @return a >= b -M.operator.ge = function(a,b) return a >= b end - ---- Returns logical a and b. Aliased as `op.land`. --- @name operator.ge --- @param a a value --- @param b a value --- @return a and b -M.operator.land = function(a,b) return a and b end - ---- Returns logical a or b. Aliased as `op.lor`. --- @name operator.lor --- @param a a value --- @param b a value --- @return a or b -M.operator.lor = function(a,b) return a or b end - ---- Returns logical not a. Aliased as `op.lnot`. --- @name operator.lnot --- @param a a value --- @return not a -M.operator.lnot = function(a) return not a end - ---- Returns concatenation of a and b. Aliased as `op.concat`. --- @name operator.concat --- @param a a value --- @param b a value --- @return a .. b -M.operator.concat = function(a,b) return a..b end - ---- Returns the length of a. Aliased as `op.len`. --- @name operator.length --- @param a a value --- @return #a -M.operator.length = function(a) return #a end -M.operator.len = M.operator.length - ---- Table functions --- @section Table functions - ---- Clears a table. All its values become nil. --- @name clear --- @param t a table --- @return the given table, cleared. -function M.clear(t) - for k in pairs(t) do t[k] = nil end - return t -end - - - ---- Iterates on key-value pairs, calling `f (v, k)` at every step. ---
Aliased as `forEach`. --- @name each --- @param t a table --- @param f a function, prototyped as `f (v, k)` --- @see eachi -function M.each(t, f) - for index,value in pairs(t) do - f(value, index) - end -end - ---- Iterates on integer key-value pairs, calling `f(v, k)` every step. --- Only applies to values located at integer keys. The table can be a sparse array. --- Iteration will start from the lowest integer key found to the highest one. ---
Aliased as `forEachi`. --- @name eachi --- @param t a table --- @param f a function, prototyped as `f (v, k)` --- @see each -function M.eachi(t, f) - local lkeys = M.sort(M.select(M.keys(t), M.isInteger)) - for k, key in ipairs(lkeys) do - f(t[key], key) - end -end - ---- Collects values at given keys and return them wrapped in an array. --- @name at --- @param t a table --- @param ... A variable number of keys to collect values --- @return an array-list of values -function M.at(t, ...) - local values = {} - for i, key in ipairs({...}) do values[#values+1] = t[key] end - return values -end - ---- Adjusts the value at a given key using a function or a value. In case `f` is a function, --- it should be prototyped `f(v)`. It does not mutate the given table, but rather --- returns a new array. In case the given `key` does not exist in `t`, it throws an error. --- @param t a table --- @param key a key --- @param f a function, prototyped as `f(v)` or a value -function M.adjust(t, key, f) - if (t[key] == nil) then error("key not existing in table") end - local _t = M.clone(t) - _t[key] = type(f) == 'function' and f(_t[key]) or f - return _t -end - ---- Counts occurrences of a given value in a table. Uses @{isEqual} to compare values. --- @name count --- @param t a table --- @param[opt] val a value to be searched in the table. If not given, the @{size} of the table will be returned --- @return the count of occurrences of the given value --- @see countf --- @see size -function M.count(t, val) - if val == nil then return M.size(t) end - local count = 0 - for k, v in pairs(t) do - if M.isEqual(v, val) then count = count + 1 end - end - return count -end - ---- Counts the number of values passing a predicate test. Same as @{count}, but uses an iterator. --- Returns the count for values passing the test `f (v, k)` --- @name countf --- @param t a table --- @param f an iterator function, prototyped as `f (v, k)` --- @return the count of values validating the predicate --- @see count --- @see size -function M.countf(t, f) - local count = 0 - for k, v in pairs(t) do - if f(v, k) then count = count + 1 end - end - return count -end - ---- Checks if all values in a collection are equal. Uses an optional `comp` function which is used --- to compare values and defaults to @{isEqual} when not given. ---
Aliased as `alleq`. --- @name allEqual --- @param t a table --- @param[opt] comp a comparison function. Defaults to `isEqual` --- @return `true` when all values in `t` are equal, `false` otherwise. --- @see isEqual -function M.allEqual(t, comp) - local k, pivot = next(t) - for k, v in pairs(t) do - if comp then - if not comp(pivot, v) then return false end - else - if not M.isEqual(pivot, v) then return false end - end - end - return true -end - ---- Loops `n` times through a table. In case `n` is omitted, it will loop forever. --- In case `n` is lower or equal to 0, it returns an empty function. ---
Aliased as `loop`. --- @name cycle --- @param t a table --- @param[opt] n the number of loops --- @return an iterator function yielding value-key pairs from the passed-in table. -function M.cycle(t, n) - n = n or 1 - if n<=0 then return M.noop end - local k, fk - local i = 0 - while true do - return function() - k = k and next(t,k) or next(t) - fk = not fk and k or fk - if n then - i = (k==fk) and i+1 or i - if i > n then - return - end - end - return t[k], k - end - end -end - ---- Maps `f (v, k)` on value-key pairs, collects and returns the results. ---
Aliased as `collect`. --- @name map --- @param t a table --- @param f an iterator function, prototyped as `f (v, k)` --- @return a table of results -function M.map(t, f) - local _t = {} - for index,value in pairs(t) do - local k, kv, v = index, f(value, index) - _t[v and kv or k] = v or kv - end - return _t -end - ---- Reduces a table, left-to-right. Folds the table from the first element to the last element --- to a single value, using a given iterator and an initial state. --- The iterator takes a state and a value and returns a new state. ---
Aliased as `inject`, `foldl`. --- @name reduce --- @param t a table --- @param f an iterator function, prototyped as `f (state, value)` --- @param[opt] state an initial state of reduction. Defaults to the first value in the table. --- @return the final state of reduction --- @see best --- @see reduceRight --- @see reduceBy -function M.reduce(t, f, state) - for k,value in pairs(t) do - if state == nil then state = value - else state = f(state,value) - end - end - return state -end - ---- Returns the best value passing a selector function. Acts as a special case of --- @{reduce}, using the first value in `t` as an initial state. It thens folds the given table, --- testing each of its values `v` and selecting the value passing the call `f(state,v)` every time. --- @name best --- @param t a table --- @param f an iterator function, prototyped as `f (state, value)` --- @return the final state of reduction --- @see reduce --- @see reduceRight --- @see reduceBy -function M.best(t, f) - local _, state = next(t) - for k,value in pairs(t) do - if state == nil then state = value - else state = f(state,value) and state or value - end - end - return state -end - ---- Reduces values in a table passing a given predicate. Folds the table left-to-right, considering --- only values validating a given predicate. --- @name reduceBy --- @param t a table --- @param f an iterator function, prototyped as `f (state, value)` --- @param pred a predicate function `pred (v, k)` to select values to be considered for reduction --- @param[opt] state an initial state of reduction. Defaults to the first value in the table of selected values. --- @param[optchain] ... optional args to be passed to `pred` --- @return the final state of reduction --- @see reduce --- @see best --- @see reduceRight -function M.reduceBy(t, f, pred, state) - return M.reduce(M.select(t, pred), f, state) -end - ---- Reduces a table, right-to-left. Folds the table from the last element to the first element --- to single value, using a given iterator and an initial state. --- The iterator takes a state and a value, and returns a new state. ---
Aliased as `injectr`, `foldr`. --- @name reduceRight --- @param t a table --- @param f an iterator function, prototyped as `f (state, value)` --- @param[opt] state an initial state of reduction. Defaults to the last value in the table. --- @return the final state of reduction --- @see reduce --- @see best --- @see reduceBy -function M.reduceRight(t, f, state) - return M.reduce(M.reverse(t),f,state) -end - ---- Reduces a table while saving intermediate states. Folds the table left-to-right --- using a given iterator and an initial state. The iterator takes a state and a value, --- and returns a new state. The result is an array of intermediate states. ---
Aliased as `mapr` --- @name mapReduce --- @param t a table --- @param f an iterator function, prototyped as `f (state, value)` --- @param[opt] state an initial state of reduction. Defaults to the first value in the table. --- @return an array of states --- @see mapReduceRight -function M.mapReduce(t, f, state) - local _t = {} - for i,value in pairs(t) do - _t[i] = not state and value or f(state,value) - state = _t[i] - end - return _t -end - ---- Reduces a table while saving intermediate states. Folds the table right-to-left --- using a given iterator and an initial state. The iterator takes a state and a value, --- and returns a new state. The result is an array of intermediate states. ---
Aliased as `maprr` --- @name mapReduceRight --- @param t a table --- @param f an iterator function, prototyped as `f (state, value)` --- @param[opt] state an initial state of reduction. Defaults to the last value in the table. --- @return an array of states --- @see mapReduce -function M.mapReduceRight(t, f, state) - return M.mapReduce(M.reverse(t),f,state) -end - ---- Performs a linear search for a value in a table. It does not work for nested tables. --- The given value can be a function prototyped as `f (v, value)` which should return true when --- any v in the table equals the value being searched. ---
Aliased as `any`, `some`, `contains` --- @name include --- @param t a table --- @param value a value to search for --- @return a boolean : `true` when found, `false` otherwise --- @see detect -function M.include(t, value) - local _iter = (type(value) == 'function') and value or M.isEqual - for k,v in pairs(t) do - if _iter(v,value) then return true end - end - return false -end - ---- Performs a linear search for a value in a table. Returns the key of the value if found. --- The given value can be a function prototyped as `f (v, value)` which should return true when --- any v in the table equals the value being searched. This function is similar to @{find}, --- which is mostly meant to work with array. --- @name detect --- @param t a table --- @param value a value to search for --- @return the key of the value when found or __nil__ --- @see include --- @see find -function M.detect(t, value) - local _iter = (type(value) == 'function') and value or M.isEqual - for key,arg in pairs(t) do - if _iter(arg,value) then return key end - end -end - ---- Returns all values having specified keys `props`. --- @name where --- @param t a table --- @param props a set of keys --- @return an array of values from the passed-in table --- @see findWhere -function M.where(t, props) - local r = M.select(t, function(v) - for key in pairs(props) do - if v[key] ~= props[key] then return false end - end - return true - end) - return #r > 0 and r or nil -end - ---- Returns the first value having specified keys `props`. --- @name findWhere --- @param t a table --- @param props a set of keys --- @return a value from the passed-in table --- @see where -function M.findWhere(t, props) - local index = M.detect(t, function(v) - for key in pairs(props) do - if props[key] ~= v[key] then return false end - end - return true - end) - return index and t[index] -end - ---- Selects and returns values passing an iterator test. ---
Aliased as `filter`. --- @name select --- @param t a table --- @param f an iterator function, prototyped as `f (v, k)` --- @return the selected values --- @see reject -function M.select(t, f) - local _t = {} - for index,value in pairs(t) do - if f(value,index) then _t[#_t+1] = value end - end - return _t -end - ---- Clones a table while dropping values passing an iterator test. ---
Aliased as `discard` --- @name reject --- @param t a table --- @param f an iterator function, prototyped as `f (v, k)` --- @return the remaining values --- @see select -function M.reject(t, f) - local _t = {} - for index,value in pairs (t) do - if not f(value,index) then _t[#_t+1] = value end - end - return _t -end - ---- Checks if all values in a table are passing an iterator test. ---
Aliased as `every` --- @name all --- @param t a table --- @param f an iterator function, prototyped as `f (v, k)` --- @return `true` if all values passes the predicate, `false` otherwise -function M.all(t, f) - for index,value in pairs(t) do - if not f(value,index) then return false end - end - return true -end - ---- Invokes a method on each value in a table. --- @name invoke --- @param t a table --- @param method a function, prototyped as `f (v, k)` --- @return the result of the call `f (v, k)` --- @see pluck -function M.invoke(t, method) - return M.map(t, function(v, k) - if (type(v) == 'table') then - if v[method] then - if M.isCallable(v[method]) then - return v[method](v,k) - else - return v[method] - end - else - if M.isCallable(method) then - return method(v,k) - end - end - elseif M.isCallable(method) then - return method(v,k) - end - end) -end - ---- Extracts values in a table having a given key. --- @name pluck --- @param t a table --- @param key a key, will be used to index in each value: `value[key]` --- @return an array of values having the given key -function M.pluck(t, key) - local _t = {} - for k, v in pairs(t) do - if v[key] then _t[#_t+1] = v[key] end - end - return _t -end - ---- Returns the max value in a collection. If a `transform` function is passed, it will --- be used to evaluate values by which all objects will be sorted. --- @name max --- @param t a table --- @param[opt] transform a transformation function, prototyped as `transform (v, k)`, defaults to @{identity} --- @return the max value found --- @see min -function M.max(t, transform) - return extract(t, f_max, transform) -end - ---- Returns the min value in a collection. If a `transform` function is passed, it will --- be used to evaluate values by which all objects will be sorted. --- @name min --- @param t a table --- @param[opt] transform a transformation function, prototyped as `transform (v, k)`, defaults to @{identity} --- @return the min value found --- @see max -function M.min(t, transform) - return extract(t, f_min, transform) -end - ---- Checks if two tables are the same. It compares if both tables features the same values, --- but not necessarily at the same keys. --- @name same --- @param a a table --- @param b another table --- @return `true` or `false` -function M.same(a, b) - return M.all(a, function(v) return M.include(b,v) end) - and M.all(b, function(v) return M.include(a,v) end) -end - ---- Sorts a table, in-place. If a comparison function is given, it will be used to sort values. --- @name sort --- @param t a table --- @param[opt] comp a comparison function prototyped as `comp (a, b)`, defaults to < operator. --- @return the given table, sorted. --- @see sortBy -function M.sort(t, comp) - t_sort(t, comp) - return t -end - ---- Iterates on values with respect to key order. Keys are sorted using `comp` function --- which defaults to `math.min`. It returns upon each call a `key, value` pair. --- @name sortedk --- @param t a table --- @param[opt] comp a comparison function. Defaults to `<` operator --- @return an iterator function --- @see sortedv -function M.sortedk(t, comp) - local keys = M.keys(t) - t_sort(keys, comp) - local i = 0 - return function () - i = i + 1 - return keys[i], t[keys[i]] - end -end - ---- Iterates on values with respect to values order. Values are sorted using `comp` function --- which defaults to `math.min`. It returns upon each call a `key, value` pair. --- @name sortedv --- @param t a table --- @param[opt] comp a comparison function. Defaults to `<` operator --- @return an iterator function --- @see sortedk -function M.sortedv(t, comp) - local keys = M.keys(t) - comp = comp or f_min - t_sort(keys, function(a,b) return comp(t[a],t[b]) end) - local i = 0 - return function () - i = i + 1 - return keys[i], t[keys[i]] - end -end - ---- Sorts a table in-place using a transform. Values are ranked in a custom order of the results of --- running `transform (v)` on all values. `transform` may also be a string name property sort by. --- `comp` is a comparison function. --- @name sortBy --- @param t a table --- @param[opt] transform a `transform` function to sort elements prototyped as `transform (v)`. Defaults to @{identity} --- @param[optchain] comp a comparison function, defaults to the `<` operator --- @return a new array of sorted values --- @see sort -function M.sortBy(t, transform, comp) - local f = transform or M.identity - if (type(transform) == 'string') then - f = function(t) return t[transform] end - end - comp = comp or f_min - t_sort(t, function(a,b) return comp(f(a), f(b)) end) - return t -end - ---- Splits a table into subsets groups. --- @name groupBy --- @param t a table --- @param iter an iterator function, prototyped as `iter (v, k)` --- @return a table of subsets groups -function M.groupBy(t, iter) - local _t = {} - for k,v in pairs(t) do - local _key = iter(v,k) - if _t[_key] then _t[_key][#_t[_key]+1] = v - else _t[_key] = {v} - end - end - return _t -end - ---- Groups values in a collection and counts them. --- @name countBy --- @param t a table --- @param iter an iterator function, prototyped as `iter (v, k)` --- @return a table of subsets groups names paired with their count -function M.countBy(t, iter) - local stats = {} - for i,v in pairs(t) do - local key = iter(v,i) - stats[key] = (stats[key] or 0)+1 - end - return stats -end - ---- Counts the number of values in a collection. If being passed more than one argument --- it will return the count of all passed-in arguments. --- @name size --- @param[opt] ... Optional variable number of arguments --- @return a count --- @see count --- @see countf -function M.size(...) - local args = {...} - local arg1 = args[1] - return (type(arg1) == 'table') and count(args[1]) or count(args) -end - ---- Checks if all the keys of `other` table exists in table `t`. It does not --- compares values. The test is not commutative, i.e table `t` may contains keys --- not existing in `other`. --- @name containsKeys --- @param t a table --- @param other another table --- @return `true` or `false` --- @see sameKeys -function M.containsKeys(t, other) - for key in pairs(other) do - if not t[key] then return false end - end - return true -end - ---- Checks if both given tables have the same keys. It does not compares values. --- @name sameKeys --- @param tA a table --- @param tB another table --- @return `true` or `false` --- @see containsKeys -function M.sameKeys(tA, tB) - for key in pairs(tA) do - if not tB[key] then return false end - end - for key in pairs(tB) do - if not tA[key] then return false end - end - return true -end - ---- Array functions --- @section Array functions - ---- Samples `n` random values from an array. If `n` is not specified, returns a single element. --- It uses internally @{shuffle} to shuffle the array before sampling values. If `seed` is passed, --- it will be used for shuffling. --- @name sample --- @param array an array --- @param[opt] n a number of elements to be sampled. Defaults to 1. --- @param[optchain] seed an optional seed for shuffling --- @return an array of selected values --- @see sampleProb -function M.sample(array, n, seed) - n = n or 1 - if n == 0 then return {} end - if n == 1 then - if seed then randomseed(seed) end - return {array[random(1, #array)]} - end - return M.slice(M.shuffle(array, seed), 1, n) -end - ---- Return elements from a sequence with a given probability. It considers each value independently. --- Providing a seed will result in deterministic sampling. Given the same seed it will return the same sample --- every time. --- @name sampleProb --- @param array an array --- @param prob a probability for each element in array to be selected --- @param[opt] seed an optional seed for deterministic sampling --- @return an array of selected values --- @see sample -function M.sampleProb(array, prob, seed) - if seed then randomseed(seed) end - local t = {} - for k, v in ipairs(array) do - if random() < prob then t[#t+1] = v end - end - return t -end - ---- Returns the n-top values satisfying a predicate. It takes a comparison function --- `comp` used to sort array values, and then picks the top n-values. It leaves the original array untouched. --- @name nsorted --- @param array an array --- @param[opt] n a number of values to retrieve. Defaults to 1. --- @param[optchain] comp a comparison function. Defaults to `<` operator. --- @return an array of top n values -function M.nsorted(array, n, comp) - comp = comp or f_min - n = n or 1 - local values, count = {}, 0 - for k, v in M.sortedv(array, comp) do - if count < n then - count = count + 1 - values[count] = v - end - end - return values -end - ---- Returns a shuffled copy of a given array. If a seed is provided, it will --- be used to init the built-in pseudo random number generator (using `math.randomseed`). --- @name shuffle --- @param array an array --- @param[opt] seed a seed --- @return a shuffled copy of the given array -function M.shuffle(array, seed) - if seed then randomseed(seed) end - local _shuffled = {} - for index, value in ipairs(array) do - local randPos = floor(random()*index)+1 - _shuffled[index] = _shuffled[randPos] - _shuffled[randPos] = value - end - return _shuffled -end - ---- Converts a list of arguments to an array. --- @name pack --- @param ... a list of arguments --- @return an array of all passed-in args -function M.pack(...) return {...} end - ---- Looks for the first occurrence of a given value in an array. Returns the value index if found. --- Uses @{isEqual} to compare values. --- @name find --- @param array an array of values --- @param value a value to lookup for --- @param[opt] from the index from where the search will start. Defaults to 1. --- @return the index of the value if found in the array, `nil` otherwise. --- @see detect -function M.find(array, value, from) - for i = from or 1, #array do - if M.isEqual(array[i], value) then return i end - end -end - ---- Returns an array where values are in reverse order. The passed-in array should not be sparse. --- @name reverse --- @param array an array --- @return a reversed array -function M.reverse(array) - local _array = {} - for i = #array,1,-1 do - _array[#_array+1] = array[i] - end - return _array -end - ---- Replaces elements in a given array with a given value. In case `i` and `j` are given --- it will only replaces values at indexes between `[i,j]`. In case `j` is greater than the array --- size, it will append new values, increasing the array size. --- @name fill --- @param array an array --- @param value a value --- @param[opt] i the index from which to start replacing values. Defaults to 1. --- @param[optchain] j the index where to stop replacing values. Defaults to the array size. --- @return the original array with values changed -function M.fill(array, value, i, j) - j = j or M.size(array) - for i = i or 1, j do array[i] = value end - return array -end - ---- Returns an array of `n` zeros. --- @name zeros --- @param n a number --- @return an array --- @see ones --- @see vector -function M.zeros(n) return M.fill({}, 0, 1, n) end - ---- Returns an array of `n` 1's. --- @name ones --- @param n a number --- @return an array --- @see zeros --- @see vector -function M.ones(n) return M.fill({}, 1, 1, n) end - ---- Returns an array of `n` times a given value. --- @name vector --- @param value a value --- @param n a number --- @return an array --- @see zeros --- @see ones -function M.vector(value, n) return M.fill({}, value, 1, n) end - ---- Collects values from a given array. The passed-in array should not be sparse. --- This function collects values as long as they satisfy a given predicate and returns on the first falsy test. ---
Aliased as `takeWhile` --- @name selectWhile --- @param array an array --- @param f an iterator function prototyped as `f (v, k)` --- @return a new table containing all values collected --- @see dropWhile -function M.selectWhile(array, f) - local t = {} - for i,v in ipairs(array) do - if f(v,i) then t[i] = v else break end - end - return t -end - ---- Collects values from a given array. The passed-in array should not be sparse. --- This function collects values as long as they do not satisfy a given predicate and returns on the first truthy test. ---
Aliased as `rejectWhile` --- @name dropWhile --- @param array an array --- @param f an iterator function prototyped as `f (v, k)` --- @return a new table containing all values collected --- @see selectWhile -function M.dropWhile(array, f) - local _i - for i,v in ipairs(array) do - if not f(v, i) then - _i = i - break - end - end - if (_i == nil) then return {} end - return M.rest(array,_i) -end - ---- Returns the index at which a value should be inserted. This index is evaluated so --- that it maintains the sort. If a comparison function is passed, it will be used to sort --- values. --- @name sortedIndex --- @param array an array --- @param the value to be inserted --- @param[opt] comp an comparison function prototyped as `f (a, b)`, defaults to < operator. --- @param[optchain] sort whether or not the passed-in array should be sorted --- @return number the index at which the passed-in value should be inserted -function M.sortedIndex(array, value, comp, sort) - local _comp = comp or f_min - if (sort == true) then t_sort(array,_comp) end - for i = 1,#array do - if not _comp(array[i],value) then return i end - end - return #array+1 -end - ---- Returns the index of the first occurrence of value in an array. --- @name indexOf --- @param array an array --- @param value the value to search for --- @return the index of the passed-in value --- @see lastIndexOf -function M.indexOf(array, value) - for k = 1,#array do - if array[k] == value then return k end - end -end - ---- Returns the index of the last occurrence of value in an array. --- @name lastIndexOf --- @param array an array --- @param value the value to search for --- @return the index of the last occurrence of the passed-in value or __nil__ --- @see indexOf -function M.lastIndexOf(array, value) - local key = M.indexOf(M.reverse(array),value) - if key then return #array-key+1 end -end - ---- Returns the first index at which a predicate returns true. --- @name findIndex --- @param array an array --- @param pred a predicate function prototyped as `pred (v, k)` --- @return the index found or __nil__ --- @see findLastIndex -function M.findIndex(array, pred) - for k = 1, #array do - if pred(array[k],k) then return k end - end -end - ---- Returns the last index at which a predicate returns true. --- @name findLastIndex --- @param array an array --- @param pred a predicate function prototyped as `pred (k, v)` --- @return the index found or __nil__ --- @see findIndex -function M.findLastIndex(array, pred) - local key = M.findIndex(M.reverse(array),pred) - if key then return #array-key+1 end -end - ---- Adds all passed-in values at the top of an array. The last elements will bubble to the --- top of the given array. --- @name addTop --- @param array an array --- @param ... a variable number of arguments --- @return the passed-in array with new values added --- @see prepend --- @see push -function M.addTop(array, ...) - for k,v in ipairs({...}) do - t_insert(array,1,v) - end - return array -end - ---- Adds all passed-in values at the top of an array. As opposed to @{addTop}, it preserves the order --- of the passed-in elements. --- @name prepend --- @param array an array --- @param ... a variable number of arguments --- @return the passed-in array with new values added --- @see addTop --- @see push -function M.prepend(array, ...) - return M.append({...}, array) -end - ---- Pushes all passed-in values at the end of an array. --- @name push --- @param array an array --- @param ... a variable number of arguments --- @return the passed-in array with new added values --- @see addTop --- @see prepend -function M.push(array, ...) - local args = {...} - for k,v in ipairs({...}) do - array[#array+1] = v - end - return array -end - ---- Removes and returns the values at the top of a given array. ---
Aliased as `pop` --- @name shift --- @param array an array --- @param[opt] n the number of values to be popped. Defaults to 1. --- @return the popped values --- @see unshift -function M.shift(array, n) - n = min(n or 1, #array) - local ret = {} - for i = 1, n do - local retValue = array[1] - ret[#ret + 1] = retValue - t_remove(array,1) - end - return unpack(ret) -end - ---- Removes and returns the values at the end of a given array. --- @name unshift --- @param array an array --- @param[opt] n the number of values to be unshifted. Defaults to 1. --- @return the values --- @see shift -function M.unshift(array, n) - n = min(n or 1, #array) - local ret = {} - for i = 1, n do - local retValue = array[#array] - ret[#ret + 1] = retValue - t_remove(array) - end - return unpack(ret) -end - ---- Removes all provided values in a given array. ---
Aliased as `remove` --- @name pull --- @param array an array --- @param ... a variable number of values to be removed from the array --- @return the passed-in array with values removed -function M.pull(array, ...) - local values = {...} - for i = #array, 1, -1 do - local remval = false - for k, rmValue in ipairs(values) do - if (remval == false) then - if M.isEqual(array[i], rmValue) then - t_remove(array, i) - remval = true - end - end - end - end - return array -end - ---- Removes values at an index within the range `[start, finish]`. ---
Aliased as `rmRange`, `chop` --- @name removeRange --- @param array an array --- @param[opt] start the lower bound index, defaults to the first index in the array. --- @param[optchain] finish the upper bound index, defaults to the array length. --- @return the passed-in array with values removed -function M.removeRange(array, start, finish) - start = start or 1 - finish = finish or #array - if start > finish then - error("start cannot be greater than finish.") - end - for i = finish, start, -1 do - t_remove(array, i) - end - return array -end - ---- Chunks together consecutive values. Values are chunked on the basis of the return --- value of a provided predicate `f (v, k)`. Consecutive elements which return --- the same value are chunked together. Leaves the first argument untouched if it is not an array. --- @name chunk --- @param array an array --- @param f an iterator function prototyped as `f (v, k)` --- @return a table of chunks (arrays) --- @see zip -function M.chunk(array, f) - local ch, ck, prev, val = {}, 0 - for k,v in ipairs(array) do - val = f(v, k) - prev = (prev==nil) and val or prev - ck = ((val~=prev) and (ck+1) or ck) - if not ch[ck] then - ch[ck] = {array[k]} - else - ch[ck][#ch[ck]+1] = array[k] - end - prev = val - end - return ch -end - ---- Slices values indexed within `[start, finish]` range. ---
Aliased as `M.sub` --- @name slice --- @param array an array --- @param[opt] start the lower bound index, defaults to the first index in the array. --- @param[optchain] finish the upper bound index, defaults to the array length. --- @return a new array of sliced values -function M.slice(array, start, finish) - local t = {} - for k = start or 1, finish or #array do - t[#t+1] = array[k] - end - return t -end - ---- Returns the first N values in an array. ---
Aliased as `head`, `take` --- @name first --- @param array an array --- @param[opt] n the number of values to be collected, defaults to 1. --- @return a new array --- @see initial --- @see last --- @see rest -function M.first(array, n) - n = n or 1 - local t = {} - for k = 1, n do - t[k] = array[k] - end - return t -end - ---- Returns all values in an array excluding the last N values. --- @name initial --- @param array an array --- @param[opt] n the number of values to be left, defaults to the array length. --- @return a new array --- @see first --- @see last --- @see rest -function M.initial(array, n) - local l = #array - n = n and l-(min(n,l)) or l-1 - local t = {} - for k = 1, n do - t[k] = array[k] - end - return t -end - ---- Returns the last N values in an array. --- @name last --- @param array an array --- @param[opt] n the number of values to be collected, defaults to the array length. --- @return a new array --- @see first --- @see initial --- @see rest -function M.last(array, n) - local l = #array - n = n and l-min(n-1,l-1) or 2 - local t = {} - for k = n, l do - t[#t+1] = array[k] - end - return t -end - ---- Returns all values after index. ---
Aliased as `tail` --- @name rest --- @param array an array --- @param[opt] index an index, defaults to 1 --- @return a new array --- @see first --- @see initial --- @see last -function M.rest(array, index) - local t = {} - for k = index or 1, #array do - t[#t+1] = array[k] - end - return t -end - ---- Returns the value at a given index. --- @name nth --- @param array an array --- @param index an index --- @return the value at the given index -function M.nth(array, index) - return array[index] -end - ---- Returns all truthy values (removes `falses` and `nils`). --- @name compact --- @param array an array --- @return a new array -function M.compact(array) - local t = {} - for k,v in pairs(array) do - if v then t[#t+1] = v end - end - return t -end - ---- Flattens a nested array. Passing `shallow` will only flatten at the first level. --- @name flatten --- @param array an array --- @param[opt] shallow specifies the flattening depth. Defaults to `false`.` --- @return a flattened array -function M.flatten(array, shallow) - shallow = shallow or false - local new_flattened - local _flat = {} - for key,value in ipairs(array) do - if type(value) == 'table' then - new_flattened = shallow and value or M.flatten (value) - for k,item in ipairs(new_flattened) do _flat[#_flat+1] = item end - else _flat[#_flat+1] = value - end - end - return _flat -end - ---- Returns values from an array not present in all passed-in args. ---
Aliased as `without` and `diff` --- @name difference --- @param array an array --- @param another array --- @return a new array --- @see union --- @see intersection --- @see symmetricDifference -function M.difference(array, array2) - if not array2 then return M.clone(array) end - return M.select(array,function(value) - return not M.include(array2,value) - end) -end - ---- Returns the duplicate-free union of all passed in arrays. --- @name union --- @param ... a variable number of arrays arguments --- @return a new array --- @see difference --- @see intersection --- @see symmetricDifference -function M.union(...) - return M.unique(M.flatten({...})) -end - ---- Returns the intersection of all passed-in arrays. --- Each value in the result is present in each of the passed-in arrays. --- @name intersection --- @param ... a variable number of array arguments --- @return a new array --- @see difference --- @see union --- @see symmetricDifference -function M.intersection(...) - local arg = {...} - local array = arg[1] - t_remove(arg, 1) - local _intersect = {} - for i,value in ipairs(array) do - if M.all(arg,function(v) return M.include(v,value) end) then - _intersect[#_intersect+1] = value - end - end - return _intersect -end - ---- Checks if all passed in arrays are disjunct. --- @name disjoint --- @param ... a variable number of arrays --- @return `true` if the intersection of all arrays is not empty, `false` otherwise. --- @see intersection -function M.disjoint(...) - return (#M.intersection(...) == 0) -end - ---- Performs a symmetric difference. Returns values from `array` not present in `array2` and also values --- from `array2` not present in `array`. ---
Aliased as `symdiff` --- @name symmetricDifference --- @param array an array --- @param array2 another array --- @return a new array --- @see difference --- @see union --- @see intersection -function M.symmetricDifference(array, array2) - return M.difference( - M.union(array, array2), - M.intersection(array,array2) - ) -end - ---- Produces a duplicate-free version of a given array. ---
Aliased as `uniq` --- @name unique --- @param array an array --- @return a new array, duplicate-free --- @see isunique --- @see duplicates -function M.unique(array) - local ret = {} - for i = 1, #array do - if not M.find(ret, array[i]) then - ret[#ret+1] = array[i] - end - end - return ret -end - ---- Checks if a given array contains distinct values. Such an array is made of distinct elements, --- which only occur once in this array. ---
Aliased as `isuniq` --- @name isunique --- @param array an array --- @return `true` if the given array is unique, `false` otherwise. --- @see unique --- @see duplicates -function M.isunique(array) - return #array == #(M.unique(array)) -end - ---- Returns an array list of all duplicates in array. --- @name duplicates --- @param array an array --- @return an array-list of duplicates --- @see unique -function M.duplicates(array) - local dict = M.invert(array) - local dups = {} - for k, v in ipairs(array) do - if dict[v] ~= k and not M.find(dups, v) then - dups[#dups+1] = v - end - end - return dups -end - ---- Merges values of each of the passed-in arrays in subsets. --- Only values indexed with the same key in the given arrays are merged in the same subset. ---
Aliased as `transpose` --- @name zip --- @param ... a variable number of array arguments --- @return a new array --- @see zipWith -function M.zip(...) - local args = {...} - local n = M.max(args, function(array) return #array end) - local _ans = {} - for i = 1,n do - if not _ans[i] then _ans[i] = {} end - for k, array in ipairs(args) do - if (array[i]~= nil) then _ans[i][#_ans[i]+1] = array[i] end - end - end - return _ans -end - ---- Merges values using a given function. --- Only values indexed with the same key in the given arrays are merged in the same subset. --- Function `f` is used to combine values. ---
Aliased as `transposeWith` --- @name zipWith --- @param f a function --- @param ... a variable number of array arguments --- @return a flat array of results --- @see zip -function M.zipWith(f, ...) - local args = {...} - local n = M.max(args, function(array) return #array end) - local _ans = {} - for i = 1,n do - _ans[i] = f(unpack(M.pluck(args,i))) - end - return _ans -end - ---- Clones array and appends values from another array. --- @name append --- @param array an array --- @param other an array --- @return a new array -function M.append(array, other) - local t = {} - for i,v in ipairs(array) do t[i] = v end - for i,v in ipairs(other) do t[#t+1] = v end - return t -end - ---- Interleaves arrays. It returns a single array made of values from all --- passed in arrays in their given order, interleaved. --- @name interleave --- @param ... a variable list of arrays --- @return a new array --- @see interpose -function M.interleave(...) - local args = {...} - local n = M.max(args, M.size) - local t = {} - for i = 1, n do - for k, array in ipairs(args) do - if array[i] then t[#t+1] = array[i] end - end - end - return t -end - ---- Interposes value in-between consecutive pair of values in array. ---
Aliased as `intersperse` --- @name interpose --- @param array an array --- @param value a value --- @return a new array --- @see interleave -function M.interpose(array, value) - for k = #array, 2,-1 do - t_insert(array, k, value) - end - return array -end - ---- Produces a flexible list of numbers. If one value is passed, will count from 1 to that value, --- with a default step of 1 (or -1). If two values are passed, will count from the first one to the second one, --- using a default step of 1 (or -1). A third value passed will be considered a step value. --- @name range --- @param[opt] from the initial value of the range --- @param[optchain] to the final value of the range --- @param[optchain] step the step of count. Defaults to 1 or -1. --- @return a new array of numbers -function M.range(from, to, step) - if (from == nil) and (to == nil) and (step ==nil) then - return {} - elseif (from ~= nil) and (to == nil) and (step == nil) then - from, to, step = signum(from), from, signum(from) - elseif (from ~= nil) and (to ~= nil) and (step == nil) then - step = signum(to - from) - end - local _ranged = {from} - local steps = max(floor((to-from)/step),0) - for i=1,steps do _ranged[#_ranged+1] = from+step*i end - return _ranged -end - ---- Creates an array list of `n` values, repeated. --- @name rep --- @param value a value to be repeated --- @param n the number of repetitions of value. --- @return a new array of `n` values -function M.rep(value, n) - local ret = {} - for i = 1, n do ret[i] = value end - return ret -end - ---- Returns the powerset of array values. For instance, when given the set {1,2,3}, --- returns `{{1},{2},{3},{1,2},{2,3},{1,2,3}}`. --- @name powerset --- @param array an array --- @return an array -function M.powerset(array) - local n = #array - if n == 0 then return {{}} end - local t = {} - for l = 1, n do - for s = 1, n-l+1 do - t[#t+1] = M.slice(array,s,s+l-1) - end - end - return t -end - ---- Iterator returning partitions of an array. It returns arrays of length `n` --- made of values from the given array. If the last partition has lower elements than `n` and --- `pad` is supplied, it will be adjusted to `n` of elements with `pad` value. --- @name partition --- @param array an array --- @param[opt] n the size of partitions. Defaults to 1. --- @param[optchain] pads a value to adjust the last subsequence to the `n` elements --- @return an iterator function --- @see overlapping --- @see aperture -function M.partition(array, n, pad) - if n<=0 then return end - return wrap(function() - partgen(array, n or 1, yield, pad) - end) -end - ---- Iterator returning overlapping partitions of an array. --- If the last subsequence has lower elements than `n` and `pad` is --- supplied, it will be adjusted to `n` elements with `pad` value. --- @name overlapping --- @param array an array --- @param[opt] n the size of partitions. Defaults to 2. --- @param[optchain] pads a value to adjust the last subsequence to the `n` elements --- @return an iterator function --- @see partition --- @see aperture -function M.overlapping(array, n, pad) - if n<=1 then return end - return wrap(function() - partgen2(array, n or 2, yield, pad) - end) -end - ---- Iterator returning sliding partitions of an array. ---
Aliased as `sliding` --- @name aperture --- @param array an array --- @param[opt] n the size of partitions. Defaults to 2 (and then behaves like @{pairwise}) --- @return an iterator function --- @see partition --- @see overlapping --- @see pairwise -function M.aperture(array, n) - if n<=1 then return end - return wrap(function() - partgen3(array, n or 2, yield) - end) -end - ---- Iterator returning sliding pairs of an array. --- @name pairwise --- @param array an array --- @return an iterator function --- @see overlapping -function M.pairwise(array) return M.aperture(array, 2) end - ---- Iterator returning the permutations of an array. It returns arrays made of all values --- from the passed-in array, with values permuted. --- @name permutation --- @param array an array --- @return an iterator function -function M.permutation(array) - return wrap(function() - permgen(array, #array, yield) - end) -end - ---- Concatenates values in a given array. Handles booleans as well. If `sep` string is --- passed, it will be used as a separator. Passing `i` and `j` will result in concatenating --- only values within `[i, j]` range. ---
Aliased as `join` --- @name concat --- @param array a given array --- @param[opt] sep a separator string, defaults to the empty string `''`. --- @param[optchain] i the starting index, defaults to 1. --- @param[optchain] j the final index, defaults to the array length. --- @return a string -function M.concat(array, sep, i, j) - return t_concat(M.map(array,tostring),sep,i,j) -end - ---- Returns all possible pairs built from given arrays. --- @name xprod --- @param array a first array --- @param array2 a second array --- @return an array list of all pairs -function M.xprod(array, array2) - local p = {} - for i, v1 in ipairs(array) do - for j, v2 in ipairs(array2) do - p[#p+1] = {v1, v2} - end - end - return p -end - ---- Creates pairs from value and array. Value is always prepended to the pair. --- @name xpairs --- @param valua a value --- @param array an array --- @return an array list of all pairs -function M.xpairs(value, array) - local xpairs = {} - for k, v in ipairs(array) do - xpairs[k] = {value, v} - end - return xpairs -end - ---- Creates pairs from value and array. Value is always appended as the last item to the pair. --- @name xpairsRight --- @param valua a value --- @param array an array --- @return an array list of all pairs -function M.xpairsRight(value, array) - local xpairs = {} - for k, v in ipairs(array) do - xpairs[k] = {v, value} - end - return xpairs -end - ---- Returns the sum of array values. --- @name sum --- @param array a given array --- @return the sum of array values -function M.sum(array) - local s = 0 - for k, v in ipairs(array) do s = s + v end - return s -end - ---- Returns the product of array values. --- @name product --- @param array a given array --- @return the product of array values -function M.product(array) - local p = 1 - for k, v in ipairs(array) do p = p * v end - return p -end - ---- Returns the mean of an array of numbers. ---
Aliased as `average` --- @name mean --- @param array an array of numbers --- @return a number --- @see sum --- @see product --- @see median -function M.mean(array) - return M.sum(array)/(#array) -end - ---- Returns the median of an array of numbers. --- @name median --- @param array an array of numbers --- @return a number --- @see sum --- @see product --- @see mean -function M.median(array) - local t = M.sort(M.clone(array)) - local n = #t - if n == 0 then - return - elseif n==1 then - return t[1] - end - local mid = ceil(n/2) - return n%2==0 and (t[mid] + t[mid+1])/2 or t[mid] -end - ---- Utility functions --- @section Utility functions - ---- The no operation function. --- @name noop --- @return nothing -function M.noop() return end - ---- Returns the passed-in value. This function is used internally --- as a default iterator. --- @name identity --- @param value a value --- @return the passed-in value -function M.identity(value) return value end - ---- Calls `f` with the supplied arguments. Returns the results of `f(...)`. --- @name call --- @param f a function --- @param[opt] ... a vararg list of args to `f` --- @return the result of `f(...)` call. -function M.call(f, ...) - return f(...) -end - ---- Creates a constant function which returns the same output on every call. ---
Aliased as `always` --- @name constant --- @param value a constant value --- @return a constant function -function M.constant(value) - return function() return value end -end - ---- Returns a function which applies `specs` on args. This function produces an object having --- the same structure than `specs` by mapping each property to the result of calling its --- associated function with the supplied arguments --- @name applySpec --- @param specs a table --- @return a function -function M.applySpec(specs) - return function (...) - local spec = {} - for i, f in pairs(specs) do spec[i] = f(...) end - return spec - end -end - ---- Threads `value` through a series of functions. If a function expects more than one args, --- it can be specified using an array list, where the first item is the function and the following --- are the remaining args neeeded. The value is used as the first input. --- @name thread --- @param value a value --- @param ... a vararg list of functions or arrays --- @return a value --- @see threadRight -function M.thread(value, ...) - local state = value - local arg = {...} - for k, t in ipairs(arg) do - if type(t) == 'function' then - state = t(state) - elseif type(t) == 'table' then - local f = t[1] - t_remove(t, 1) - state = M.reduce(t, f, state) - end - end - return state -end - ---- Threads `value` through a series of functions. If a function expects more than one args, --- it can be specified using an array list, where the first item is the function and the following --- are the remaining args neeeded. The value is used as the last input. --- @name threadRight --- @param value a value --- @param ... a vararg list of functions or arrays --- @return a value --- @see thread -function M.threadRight(value, ...) - local state = value - local arg = {...} - for k, t in ipairs(arg) do - if type(t) == 'function' then - state = t(state) - elseif type(t) == 'table' then - local f = t[1] - t_remove(t, 1) - t_insert(t, state) - state = M.reduce(t, f) - end - end - return state -end - ---- Returns a dispatching function. When called with arguments, this function invokes each of its functions --- in the passed-in order and returns the results of the first non-nil evaluation. --- @name dispatch --- @param ... a vararg list of functions --- @return a dispatch function -function M.dispatch(...) - local funcs = {...} - return function (...) - for k, f in ipairs(funcs) do - local r = {f(...)} - if #r > 0 then return unpack(r) end - end - end -end - ---- Memoizes a given function by caching the computed result. --- Useful for speeding-up slow-running functions. ---
Aliased as `cache` --- @name memoize --- @param f a function --- @return a new function -function M.memoize(f) - local _cache = setmetatable({},{__mode = 'kv'}) - return function (key) - if (_cache[key] == nil) then - _cache[key] = f(key) - end - return _cache[key] - end -end - ---- Builds a list from a seed value. Accepts an iterator function, which --- returns either nil to stop iteration or two values : the value to add to the list --- of results and the seed to be used in the next call to the iterator function. --- @name unfold --- @param f an iterator function --- @param seed a seed value --- @return an array of values -function M.unfold(f, seed) - local t, result = {} - while true do - result, seed = f(seed) - if result ~= nil then t[#t+1] = result - else break - end - end - return t -end - ---- Returns a version of `f` that runs only once. Successive calls to `f` --- will keep yielding the same output, no matter what the passed-in arguments are. --- It can be used to initialize variables. --- @name once --- @param f a function --- @return a new function --- @see before --- @see after -function M.once(f) - local _internal = 0 - local _args = {} - return function(...) - _internal = _internal+1 - if _internal <= 1 then _args = {...} end - return f(unpack(_args)) - end -end - ---- Returns a version of `f` that will run no more than count times. Next calls will --- keep yielding the results of the count-th call. --- @name before --- @param f a function --- @param count a count --- @return a new function --- @see once --- @see after -function M.before(f, count) - local _internal = 0 - local _args = {} - return function(...) - _internal = _internal+1 - if _internal <= count then _args = {...} end - return f(unpack(_args)) - end -end - ---- Returns a version of `f` that runs on the `count-th` call. --- Useful when dealing with asynchronous tasks. --- @name after --- @param f a function --- @param count the number of calls before `f` will start running. --- @return a new function --- @see once --- @see before -function M.after(f, count) - local _limit,_internal = count, 0 - return function(...) - _internal = _internal+1 - if _internal >= _limit then return f(...) end - end -end - ---- Composes functions. Each passed-in function consumes the return value of the function that follows. --- In math terms, composing the functions `f`, `g`, and `h` produces the function `f(g(h(...)))`. --- @name compose --- @param ... a variable number of functions --- @return a new function --- @see pipe -function M.compose(...) - -- See: https://github.com/Yonaba/Moses/pull/15#issuecomment-139038895 - local f = M.reverse {...} - return function (...) - local first, _temp = true - for i, func in ipairs(f) do - if first then - first = false - _temp = func(...) - else - _temp = func(_temp) - end - end - return _temp - end -end - ---- Pipes a value through a series of functions. In math terms, --- given some functions `f`, `g`, and `h` in that order, it returns `f(g(h(value)))`. --- @name pipe --- @param value a value --- @param ... a variable number of functions --- @return the result of the composition of function calls. --- @see compose -function M.pipe(value, ...) - return M.compose(...)(value) -end - ---- Returns the logical complement of a given function. For a given input, the returned --- function will output `false` if the original function would have returned `true`, --- and vice-versa. --- @name complement --- @param f a function --- @return the logical complement of the given function `f`. -function M.complement(f) - return function(...) return not f(...) end -end - ---- Calls a sequence of passed-in functions with the same argument. --- Returns a sequence of results. ---
Aliased as `juxt` --- @name juxtapose --- @param value a value --- @param ... a variable number of functions --- @return a list of results -function M.juxtapose(value, ...) - local res = {} - for i, func in ipairs({...}) do - res[i] = func(value) - end - return unpack(res) -end - ---- Wraps `f` inside of the `wrapper` function. It passes `f` as the first argument to `wrapper`. --- This allows the wrapper to execute code before and after `f` runs, --- adjust the arguments, and execute it conditionally. --- @name wrap --- @param f a function to be wrapped, prototyped as `f (...)` --- @param wrapper a wrapper function, prototyped as `wrapper (f, ...)` --- @return the results -function M.wrap(f, wrapper) - return function (...) return wrapper(f,...) end -end - ---- Runs `iter` function `n` times. Collects the results of each run and returns them in an array. --- @name times --- @param iter an iterator function, prototyped as `iter (i)` --- @param[opt] n the number of times `iter` should be called. Defaults to 1. --- @return table an array of results -function M.times(iter, n) - local results = {} - for i = 1, (n or 1) do - results[i] = iter(i) - end - return results -end - ---- Binds `v` to be the first argument to `f`. Calling `f (...)` will result to `f (v, ...)`. --- @name bind --- @param f a function --- @param v a value --- @return a function --- @see bind2 --- @see bindn --- @see bindall -function M.bind(f, v) - return function (...) - return f(v,...) - end -end - ---- Binds `v` to be the second argument to `f`. Calling `f (a, ...)` will result to `f (a, v, ...)`. --- @name bind2 --- @param f a function --- @param v a value --- @return a function --- @see bind --- @see bindn --- @see bindall -function M.bind2(f, v) - return function (t, ...) - return f(t, v, ...) - end -end - ---- Binds `...` to be the N-first arguments to function `f`. --- Calling `f (a1, a2, ..., aN)` will result to `f (..., a1, a2, ...,aN)`. --- @name bindn --- @param f a function --- @param ... a variable number of arguments --- @return a function --- @see bind --- @see bind2 --- @see bindall -function M.bindn(f, ...) - local args = {...} - return function (...) - return f(unpack(M.append(args,{...}))) - end -end - ---- Binds methods to object. As such, whenever any of these methods is invoked, it --- always receives the object as its first argument. --- @name bindall --- @param obj an abject --- @param ... a variable number of method names --- @return the passed-in object with all methods bound to the object itself. --- @see bind --- @see bind2 --- @see bindn -function M.bindall(obj, ...) - local methodNames = {...} - for i, methodName in ipairs(methodNames) do - local method = obj[methodName] - if method then obj[methodName] = M.bind(method, obj) end - end - return obj -end - ---- Returns a function which iterate over a set of conditions. It invokes each predicate, --- passing it given values. It returns the value of the corresponding function of the first --- predicate to return a non-nil value. --- @name cond --- @param conds an array list of predicate-function pairs --- @return the result of invoking `f(...)` of the first predicate to return a non-nil value -function M.cond(conds) - return function(...) - for k, condset in ipairs(conds) do - if condset[1](...) then - return condset[2](...) - end - end - end -end - ---- Returns a validation function. Given a set of functions, the validation function evaluates --- to `true` only when all its funcs returns `true`. --- @name both --- @param ... an array list of functions --- @return `true` when all given funcs returns true with input, false otherwise -function M.both(...) - local funcs = {...} - return function (...) - for k, f in ipairs(funcs) do - if not f(...) then return false end - end - return true - end -end - ---- Returns a validation function. Given a set of functions, the validation function evaluates --- to `true` when at least one of its funcs returns `true`. --- @name either --- @param ... an array list of functions --- @return `true` when one of the given funcs returns `true` with input, `false` otherwise -function M.either(...) - local funcs = {...} - return function (...) - for k, f in ipairs(funcs) do - if f(...) then return true end - end - return false - end -end - ---- Returns a validation function. Given a set of functions, the validation function evaluates --- to `true` when neither of its func return `true`. --- @name neither --- @param ... an array list of functions --- @return `true` when neither of the given funcs returns `true` with input, `false` otherwise -function M.neither(...) - local funcs = {...} - return function (...) - for k, f in ipairs(funcs) do - if f(...) then return false end - end - return true - end -end - ---- Generates an unique ID for the current session. If given a string `template`, it --- will use this template for output formatting. Otherwise, if `template` is a function, it --- will evaluate `template (id)`. ---
Aliased as `uid`. --- @name uniqueId --- @param[opt] template either a string or a function template to format the ID --- @return value an ID -function M.uniqueId(template) - unique_id_counter = unique_id_counter + 1 - if template then - if type(template) == 'string' then - return template:format(unique_id_counter) - elseif type(template) == 'function' then - return template(unique_id_counter) - end - end - return unique_id_counter -end - ---- Produces an iterator which repeatedly apply a function `f` onto an input. --- Yields `value`, then `f(value)`, then `f(f(value))`, continuously. ---
Aliased as `iter`. --- @name iterator --- @param f a function --- @param value an initial input to `f` --- @param[opt] n the number of times the iterator should run --- @return an iterator function -function M.iterator(f, value, n) - local cnt = 0 - return function() - cnt = cnt + 1 - if n and cnt > n then return end - value = f(value) - return value - end -end - ---- Consumes the first `n` values of a iterator then returns it. --- @name skip --- @param iter an iterator function --- @param[opt] n a number. Defaults to 1. --- @return the given iterator -function M.skip(iter, n) - for i = 1, (n or 1) do - if iter() == nil then return end - end - return iter -end - ---- Iterates over an iterator and returns its values in an array. --- @name tabulate --- @param ... an iterator function (returning a generator, a state and a value) --- @return an array of results -function M.tabulate(...) - local r = {} - for v in ... do r[#r+1] = v end - return r -end - ---- Returns the length of an iterator. It consumes the iterator itself. --- @name iterlen --- @param ... an iterator function (returning a generator, a state and a value) --- @return the iterator length -function M.iterlen(...) - local l = 0 - for v in ... do l = l + 1 end - return l -end - ---- Casts value as an array if it is not one. --- @name castArray --- @param value a value --- @return an array containing the given value -function M.castArray(value) - return (type(value)~='table') and {value} or value -end - ---- Creates a function of `f` with arguments flipped in reverse order. --- @name flip --- @param f a function --- @return a function -function M.flip(f) - return function(...) - return f(unpack(M.reverse({...}))) - end -end - ---- Returns a function that gets the nth argument. --- If n is negative, the nth argument from the end is returned. --- @name nthArg --- @param n a number --- @return a function -function M.nthArg(n) - return function (...) - local args = {...} - return args[(n < 0) and (#args + n + 1) or n] - end -end - ---- Returns a function which accepts up to one arg. It ignores any additional arguments. --- @name unary --- @param f a function --- @return a function --- @see ary -function M.unary(f) - return function (...) - local args = {...} - return f(args[1]) - end -end - ---- Returns a function which accepts up to `n` args. It ignores any additional arguments. ---
Aliased as `nAry`. --- @name ary --- @param f a function --- @param[opt] n a number. Defaults to 1. --- @return a function --- @see unary -function M.ary(f, n) - n = n or 1 - return function (...) - local args = {...} - local fargs = {} - for i = 1, n do fargs[i] = args[i] end - return f(unpack(fargs)) - end -end - ---- Returns a function with an arity of 0. The new function ignores any arguments passed to it. --- @name noarg --- @param f a function --- @return a new function -function M.noarg(f) - return function () - return f() - end -end - ---- Returns a function which runs with arguments rearranged. Arguments are passed to the --- returned function in the order of supplied `indexes` at call-time. --- @name rearg --- @param f a function --- @param indexes an array list of indexes --- @return a function -function M.rearg(f, indexes) - return function(...) - local args = {...} - local reargs = {} - for i, arg in ipairs(indexes) do reargs[i] = args[arg] end - return f(unpack(reargs)) - end -end - ---- Creates a function that runs transforms on all arguments it receives. --- @name over --- @param ... a set of functions which will receive all arguments to the returned function --- @return a function --- @see overEvery --- @see overSome --- @see overArgs -function M.over(...) - local transforms = {...} - return function(...) - local r = {} - for i,transform in ipairs(transforms) do - r[#r+1] = transform(...) - end - return r - end -end - ---- Creates a validation function. The returned function checks if *all* of the given predicates return --- truthy when invoked with the arguments it receives. --- @name overEvery --- @param ... a list of predicate functions --- @return a new function --- @see over --- @see overSome --- @see overArgs -function M.overEvery(...) - local f = M.over(...) - return function(...) - return M.reduce(f(...),function(state,v) return state and v end) - end -end - ---- Creates a validation function. The return function checks if *any* of a given predicates return --- truthy when invoked with the arguments it receives. --- @name overSome --- @param ... a list of predicate functions --- @return a new function --- @see over --- @see overEvery --- @see overArgs -function M.overSome(...) - local f = M.over(...) - return function(...) - return M.reduce(f(...),function(state,v) return state or v end) - end -end - ---- Creates a function that invokes `f` with its arguments transformed. 1rst arguments will be passed to --- the 1rst transform, 2nd arg to the 2nd transform, etc. Remaining arguments will not be transformed. --- @name overArgs --- @param f a function --- @param ... a list of transforms funcs prototyped as `f (v)` --- @return the result of running `f` with its transformed arguments --- @see over --- @see overEvery --- @see overSome -function M.overArgs(f,...) - local _argf = {...} - return function(...) - local _args = {...} - for i = 1,#_argf do - local func = _argf[i] - if _args[i] then _args[i] = func(_args[i]) end - end - return f(unpack(_args)) - end -end - ---- Converges two functions into one. --- @name converge --- @param f a function --- @param g a function --- @param h a function --- @return a new version of function f -function M.converge(f, g, h) return function(...) return f(g(...),h(...)) end end - ---- Partially apply a function by filling in any number of its arguments. --- One may pass a string `'M'` as a placeholder in the list of arguments to specify an argument --- that should not be pre-filled, but left open to be supplied at call-time. --- @name partial --- @param f a function --- @param ... a list of partial arguments to `f` --- @return a new version of function f having some of it original arguments filled --- @see partialRight --- @see curry -function M.partial(f,...) - local partial_args = {...} - return function (...) - local n_args = {...} - local f_args = {} - for k,v in ipairs(partial_args) do - f_args[k] = (v == '_') and M.shift(n_args) or v - end - return f(unpack(M.append(f_args,n_args))) - end -end - ---- Similar to @{partial}, but from the right. --- @name partialRight --- @param f a function --- @param ... a list of partial arguments to `f` --- @return a new version of function f having some of it original arguments filled --- @see partialRight --- @see curry -function M.partialRight(f,...) - local partial_args = {...} - return function (...) - local n_args = {...} - local f_args = {} - for k = 1,#partial_args do - f_args[k] = (partial_args[k] == '_') and M.shift(n_args) or partial_args[k] - end - return f(unpack(M.append(n_args, f_args))) - end -end - ---- Curries a function. If the given function `f` takes multiple arguments, it returns another version of --- `f` that takes a single argument (the first of the arguments to the original function) and returns a new --- function that takes the remainder of the arguments and returns the result. --- @name curry --- @param f a function --- @param[opt] n_args the number of arguments expected for `f`. Defaults to 2. --- @return a curried version of `f` --- @see partial --- @see partialRight -function M.curry(f, n_args) - n_args = n_args or 2 - local _args = {} - local function scurry(v) - if n_args == 1 then return f(v) end - if v ~= nil then _args[#_args+1] = v end - if #_args < n_args then - return scurry - else - local r = {f(unpack(_args))} - _args = {} - return unpack(r) - end - end - return scurry -end - ---- Returns the execution time of `f (...)` and its returned values. --- @name time --- @param f a function --- @param[opt] ... optional args to `f` --- @return the execution time and the results of `f (...)` -function M.time(f, ...) - local stime = clock() - local r = {f(...)} - return clock() - stime, unpack(r) -end - ---- Object functions --- @section Object functions - ---- Returns the keys of the object properties. --- @name keys --- @param obj an object --- @return an array -function M.keys(obj) - local keys = {} - for key in pairs(obj) do keys[#keys+1] = key end - return keys -end - ---- Returns the values of the object properties. --- @name values --- @param obj an object --- @return an array of values -function M.values(obj) - local values = {} - for key, value in pairs(obj) do values[#values+1] = value end - return values -end - ---- Returns the value at a given path in an object. --- Path is given as a vararg list of keys. --- @name path --- @param obj an object --- @param ... a vararg list of keys --- @return a value or nil -function M.path(obj, ...) - local value, path = obj, {...} - for i, p in ipairs(path) do - if (value[p] == nil) then return end - value = value[p] - end - return value -end - ---- Spreads object under property path onto provided object. --- It is similar to @{flattenPath}, but removes object under the property path. --- @name spreadPath --- @param obj an object --- @param ... a property path given as a vararg list --- @return the passed-in object with changes --- @see flattenPath -function M.spreadPath(obj, ...) - local path = {...} - for _, p in ipairs(path) do - if obj[p] then - for k, v in pairs(obj[p]) do - obj[k] = v - obj[p][k] = nil - end - end - end - return obj -end - ---- Flattens object under property path onto provided object. --- It is similar to @{spreadPath}, but preserves object under the property path. --- @name flattenPath --- @param obj an object --- @param ... a property path given as a vararg list --- @return the passed-in object with changes --- @see spreadPath -function M.flattenPath(obj, ...) - local path = {...} - for _, p in ipairs(path) do - if obj[p] then - for k, v in pairs(obj[p]) do obj[k] = v end - end - end - return obj -end - ---- Converts key-value pairs to an array-list of `[k, v]` pairs. --- @name kvpairs --- @param obj an object --- @return an array list of key-value pairs --- @see toObj -function M.kvpairs(obj) - local t = {} - for k,v in pairs(obj) do t[#t+1] = {k,v} end - return t -end - ---- Converts an array list of `[k,v]` pairs to an object. Keys are taken --- from the 1rst column in the `[k,v]` pairs sequence, associated with values in the 2nd --- column. --- @name toObj --- @param kvpairs an array-list of `[k,v]` pairs --- @return an object --- @see kvpairs -function M.toObj(kvpairs) - local obj = {} - for k, v in ipairs(kvpairs) do - obj[v[1]] = v[2] - end - return obj -end - ---- Swaps keys with values. Produces a new object where previous keys are now values, --- while previous values are now keys. ---
Aliased as `mirror` --- @name invert --- @param obj a given object --- @return a new object -function M.invert(obj) - local _ret = {} - for k, v in pairs(obj) do - _ret[v] = k - end - return _ret -end - ---- Returns a function that will return the key property of any passed-in object. --- @name property --- @param key a key property name --- @return a function which should accept an object as argument --- @see propertyOf -function M.property(key) - return function(obj) return obj[key] end -end - ---- Returns a function which will return the value of an object property. --- @name propertyOf --- @param obj an object --- @return a function which should accept a key property argument --- @see property -function M.propertyOf(obj) - return function(key) return obj[key] end -end - ---- Converts any given value to a boolean --- @name toBoolean --- @param value a value. Can be of any type --- @return `true` if value is true, `false` otherwise (false or nil). -function M.toBoolean(value) - return not not value -end - ---- Extends an object properties. It copies the properties of extra passed-in objects --- into the destination object, and returns the destination object. The last objects --- will override properties of the same name. --- @name extend --- @param destObj a destination object --- @param ... a list of objects --- @return the destination object extended -function M.extend(destObj, ...) - local sources = {...} - for k, source in ipairs(sources) do - if type(source) == 'table' then - for key, value in pairs(source) do destObj[key] = value end - end - end - return destObj -end - ---- Returns a sorted list of all methods names found in an object. If the given object --- has a metatable implementing an `__index` field pointing to another table, will also recurse on this --- table if `recurseMt` is provided. If `obj` is omitted, it defaults to the library functions. ---
Aliased as `methods`. --- @name functions --- @param[opt] obj an object. Defaults to Moses library functions. --- @return an array-list of methods names -function M.functions(obj, recurseMt) - obj = obj or M - local _methods = {} - for key, value in pairs(obj) do - if type(value) == 'function' then - _methods[#_methods+1] = key - end - end - if recurseMt then - local mt = getmetatable(obj) - if mt and mt.__index then - local mt_methods = M.functions(mt.__index, recurseMt) - for k, fn in ipairs(mt_methods) do - _methods[#_methods+1] = fn - end - end - end - return _methods -end - ---- Clones a given object properties. If `shallow` is passed will also clone nested array properties. --- @name clone --- @param obj an object --- @param[opt] shallow whether or not nested array-properties should be cloned, defaults to false. --- @return a copy of the passed-in object -function M.clone(obj, shallow) - if type(obj) ~= 'table' then return obj end - local _obj = {} - for i,v in pairs(obj) do - if type(v) == 'table' then - if not shallow then - _obj[i] = M.clone(v,shallow) - else _obj[i] = v - end - else - _obj[i] = v - end - end - return _obj -end - ---- Invokes interceptor with the object, and then returns object. --- The primary purpose of this method is to "tap into" a method chain, in order to perform operations --- on intermediate results within the chain. --- @name tap --- @param obj an object --- @param f an interceptor function, should be prototyped as `f (obj)` --- @return the passed-in object -function M.tap(obj, f) - f(obj) - return obj -end - ---- Checks if a given object implements a property. --- @name has --- @param obj an object --- @param key a key property to be checked --- @return `true` or `false` -function M.has(obj, key) - return obj[key]~=nil -end - ---- Returns an object copy having white-listed properties. ---
Aliased as `choose`. --- @name pick --- @param obj an object --- @param ... a variable number of string keys --- @return the filtered object -function M.pick(obj, ...) - local whitelist = M.flatten {...} - local _picked = {} - for key, property in pairs(whitelist) do - if (obj[property])~=nil then - _picked[property] = obj[property] - end - end - return _picked -end - ---- Returns an object copy without black-listed properties. ---
Aliased as `drop`. --- @name omit --- @param obj an object --- @param ... a variable number of string keys --- @return the filtered object -function M.omit(obj, ...) - local blacklist = M.flatten {...} - local _picked = {} - for key, value in pairs(obj) do - if not M.include(blacklist,key) then - _picked[key] = value - end - end - return _picked -end - ---- Applies a template to an object, preserving non-nil properties. ---
Aliased as `defaults`. --- @name template --- @param obj an object --- @param[opt] template a template object. If `nil`, leaves `obj` untouched. --- @return the passed-in object filled -function M.template(obj, template) - if not template then return obj end - for i, v in pairs(template) do - if not obj[i] then obj[i] = v end - end - return obj -end - ---- Performs a deep comparison test between two objects. Can compare strings, functions --- (by reference), nil, booleans. Compares tables by reference or by values. If `useMt` --- is passed, the equality operator `==` will be used if one of the given objects has a --- metatable implementing `__eq`. ---
Aliased as `M.compare`, `M.matches` --- @name isEqual --- @param objA an object --- @param objB another object --- @param[opt] useMt whether or not `__eq` should be used, defaults to false. --- @return `true` or `false` --- @see allEqual -function M.isEqual(objA, objB, useMt) - local typeObjA = type(objA) - local typeObjB = type(objB) - - if typeObjA~=typeObjB then return false end - if typeObjA~='table' then return (objA==objB) end - - local mtA = getmetatable(objA) - local mtB = getmetatable(objB) - - if useMt then - if (mtA or mtB) and (mtA.__eq or mtB.__eq) then - return mtA.__eq(objA, objB) or mtB.__eq(objB, objA) or (objA==objB) - end - end - - if M.size(objA)~=M.size(objB) then return false end - - local vB - for i,vA in pairs(objA) do - vB = objB[i] - if vB == nil or not M.isEqual(vA, vB, useMt) then return false end - end - - for i in pairs(objB) do - if objA[i] == nil then return false end - end - - return true -end - ---- Invokes an object method. It passes the object itself as the first argument. if `method` is not --- callable, will return `obj[method]`. --- @name result --- @param obj an object --- @param method a string key to index in object `obj`. --- @return the returned value of `method (obj)` call -function M.result(obj, method) - if obj[method] then - if M.isCallable(obj[method]) then - return obj[method](obj) - else return obj[method] - end - end - if M.isCallable(method) then - return method(obj) - end -end - ---- Checks if the given arg is a table. --- @name isTable --- @param t a value to be tested --- @return `true` or `false` -function M.isTable(t) - return type(t) == 'table' -end - ---- Checks if the given argument is callable. Assumes `obj` is callable if --- it is either a function or a table having a metatable implementing `__call` metamethod. --- @name isCallable --- @param obj an object --- @return `true` or `false` -function M.isCallable(obj) - return - ((type(obj) == 'function') or - ((type(obj) == 'table') and getmetatable(obj) and getmetatable(obj).__call~=nil) or - false) -end - ---- Checks if the given argument is an array. Assumes `obj` is an array --- if is a table with consecutive integer keys starting at 1. --- @name isArray --- @param obj an object --- @return `true` or `false` -function M.isArray(obj) - if not (type(obj) == 'table') then return false end - -- Thanks @Wojak and @Enrique García Cota for suggesting this - -- See : http://love2d.org/forums/viewtopic.php?f=3&t=77255&start=40#p163624 - local i = 0 - for k in pairs(obj) do - i = i + 1 - if obj[i] == nil then return false end - end - return true -end - ---- Checks if the given object is iterable with `pairs` (or `ipairs`). --- @name isIterable --- @param obj an object --- @return `true` if the object can be iterated with `pairs` (or `ipairs`), `false` otherwise -function M.isIterable(obj) - return M.toBoolean((pcall(pairs, obj))) -end - ---- Extends Lua's `type` function. It returns the type of the given object and also recognises --- file userdata --- @name type --- @param obj an object --- @return the given object type -function M.type(obj) - local tp = type(obj) - if tp == 'userdata' then - local mt = getmetatable(obj) - if mt == getmetatable(io.stdout) then - return 'file' - end - end - return tp -end - ---- Checks if the given pbject is empty. If `obj` is a string, will return `true` --- if `#obj == 0`. Otherwise, if `obj` is a table, will return whether or not this table --- is empty. If `obj` is `nil`, it will return true. --- @name isEmpty --- @param[opt] obj an object --- @return `true` or `false` -function M.isEmpty(obj) - if (obj == nil) then return true end - if type(obj) == 'string' then return #obj==0 end - if type(obj) == 'table' then return next(obj)==nil end - return true -end - ---- Checks if the given argument is a string. --- @name isString --- @param obj an object --- @return `true` or `false` -function M.isString(obj) - return type(obj) == 'string' -end - ---- Checks if the given argument is a function. --- @name isFunction --- @param obj an object --- @return `true` or `false` -function M.isFunction(obj) - return type(obj) == 'function' -end - ---- Checks if the given argument is nil. --- @name isNil --- @param obj an object --- @return `true` or `false` -function M.isNil(obj) - return obj==nil -end - ---- Checks if the given argument is a number. --- @name isNumber --- @param obj an object --- @return `true` or `false` --- @see isNaN -function M.isNumber(obj) - return type(obj) == 'number' -end - ---- Checks if the given argument is NaN (see [Not-A-Number](http://en.wikipedia.org/wiki/NaN)). --- @name isNaN --- @param obj an object --- @return `true` or `false` --- @see isNumber -function M.isNaN(obj) - return type(obj) == 'number' and obj~=obj -end - ---- Checks if the given argument is a finite number. --- @name isFinite --- @param obj an object --- @return `true` or `false` -function M.isFinite(obj) - if type(obj) ~= 'number' then return false end - return obj > -huge and obj < huge -end - ---- Checks if the given argument is a boolean. --- @name isBoolean --- @param obj an object --- @return `true` or `false` -function M.isBoolean(obj) - return type(obj) == 'boolean' -end - ---- Checks if the given argument is an integer. --- @name isInteger --- @param obj an object --- @return `true` or `false` -function M.isInteger(obj) - return type(obj) == 'number' and floor(obj)==obj -end - --- Aliases - -do - - -- Table functions aliases - M.forEach = M.each - M.forEachi = M.eachi - M.update = M.adjust - M.alleq = M.allEqual - M.loop = M.cycle - M.collect = M.map - M.inject = M.reduce - M.foldl = M.reduce - M.injectr = M.reduceRight - M.foldr = M.reduceRight - M.mapr = M.mapReduce - M.maprr = M.mapReduceRight - M.any = M.include - M.some = M.include - M.contains = M.include - M.filter = M.select - M.discard = M.reject - M.every = M.all - - -- Array functions aliases - M.takeWhile = M.selectWhile - M.rejectWhile = M.dropWhile - M.pop = M.shift - M.remove = M.pull - M.rmRange = M.removeRange - M.chop = M.removeRange - M.sub = M.slice - M.head = M.first - M.take = M.first - M.tail = M.rest - M.without = M.difference - M.diff = M.difference - M.symdiff = M.symmetricDifference - M.xor = M.symmetricDifference - M.uniq = M.unique - M.isuniq = M.isunique - M.transpose = M.zip - M.part = M.partition - M.perm = M.permutation - M.transposeWith = M.zipWith - M.intersperse = M.interpose - M.sliding = M.aperture - M.mirror = M.invert - M.join = M.concat - M.average = M.mean - - -- Utility functions aliases - M.always = M.constant - M.cache = M.memoize - M.juxt = M.juxtapose - M.uid = M.uniqueid - M.iter = M.iterator - M.nAry = M.ary - - -- Object functions aliases - M.methods = M.functions - M.choose = M.pick - M.drop = M.omit - M.defaults = M.template - M.compare = M.isEqual - M.matches = M.isEqual - -end - --- Setting chaining and building interface - -do - - -- Wrapper to Moses - local f = {} - - -- Will be returned upon requiring, indexes into the wrapper - local Moses = {} - Moses.__index = f - - -- Wraps a value into an instance, and returns the wrapped object - local function new(value) - return setmetatable({_value = value, _wrapped = true}, Moses) - end - - setmetatable(Moses,{ - __call = function(self,v) return new(v) end, -- Calls returns to instantiation - __index = function(t,key,...) return f[key] end -- Redirects to the wrapper - }) - - --- Returns a wrapped object. Calling library functions as methods on this object - -- will continue to return wrapped objects until @{obj:value} is used. Can be aliased as `M(value)`. - -- @class function - -- @name chain - -- @param value a value to be wrapped - -- @return a wrapped object - function Moses.chain(value) - return new(value) - end - - --- Extracts the value of a wrapped object. Must be called on an chained object (see @{chain}). - -- @class function - -- @name obj:value - -- @return the value previously wrapped - function Moses:value() - return self._value - end - - -- Register chaining methods into the wrapper - f.chain, f.value = Moses.chain, Moses.value - - -- Register all functions into the wrapper - for fname,fct in pairs(M) do - if fname ~= 'operator' then -- Prevents from wrapping op functions - f[fname] = function(v, ...) - local wrapped = type(v) == 'table' and rawget(v,'_wrapped') or false - if wrapped then - local _arg = v._value - local _rslt = fct(_arg,...) - return new(_rslt) - else - return fct(v,...) - end - end - end - end - - -- Exports all op functions - f.operator = M.operator - f.op = M.operator - - --- Imports all library functions into a context. - -- @name import - -- @param[opt] context a context. Defaults to `_ENV or `_G`` (current environment). - -- @param[optchain] noConflict if supplied, will not import conflicting functions in the destination context. - -- @return the passed-in context - f.import = function(context, noConflict) - context = context or _ENV or _G - local funcs = M.functions() - for k, fname in ipairs(funcs) do - if rawget(context, fname)~= nil then - if not noConflict then - rawset(context, fname, M[fname]) - end - else - rawset(context, fname, M[fname]) - end - end - return context - end - - -- Descriptive tags - Moses._VERSION = 'Moses v'.._MODULEVERSION - Moses._URL = 'http://github.com/Yonaba/Moses' - Moses._LICENSE = 'MIT ' - Moses._DESCRIPTION = 'utility-belt library for functional programming in Lua' - - return Moses - -end diff --git a/game/scripts/vscripts/pl/Date.lua b/game/scripts/vscripts/pl/Date.lua deleted file mode 100644 index 039dbaf..0000000 --- a/game/scripts/vscripts/pl/Date.lua +++ /dev/null @@ -1,675 +0,0 @@ ---- Date and Date Format classes. --- See @{05-dates.md|the Guide}. --- --- NOTE: the date module is deprecated! see --- https://github.com/lunarmodules/Penlight/issues/285 --- --- Dependencies: `pl.class`, `pl.stringx`, `pl.utils` --- @classmod pl.Date --- @pragma nostrip - -local class = require 'pl.class' -local os_time, os_date = os.time, os.date -local stringx = require 'pl.stringx' -local utils = require 'pl.utils' -local assert_arg,assert_string = utils.assert_arg,utils.assert_string - - -utils.raise_deprecation { - source = "Penlight " .. utils._VERSION, - message = "the 'Date' module is deprecated, see https://github.com/lunarmodules/Penlight/issues/285", - version_removed = "2.0.0", - version_deprecated = "1.9.2", -} - - -local Date = class() -Date.Format = class() - ---- Date constructor. --- @param t this can be either --- --- * `nil` or empty - use current date and time --- * number - seconds since epoch (as returned by `os.time`). Resulting time is UTC --- * `Date` - make a copy of this date --- * table - table containing year, month, etc as for `os.time`. You may leave out year, month or day, --- in which case current values will be used. --- * year (will be followed by month, day etc) --- --- @param ... true if Universal Coordinated Time, or two to five numbers: month,day,hour,min,sec --- @function Date -function Date:_init(t,...) - local time - local nargs = select('#',...) - if nargs > 2 then - local extra = {...} - local year = t - t = { - year = year, - month = extra[1], - day = extra[2], - hour = extra[3], - min = extra[4], - sec = extra[5] - } - end - if nargs == 1 then - self.utc = select(1,...) == true - end - if t == nil or t == 'utc' then - time = os_time() - self.utc = t == 'utc' - elseif type(t) == 'number' then - time = t - if self.utc == nil then self.utc = true end - elseif type(t) == 'table' then - if getmetatable(t) == Date then -- copy ctor - time = t.time - self.utc = t.utc - else - if not (t.year and t.month) then - local lt = os_date('*t') - if not t.year and not t.month and not t.day then - t.year = lt.year - t.month = lt.month - t.day = lt.day - else - t.year = t.year or lt.year - t.month = t.month or (t.day and lt.month or 1) - t.day = t.day or 1 - end - end - t.day = t.day or 1 - time = os_time(t) - end - else - error("bad type for Date constructor: "..type(t),2) - end - self:set(time) -end - ---- set the current time of this Date object. --- @int t seconds since epoch -function Date:set(t) - self.time = t - if self.utc then - self.tab = os_date('!*t',t) - else - self.tab = os_date('*t',t) - end -end - ---- get the time zone offset from UTC. --- @int ts seconds ahead of UTC -function Date.tzone (ts) - if ts == nil then - ts = os_time() - elseif type(ts) == "table" then - if getmetatable(ts) == Date then - ts = ts.time - else - ts = Date(ts).time - end - end - local utc = os_date('!*t',ts) - local lcl = os_date('*t',ts) - lcl.isdst = false - return os.difftime(os_time(lcl), os_time(utc)) -end - ---- convert this date to UTC. -function Date:toUTC () - local ndate = Date(self) - if not self.utc then - ndate.utc = true - ndate:set(ndate.time) - end - return ndate -end - ---- convert this UTC date to local. -function Date:toLocal () - local ndate = Date(self) - if self.utc then - ndate.utc = false - ndate:set(ndate.time) ---~ ndate:add { sec = Date.tzone(self) } - end - return ndate -end - ---- set the year. --- @int y Four-digit year --- @class function --- @name Date:year - ---- set the month. --- @int m month --- @class function --- @name Date:month - ---- set the day. --- @int d day --- @class function --- @name Date:day - ---- set the hour. --- @int h hour --- @class function --- @name Date:hour - ---- set the minutes. --- @int min minutes --- @class function --- @name Date:min - ---- set the seconds. --- @int sec seconds --- @class function --- @name Date:sec - ---- set the day of year. --- @class function --- @int yday day of year --- @name Date:yday - ---- get the year. --- @int y Four-digit year --- @class function --- @name Date:year - ---- get the month. --- @class function --- @name Date:month - ---- get the day. --- @class function --- @name Date:day - ---- get the hour. --- @class function --- @name Date:hour - ---- get the minutes. --- @class function --- @name Date:min - ---- get the seconds. --- @class function --- @name Date:sec - ---- get the day of year. --- @class function --- @name Date:yday - - -for _,c in ipairs{'year','month','day','hour','min','sec','yday'} do - Date[c] = function(self,val) - if val then - assert_arg(1,val,"number") - self.tab[c] = val - self:set(os_time(self.tab)) - return self - else - return self.tab[c] - end - end -end - ---- name of day of week. --- @bool full abbreviated if true, full otherwise. --- @ret string name -function Date:weekday_name(full) - return os_date(full and '%A' or '%a',self.time) -end - ---- name of month. --- @int full abbreviated if true, full otherwise. --- @ret string name -function Date:month_name(full) - return os_date(full and '%B' or '%b',self.time) -end - ---- is this day on a weekend?. -function Date:is_weekend() - return self.tab.wday == 1 or self.tab.wday == 7 -end - ---- add to a date object. --- @param t a table containing one of the following keys and a value: --- one of `year`,`month`,`day`,`hour`,`min`,`sec` --- @return this date -function Date:add(t) - local old_dst = self.tab.isdst - local key,val = next(t) - self.tab[key] = self.tab[key] + val - self:set(os_time(self.tab)) - if old_dst ~= self.tab.isdst then - self.tab.hour = self.tab.hour - (old_dst and 1 or -1) - self:set(os_time(self.tab)) - end - return self -end - ---- last day of the month. --- @return int day -function Date:last_day() - local d = 28 - local m = self.tab.month - while self.tab.month == m do - d = d + 1 - self:add{day=1} - end - self:add{day=-1} - return self -end - ---- difference between two Date objects. --- @tparam Date other Date object --- @treturn Date.Interval object -function Date:diff(other) - local dt = self.time - other.time - if dt < 0 then error("date difference is negative!",2) end - return Date.Interval(dt) -end - ---- long numerical ISO data format version of this date. -function Date:__tostring() - local fmt = '%Y-%m-%dT%H:%M:%S' - if self.utc then - fmt = "!"..fmt - end - local t = os_date(fmt,self.time) - if self.utc then - return t .. 'Z' - else - local offs = self:tzone() - if offs == 0 then - return t .. 'Z' - end - local sign = offs > 0 and '+' or '-' - local h = math.ceil(offs/3600) - local m = (offs % 3600)/60 - if m == 0 then - return t .. ('%s%02d'):format(sign,h) - else - return t .. ('%s%02d:%02d'):format(sign,h,m) - end - end -end - ---- equality between Date objects. -function Date:__eq(other) - return self.time == other.time -end - ---- ordering between Date objects. -function Date:__lt(other) - return self.time < other.time -end - ---- difference between Date objects. --- @function Date:__sub -Date.__sub = Date.diff - ---- add a date and an interval. --- @param other either a `Date.Interval` object or a table such as --- passed to `Date:add` -function Date:__add(other) - local nd = Date(self) - if Date.Interval:class_of(other) then - other = {sec=other.time} - end - nd:add(other) - return nd -end - -Date.Interval = class(Date) - ----- Date.Interval constructor --- @int t an interval in seconds --- @function Date.Interval -function Date.Interval:_init(t) - self:set(t) -end - -function Date.Interval:set(t) - self.time = t - self.tab = os_date('!*t',self.time) -end - -local function ess(n) - if n > 1 then return 's ' - else return ' ' - end -end - ---- If it's an interval then the format is '2 hours 29 sec' etc. -function Date.Interval:__tostring() - local t, res = self.tab, '' - local y,m,d = t.year - 1970, t.month - 1, t.day - 1 - if y > 0 then res = res .. y .. ' year'..ess(y) end - if m > 0 then res = res .. m .. ' month'..ess(m) end - if d > 0 then res = res .. d .. ' day'..ess(d) end - if y == 0 and m == 0 then - local h = t.hour - if h > 0 then res = res .. h .. ' hour'..ess(h) end - if t.min > 0 then res = res .. t.min .. ' min ' end - if t.sec > 0 then res = res .. t.sec .. ' sec ' end - end - if res == '' then res = 'zero' end - return res -end - ------------- Date.Format class: parsing and renderinig dates ------------ - --- short field names, explicit os.date names, and a mask for allowed field repeats -local formats = { - d = {'day',{true,true}}, - y = {'year',{false,true,false,true}}, - m = {'month',{true,true}}, - H = {'hour',{true,true}}, - M = {'min',{true,true}}, - S = {'sec',{true,true}}, -} - ---- Date.Format constructor. --- @string fmt. A string where the following fields are significant: --- --- * d day (either d or dd) --- * y year (either yy or yyy) --- * m month (either m or mm) --- * H hour (either H or HH) --- * M minute (either M or MM) --- * S second (either S or SS) --- --- Alternatively, if fmt is nil then this returns a flexible date parser --- that tries various date/time schemes in turn: --- --- * [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601), like `2010-05-10 12:35:23Z` or `2008-10-03T14:30+02` --- * times like 15:30 or 8.05pm (assumed to be today's date) --- * dates like 28/10/02 (European order!) or 5 Feb 2012 --- * month name like march or Mar (case-insensitive, first 3 letters); here the --- day will be 1 and the year this current year --- --- A date in format 3 can be optionally followed by a time in format 2. --- Please see test-date.lua in the tests folder for more examples. --- @usage df = Date.Format("yyyy-mm-dd HH:MM:SS") --- @class function --- @name Date.Format -function Date.Format:_init(fmt) - if not fmt then - self.fmt = '%Y-%m-%d %H:%M:%S' - self.outf = self.fmt - self.plain = true - return - end - local append = table.insert - local D,PLUS,OPENP,CLOSEP = '\001','\002','\003','\004' - local vars,used = {},{} - local patt,outf = {},{} - local i = 1 - while i < #fmt do - local ch = fmt:sub(i,i) - local df = formats[ch] - if df then - if used[ch] then error("field appeared twice: "..ch,4) end - used[ch] = true - -- this field may be repeated - local _,inext = fmt:find(ch..'+',i+1) - local cnt = not _ and 1 or inext-i+1 - if not df[2][cnt] then error("wrong number of fields: "..ch,4) end - -- single chars mean 'accept more than one digit' - local p = cnt==1 and (D..PLUS) or (D):rep(cnt) - append(patt,OPENP..p..CLOSEP) - append(vars,ch) - if ch == 'y' then - append(outf,cnt==2 and '%y' or '%Y') - else - append(outf,'%'..ch) - end - i = i + cnt - else - append(patt,ch) - append(outf,ch) - i = i + 1 - end - end - -- escape any magic characters - fmt = utils.escape(table.concat(patt)) - -- fmt = table.concat(patt):gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1') - -- replace markers with their magic equivalents - fmt = fmt:gsub(D,'%%d'):gsub(PLUS,'+'):gsub(OPENP,'('):gsub(CLOSEP,')') - self.fmt = fmt - self.outf = table.concat(outf) - self.vars = vars -end - -local parse_date - ---- parse a string into a Date object. --- @string str a date string --- @return date object -function Date.Format:parse(str) - assert_string(1,str) - if self.plain then - return parse_date(str,self.us) - end - local res = {str:match(self.fmt)} - if #res==0 then return nil, 'cannot parse '..str end - local tab = {} - for i,v in ipairs(self.vars) do - local name = formats[v][1] -- e.g. 'y' becomes 'year' - tab[name] = tonumber(res[i]) - end - -- os.date() requires these fields; if not present, we assume - -- that the time set is for the current day. - if not (tab.year and tab.month and tab.day) then - local today = Date() - tab.year = tab.year or today:year() - tab.month = tab.month or today:month() - tab.day = tab.day or today:day() - end - local Y = tab.year - if Y < 100 then -- classic Y2K pivot - tab.year = Y + (Y < 35 and 2000 or 1999) - elseif not Y then - tab.year = 1970 - end - return Date(tab) -end - ---- convert a Date object into a string. --- @param d a date object, or a time value as returned by @{os.time} --- @return string -function Date.Format:tostring(d) - local tm - local fmt = self.outf - if type(d) == 'number' then - tm = d - else - tm = d.time - if d.utc then - fmt = '!'..fmt - end - end - return os_date(fmt,tm) -end - ---- force US order in dates like 9/11/2001 -function Date.Format:US_order(yesno) - self.us = yesno -end - ---local months = {jan=1,feb=2,mar=3,apr=4,may=5,jun=6,jul=7,aug=8,sep=9,oct=10,nov=11,dec=12} -local months -local parse_date_unsafe -local function create_months() - local ld, day1 = parse_date_unsafe '2000-12-31', {day=1} - months = {} - for i = 1,12 do - ld = ld:last_day() - ld:add(day1) - local mon = ld:month_name():lower() - months [mon] = i - end -end - ---[[ -Allowed patterns: -- [day] [monthname] [year] [time] -- [day]/[month][/year] [time] - -]] - -local function looks_like_a_month(w) - return w:match '^%a+,*$' ~= nil -end -local is_number = stringx.isdigit -local function tonum(s,l1,l2,kind) - kind = kind or '' - local n = tonumber(s) - if not n then error(("%snot a number: '%s'"):format(kind,s)) end - if n < l1 or n > l2 then - error(("%s out of range: %s is not between %d and %d"):format(kind,s,l1,l2)) - end - return n -end - -local function parse_iso_end(p,ns,sec) - -- may be fractional part of seconds - local _,nfrac,secfrac = p:find('^%.%d+',ns+1) - if secfrac then - sec = sec .. secfrac - p = p:sub(nfrac+1) - else - p = p:sub(ns+1) - end - -- ISO 8601 dates may end in Z (for UTC) or [+-][isotime] - -- (we're working with the date as lower case, hence 'z') - if p:match 'z$' then -- we're UTC! - return sec, {h=0,m=0} - end - p = p:gsub(':','') -- turn 00:30 to 0030 - local _,_,sign,offs = p:find('^([%+%-])(%d+)') - if not sign then return sec, nil end -- not UTC - - if #offs == 2 then offs = offs .. '00' end -- 01 to 0100 - local tz = { h = tonumber(offs:sub(1,2)), m = tonumber(offs:sub(3,4)) } - if sign == '-' then tz.h = -tz.h; tz.m = -tz.m end - return sec, tz -end - -function parse_date_unsafe (s,US) - s = s:gsub('T',' ') -- ISO 8601 - local parts = stringx.split(s:lower()) - local i,p = 1,parts[1] - local function nextp() i = i + 1; p = parts[i] end - local year,min,hour,sec,apm - local tz - local _,nxt,day, month = p:find '^(%d+)/(%d+)' - if day then - -- swop for US case - if US then - day, month = month, day - end - _,_,year = p:find('^/(%d+)',nxt+1) - nextp() - else -- ISO - year,month,day = p:match('^(%d+)%-(%d+)%-(%d+)') - if year then - nextp() - end - end - if p and not year and is_number(p) then -- has to be date - if #p < 4 then - day = p - nextp() - else -- unless it looks like a 24-hour time - year = true - end - end - if p and looks_like_a_month(p) then -- date followed by month - p = p:sub(1,3) - if not months then - create_months() - end - local mon = months[p] - if mon then - month = mon - else error("not a month: " .. p) end - nextp() - end - if p and not year and is_number(p) then - year = p - nextp() - end - - if p then -- time is hh:mm[:ss], hhmm[ss] or H.M[am|pm] - _,nxt,hour,min = p:find '^(%d+):(%d+)' - local ns - if nxt then -- are there seconds? - _,ns,sec = p:find ('^:(%d+)',nxt+1) - --if ns then - sec,tz = parse_iso_end(p,ns or nxt,sec) - --end - else -- might be h.m - _,ns,hour,min = p:find '^(%d+)%.(%d+)' - if ns then - apm = p:match '[ap]m$' - else -- or hhmm[ss] - local hourmin - _,nxt,hourmin = p:find ('^(%d+)') - if nxt then - hour = hourmin:sub(1,2) - min = hourmin:sub(3,4) - sec = hourmin:sub(5,6) - if #sec == 0 then sec = nil end - sec,tz = parse_iso_end(p,nxt,sec) - end - end - end - end - local today - if year == true then year = nil end - if not (year and month and day) then - today = Date() - end - day = day and tonum(day,1,31,'day') or (month and 1 or today:day()) - month = month and tonum(month,1,12,'month') or today:month() - year = year and tonumber(year) or today:year() - if year < 100 then -- two-digit year pivot around year < 2035 - year = year + (year < 35 and 2000 or 1900) - end - hour = hour and tonum(hour,0,apm and 12 or 24,'hour') or 12 - if apm == 'pm' then - hour = hour + 12 - end - min = min and tonum(min,0,59) or 0 - sec = sec and tonum(sec,0,60) or 0 --60 used to indicate leap second - local res = Date {year = year, month = month, day = day, hour = hour, min = min, sec = sec} - if tz then -- ISO 8601 UTC time - local corrected = false - if tz.h ~= 0 then res:add {hour = -tz.h}; corrected = true end - if tz.m ~= 0 then res:add {min = -tz.m}; corrected = true end - res.utc = true - -- we're in UTC, so let's go local... - if corrected then - res = res:toLocal() - end-- we're UTC! - end - return res -end - -function parse_date (s) - local ok, d = pcall(parse_date_unsafe,s) - if not ok then -- error - d = d:gsub('.-:%d+: ','') - return nil, d - else - return d - end -end - -return Date - diff --git a/game/scripts/vscripts/pl/List.lua b/game/scripts/vscripts/pl/List.lua deleted file mode 100644 index b66c251..0000000 --- a/game/scripts/vscripts/pl/List.lua +++ /dev/null @@ -1,566 +0,0 @@ ---- Python-style list class. --- --- **Please Note**: methods that change the list will return the list. --- This is to allow for method chaining, but please note that `ls = ls:sort()` --- does not mean that a new copy of the list is made. In-place (mutable) methods --- are marked as returning 'the list' in this documentation. --- --- See the Guide for further @{02-arrays.md.Python_style_Lists|discussion} --- --- See http://www.python.org/doc/current/tut/tut.html, section 5.1 --- --- **Note**: The comments before some of the functions are from the Python docs --- and contain Python code. --- --- Written for Lua version Nick Trout 4.0; Redone for Lua 5.1, Steve Donovan. --- --- Dependencies: `pl.utils`, `pl.tablex`, `pl.class` --- @classmod pl.List --- @pragma nostrip - -local tinsert,tremove,concat,tsort = table.insert,table.remove,table.concat,table.sort -local setmetatable, getmetatable,type,tostring,string = setmetatable,getmetatable,type,tostring,string -local tablex = require 'pl.tablex' -local filter,imap,imap2,reduce,transform,tremovevalues = tablex.filter,tablex.imap,tablex.imap2,tablex.reduce,tablex.transform,tablex.removevalues -local tsub = tablex.sub -local utils = require 'pl.utils' -local class = require 'pl.class' - -local array_tostring,split,assert_arg,function_arg = utils.array_tostring,utils.split,utils.assert_arg,utils.function_arg -local normalize_slice = tablex._normalize_slice - --- metatable for our list and map objects has already been defined.. -local Multimap = utils.stdmt.MultiMap -local List = utils.stdmt.List - -local iter - -class(nil,nil,List) - --- we want the result to be _covariant_, i.e. t must have type of obj if possible -local function makelist (t,obj) - local klass = List - if obj then - klass = getmetatable(obj) - end - return setmetatable(t,klass) -end - -local function simple_table(t) - return type(t) == 'table' and not getmetatable(t) and #t > 0 -end - -function List._create (src) - if simple_table(src) then return src end -end - -function List:_init (src) - if self == src then return end -- existing table used as self! - if src then - for v in iter(src) do - tinsert(self,v) - end - end -end - ---- Create a new list. Can optionally pass a table; --- passing another instance of List will cause a copy to be created; --- this will return a plain table with an appropriate metatable. --- we pass anything which isn't a simple table to iterate() to work out --- an appropriate iterator --- @see List.iterate --- @param[opt] t An optional list-like table --- @return a new List --- @usage ls = List(); ls = List {1,2,3,4} --- @function List.new - -List.new = List - ---- Make a copy of an existing list. --- The difference from a plain 'copy constructor' is that this returns --- the actual List subtype. -function List:clone() - local ls = makelist({},self) - ls:extend(self) - return ls -end - ---- Add an item to the end of the list. --- @param i An item --- @return the list -function List:append(i) - tinsert(self,i) - return self -end - -List.push = tinsert - ---- Extend the list by appending all the items in the given list. --- equivalent to 'a[len(a):] = L'. --- @tparam List L Another List --- @return the list -function List:extend(L) - assert_arg(1,L,'table') - for i = 1,#L do tinsert(self,L[i]) end - return self -end - ---- Insert an item at a given position. i is the index of the --- element before which to insert. --- @int i index of element before whichh to insert --- @param x A data item --- @return the list -function List:insert(i, x) - assert_arg(1,i,'number') - tinsert(self,i,x) - return self -end - ---- Insert an item at the begining of the list. --- @param x a data item --- @return the list -function List:put (x) - return self:insert(1,x) -end - ---- Remove an element given its index. --- (equivalent of Python's del s[i]) --- @int i the index --- @return the list -function List:remove (i) - assert_arg(1,i,'number') - tremove(self,i) - return self -end - ---- Remove the first item from the list whose value is given. --- (This is called 'remove' in Python; renamed to avoid confusion --- with table.remove) --- Return nil if there is no such item. --- @param x A data value --- @return the list -function List:remove_value(x) - for i=1,#self do - if self[i]==x then tremove(self,i) return self end - end - return self - end - ---- Remove the item at the given position in the list, and return it. --- If no index is specified, a:pop() returns the last item in the list. --- The item is also removed from the list. --- @int[opt] i An index --- @return the item -function List:pop(i) - if not i then i = #self end - assert_arg(1,i,'number') - return tremove(self,i) -end - -List.get = List.pop - ---- Return the index in the list of the first item whose value is given. --- Return nil if there is no such item. --- @function List:index --- @param x A data value --- @int[opt=1] idx where to start search --- @return the index, or nil if not found. - -local tfind = tablex.find -List.index = tfind - ---- Does this list contain the value? --- @param x A data value --- @return true or false -function List:contains(x) - return tfind(self,x) and true or false -end - ---- Return the number of times value appears in the list. --- @param x A data value --- @return number of times x appears -function List:count(x) - local cnt=0 - for i=1,#self do - if self[i]==x then cnt=cnt+1 end - end - return cnt -end - ---- Sort the items of the list, in place. --- @func[opt='<'] cmp an optional comparison function --- @return the list -function List:sort(cmp) - if cmp then cmp = function_arg(1,cmp) end - tsort(self,cmp) - return self -end - ---- Return a sorted copy of this list. --- @func[opt='<'] cmp an optional comparison function --- @return a new list -function List:sorted(cmp) - return List(self):sort(cmp) -end - ---- Reverse the elements of the list, in place. --- @return the list -function List:reverse() - local t = self - local n = #t - for i = 1,n/2 do - t[i],t[n] = t[n],t[i] - n = n - 1 - end - return self -end - ---- Return the minimum and the maximum value of the list. --- @return minimum value --- @return maximum value -function List:minmax() - local vmin,vmax = 1e70,-1e70 - for i = 1,#self do - local v = self[i] - if v < vmin then vmin = v end - if v > vmax then vmax = v end - end - return vmin,vmax -end - ---- Emulate list slicing. like 'list[first:last]' in Python. --- If first or last are negative then they are relative to the end of the list --- eg. slice(-2) gives last 2 entries in a list, and --- slice(-4,-2) gives from -4th to -2nd --- @param first An index --- @param last An index --- @return a new List -function List:slice(first,last) - return tsub(self,first,last) -end - ---- Empty the list. --- @return the list -function List:clear() - for i=1,#self do tremove(self) end - return self -end - -local eps = 1.0e-10 - ---- Emulate Python's range(x) function. --- Include it in List table for tidiness --- @int start A number --- @int[opt] finish A number greater than start; if absent, --- then start is 1 and finish is start --- @int[opt=1] incr an increment (may be less than 1) --- @return a List from start .. finish --- @usage List.range(0,3) == List{0,1,2,3} --- @usage List.range(4) = List{1,2,3,4} --- @usage List.range(5,1,-1) == List{5,4,3,2,1} -function List.range(start,finish,incr) - if not finish then - finish = start - start = 1 - end - if incr then - assert_arg(3,incr,'number') - if math.ceil(incr) ~= incr then finish = finish + eps end - else - incr = 1 - end - assert_arg(1,start,'number') - assert_arg(2,finish,'number') - local t = List() - for i=start,finish,incr do tinsert(t,i) end - return t -end - ---- list:len() is the same as #list. -function List:len() - return #self -end - --- Extended operations -- - ---- Remove a subrange of elements. --- equivalent to 'del s[i1:i2]' in Python. --- @int i1 start of range --- @int i2 end of range --- @return the list -function List:chop(i1,i2) - return tremovevalues(self,i1,i2) -end - ---- Insert a sublist into a list --- equivalent to 's[idx:idx] = list' in Python --- @int idx index --- @tparam List list list to insert --- @return the list --- @usage l = List{10,20}; l:splice(2,{21,22}); assert(l == List{10,21,22,20}) -function List:splice(idx,list) - assert_arg(1,idx,'number') - idx = idx - 1 - local i = 1 - for v in iter(list) do - tinsert(self,i+idx,v) - i = i + 1 - end - return self -end - ---- General slice assignment s[i1:i2] = seq. --- @int i1 start index --- @int i2 end index --- @tparam List seq a list --- @return the list -function List:slice_assign(i1,i2,seq) - assert_arg(1,i1,'number') - assert_arg(1,i2,'number') - i1,i2 = normalize_slice(self,i1,i2) - if i2 >= i1 then self:chop(i1,i2) end - self:splice(i1,seq) - return self -end - ---- Concatenation operator. --- @within metamethods --- @tparam List L another List --- @return a new list consisting of the list with the elements of the new list appended -function List:__concat(L) - assert_arg(1,L,'table') - local ls = self:clone() - ls:extend(L) - return ls -end - ---- Equality operator ==. True iff all elements of two lists are equal. --- @within metamethods --- @tparam List L another List --- @return true or false -function List:__eq(L) - if #self ~= #L then return false end - for i = 1,#self do - if self[i] ~= L[i] then return false end - end - return true -end - ---- Join the elements of a list using a delimiter. --- This method uses tostring on all elements. --- @string[opt=''] delim a delimiter string, can be empty. --- @return a string -function List:join (delim) - delim = delim or '' - assert_arg(1,delim,'string') - return concat(array_tostring(self),delim) -end - ---- Join a list of strings.
--- Uses `table.concat` directly. --- @function List:concat --- @string[opt=''] delim a delimiter --- @return a string -List.concat = concat - -local function tostring_q(val) - local s = tostring(val) - if type(val) == 'string' then - s = '"'..s..'"' - end - return s -end - ---- How our list should be rendered as a string. Uses join(). --- @within metamethods --- @see List:join -function List:__tostring() - return '{'..self:join(',',tostring_q)..'}' -end - ---- Call the function on each element of the list. --- @func fun a function or callable object --- @param ... optional values to pass to function -function List:foreach (fun,...) - fun = function_arg(1,fun) - for i = 1,#self do - fun(self[i],...) - end -end - -local function lookup_fun (obj,name) - local f = obj[name] - if not f then error(type(obj).." does not have method "..name,3) end - return f -end - ---- Call the named method on each element of the list. --- @string name the method name --- @param ... optional values to pass to function -function List:foreachm (name,...) - for i = 1,#self do - local obj = self[i] - local f = lookup_fun(obj,name) - f(obj,...) - end -end - ---- Create a list of all elements which match a function. --- @func fun a boolean function --- @param[opt] arg optional argument to be passed as second argument of the predicate --- @return a new filtered list. -function List:filter (fun,arg) - return makelist(filter(self,fun,arg),self) -end - ---- Split a string using a delimiter. --- @string s the string --- @string[opt] delim the delimiter (default spaces) --- @return a List of strings --- @see pl.utils.split -function List.split (s,delim) - assert_arg(1,s,'string') - return makelist(split(s,delim)) -end - ---- Apply a function to all elements. --- Any extra arguments will be passed to the function. --- @func fun a function of at least one argument --- @param ... arbitrary extra arguments. --- @return a new list: {f(x) for x in self} --- @usage List{'one','two'}:map(string.upper) == {'ONE','TWO'} --- @see pl.tablex.imap -function List:map (fun,...) - return makelist(imap(fun,self,...),self) -end - ---- Apply a function to all elements, in-place. --- Any extra arguments are passed to the function. --- @func fun A function that takes at least one argument --- @param ... arbitrary extra arguments. --- @return the list. -function List:transform (fun,...) - transform(fun,self,...) - return self -end - ---- Apply a function to elements of two lists. --- Any extra arguments will be passed to the function --- @func fun a function of at least two arguments --- @tparam List ls another list --- @param ... arbitrary extra arguments. --- @return a new list: {f(x,y) for x in self, for x in arg1} --- @see pl.tablex.imap2 -function List:map2 (fun,ls,...) - return makelist(imap2(fun,self,ls,...),self) -end - ---- apply a named method to all elements. --- Any extra arguments will be passed to the method. --- @string name name of method --- @param ... extra arguments --- @return a new list of the results --- @see pl.seq.mapmethod -function List:mapm (name,...) - local res = {} - for i = 1,#self do - local val = self[i] - local fn = lookup_fun(val,name) - res[i] = fn(val,...) - end - return makelist(res,self) -end - -local function composite_call (method,f) - return function(self,...) - return self[method](self,f,...) - end -end - -function List.default_map_with(T) - return function(self,name) - local m - if T then - local f = lookup_fun(T,name) - m = composite_call('map',f) - else - m = composite_call('mapn',name) - end - getmetatable(self)[name] = m -- and cache.. - return m - end -end - -List.default_map = List.default_map_with - ---- 'reduce' a list using a binary function. --- @func fun a function of two arguments --- @return result of the function --- @see pl.tablex.reduce -function List:reduce (fun) - return reduce(fun,self) -end - ---- Partition a list using a classifier function. --- The function may return nil, but this will be converted to the string key ''. --- @func fun a function of at least one argument --- @param ... will also be passed to the function --- @treturn MultiMap a table where the keys are the returned values, and the values are Lists --- of values where the function returned that key. --- @see pl.MultiMap -function List:partition (fun,...) - fun = function_arg(1,fun) - local res = {} - for i = 1,#self do - local val = self[i] - local klass = fun(val,...) - if klass == nil then klass = '' end - if not res[klass] then res[klass] = List() end - res[klass]:append(val) - end - return setmetatable(res,Multimap) -end - ---- return an iterator over all values. -function List:iter () - return iter(self) -end - ---- Create an iterator over a seqence. --- This captures the Python concept of 'sequence'. --- For tables, iterates over all values with integer indices. --- @param seq a sequence; a string (over characters), a table, a file object (over lines) or an iterator function --- @usage for x in iterate {1,10,22,55} do io.write(x,',') end ==> 1,10,22,55 --- @usage for ch in iterate 'help' do do io.write(ch,' ') end ==> h e l p -function List.iterate(seq) - if type(seq) == 'string' then - local idx = 0 - local n = #seq - local sub = string.sub - return function () - idx = idx + 1 - if idx > n then return nil - else - return sub(seq,idx,idx) - end - end - elseif type(seq) == 'table' then - local idx = 0 - local n = #seq - return function() - idx = idx + 1 - if idx > n then return nil - else - return seq[idx] - end - end - elseif type(seq) == 'function' then - return seq - elseif type(seq) == 'userdata' and io.type(seq) == 'file' then - return seq:lines() - end -end -iter = List.iterate - -return List - diff --git a/game/scripts/vscripts/pl/Map.lua b/game/scripts/vscripts/pl/Map.lua deleted file mode 100644 index 572b22a..0000000 --- a/game/scripts/vscripts/pl/Map.lua +++ /dev/null @@ -1,120 +0,0 @@ ---- A Map class. --- --- > Map = require 'pl.Map' --- > m = Map{one=1,two=2} --- > m:update {three=3,four=4,two=20} --- > = m == M{one=1,two=20,three=3,four=4} --- true --- --- Dependencies: `pl.utils`, `pl.class`, `pl.tablex`, `pl.pretty` --- @classmod pl.Map - -local tablex = require 'pl.tablex' -local utils = require 'pl.utils' -local stdmt = utils.stdmt -local deepcompare = tablex.deepcompare - -local pretty_write = require 'pl.pretty' . write -local Map = stdmt.Map -local Set = stdmt.Set - -local class = require 'pl.class' - --- the Map class --------------------- -class(nil,nil,Map) - -function Map:_init (t) - local mt = getmetatable(t) - if mt == Set or mt == Map then - self:update(t) - else - return t -- otherwise assumed to be a map-like table - end -end - - -local function makelist(t) - return setmetatable(t, require('pl.List')) -end - ---- list of keys. -Map.keys = tablex.keys - ---- list of values. -Map.values = tablex.values - ---- return an iterator over all key-value pairs. -function Map:iter () - return pairs(self) -end - ---- return a List of all key-value pairs, sorted by the keys. -function Map:items() - local ls = makelist(tablex.pairmap (function (k,v) return makelist {k,v} end, self)) - ls:sort(function(t1,t2) return t1[1] < t2[1] end) - return ls -end - ---- set a value in the map if it doesn't exist yet. --- @param key the key --- @param default value to set --- @return the value stored in the map (existing value, or the new value) -function Map:setdefault(key, default) - local val = self[key] - if val ~= nil then - return val - end - self:set(key,default) - return default -end - ---- size of map. --- note: this is a relatively expensive operation! --- @class function --- @name Map:len -Map.len = tablex.size - ---- put a value into the map. --- This will remove the key if the value is `nil` --- @param key the key --- @param val the value -function Map:set (key,val) - self[key] = val -end - ---- get a value from the map. --- @param key the key --- @return the value, or nil if not found. -function Map:get (key) - return rawget(self,key) -end - -local index_by = tablex.index_by - ---- get a list of values indexed by a list of keys. --- @param keys a list-like table of keys --- @return a new list -function Map:getvalues (keys) - return makelist(index_by(self,keys)) -end - ---- update the map using key/value pairs from another table. --- @tab table --- @function Map:update -Map.update = tablex.update - ---- equality between maps. --- @within metamethods --- @tparam Map m another map. -function Map:__eq (m) - -- note we explicitly ask deepcompare _not_ to use __eq! - return deepcompare(self,m,true) -end - ---- string representation of a map. --- @within metamethods -function Map:__tostring () - return pretty_write(self,'') -end - -return Map diff --git a/game/scripts/vscripts/pl/MultiMap.lua b/game/scripts/vscripts/pl/MultiMap.lua deleted file mode 100644 index 0abe84d..0000000 --- a/game/scripts/vscripts/pl/MultiMap.lua +++ /dev/null @@ -1,54 +0,0 @@ ---- MultiMap, a Map which has multiple values per key. --- --- Dependencies: `pl.utils`, `pl.class`, `pl.List`, `pl.Map` --- @classmod pl.MultiMap - -local utils = require 'pl.utils' -local class = require 'pl.class' -local List = require 'pl.List' -local Map = require 'pl.Map' - --- MultiMap is a standard MT -local MultiMap = utils.stdmt.MultiMap - -class(Map,nil,MultiMap) -MultiMap._name = 'MultiMap' - -function MultiMap:_init (t) - if not t then return end - self:update(t) -end - ---- update a MultiMap using a table. --- @param t either a Multimap or a map-like table. --- @return the map -function MultiMap:update (t) - utils.assert_arg(1,t,'table') - if Map:class_of(t) then - for k,v in pairs(t) do - self[k] = List() - self[k]:append(v) - end - else - for k,v in pairs(t) do - self[k] = List(v) - end - end -end - ---- add a new value to a key. Setting a nil value removes the key. --- @param key the key --- @param val the value --- @return the map -function MultiMap:set (key,val) - if val == nil then - self[key] = nil - else - if not self[key] then - self[key] = List() - end - self[key]:append(val) - end -end - -return MultiMap diff --git a/game/scripts/vscripts/pl/OrderedMap.lua b/game/scripts/vscripts/pl/OrderedMap.lua deleted file mode 100644 index 379c44f..0000000 --- a/game/scripts/vscripts/pl/OrderedMap.lua +++ /dev/null @@ -1,167 +0,0 @@ ---- OrderedMap, a map which preserves ordering. --- --- Derived from `pl.Map`. --- --- Dependencies: `pl.utils`, `pl.tablex`, `pl.class`, `pl.List`, `pl.Map` --- @classmod pl.OrderedMap - -local tablex = require 'pl.tablex' -local utils = require 'pl.utils' -local List = require 'pl.List' -local index_by,tsort,concat = tablex.index_by,table.sort,table.concat - -local class = require 'pl.class' -local Map = require 'pl.Map' - -local OrderedMap = class(Map) -OrderedMap._name = 'OrderedMap' - -local rawset = rawset - ---- construct an OrderedMap. --- Will throw an error if the argument is bad. --- @param t optional initialization table, same as for @{OrderedMap:update} -function OrderedMap:_init (t) - rawset(self,'_keys',List()) - if t then - local map,err = self:update(t) - if not map then error(err,2) end - end -end - -local assert_arg,raise = utils.assert_arg,utils.raise - ---- update an OrderedMap using a table. --- If the table is itself an OrderedMap, then its entries will be appended. --- if it s a table of the form `{{key1=val1},{key2=val2},...}` these will be appended. --- --- Otherwise, it is assumed to be a map-like table, and order of extra entries is arbitrary. --- @tab t a table. --- @return the map, or nil in case of error --- @return the error message -function OrderedMap:update (t) - assert_arg(1,t,'table') - if OrderedMap:class_of(t) then - for k,v in t:iter() do - self:set(k,v) - end - elseif #t > 0 then -- an array must contain {key=val} tables - if type(t[1]) == 'table' then - for _,pair in ipairs(t) do - local key,value = next(pair) - if not key then return raise 'empty pair initialization table' end - self:set(key,value) - end - else - return raise 'cannot use an array to initialize an OrderedMap' - end - else - for k,v in pairs(t) do - self:set(k,v) - end - end - return self -end - ---- set the key's value. This key will be appended at the end of the map. --- --- If the value is nil, then the key is removed. --- @param key the key --- @param val the value --- @return the map -function OrderedMap:set (key,val) - if rawget(self, key) == nil and val ~= nil then -- new key - self._keys:append(key) -- we keep in order - rawset(self,key,val) -- don't want to provoke __newindex! - else -- existing key-value pair - if val == nil then - self._keys:remove_value(key) - rawset(self,key,nil) - else - self[key] = val - end - end - return self -end - -OrderedMap.__newindex = OrderedMap.set - ---- insert a key/value pair before a given position. --- Note: if the map already contains the key, then this effectively --- moves the item to the new position by first removing at the old position. --- Has no effect if the key does not exist and val is nil --- @int pos a position starting at 1 --- @param key the key --- @param val the value; if nil use the old value -function OrderedMap:insert (pos,key,val) - local oldval = self[key] - val = val or oldval - if oldval then - self._keys:remove_value(key) - end - if val then - self._keys:insert(pos,key) - rawset(self,key,val) - end - return self -end - ---- return the keys in order. --- (Not a copy!) --- @return List -function OrderedMap:keys () - return self._keys -end - ---- return the values in order. --- this is relatively expensive. --- @return List -function OrderedMap:values () - return List(index_by(self,self._keys)) -end - ---- sort the keys. --- @func cmp a comparison function as for @{table.sort} --- @return the map -function OrderedMap:sort (cmp) - tsort(self._keys,cmp) - return self -end - ---- iterate over key-value pairs in order. -function OrderedMap:iter () - local i = 0 - local keys = self._keys - local idx - return function() - i = i + 1 - if i > #keys then return nil end - idx = keys[i] - return idx,self[idx] - end -end - ---- iterate over an ordered map (5.2). --- @within metamethods --- @function OrderedMap:__pairs -OrderedMap.__pairs = OrderedMap.iter - ---- string representation of an ordered map. --- @within metamethods -function OrderedMap:__tostring () - local res = {} - for i,v in ipairs(self._keys) do - local val = self[v] - local vs = tostring(val) - if type(val) ~= 'number' then - vs = '"'..vs..'"' - end - res[i] = tostring(v)..'='..vs - end - return '{'..concat(res,',')..'}' -end - -return OrderedMap - - - diff --git a/game/scripts/vscripts/pl/Set.lua b/game/scripts/vscripts/pl/Set.lua deleted file mode 100644 index ce428f0..0000000 --- a/game/scripts/vscripts/pl/Set.lua +++ /dev/null @@ -1,222 +0,0 @@ ---- A Set class. --- --- > Set = require 'pl.Set' --- > = Set{'one','two'} == Set{'two','one'} --- true --- > fruit = Set{'apple','banana','orange'} --- > = fruit['banana'] --- true --- > = fruit['hazelnut'] --- nil --- > colours = Set{'red','orange','green','blue'} --- > = fruit,colours --- [apple,orange,banana] [blue,green,orange,red] --- > = fruit+colours --- [blue,green,apple,red,orange,banana] --- [orange] --- > more_fruits = fruit + 'apricot' --- > = fruit*colours --- > = more_fruits, fruit --- [banana,apricot,apple,orange] [banana,apple,orange] --- --- Dependencies: `pl.utils`, `pl.tablex`, `pl.class`, `pl.Map`, (`pl.List` if __tostring is used) --- @classmod pl.Set - -local tablex = require 'pl.tablex' -local utils = require 'pl.utils' -local array_tostring, concat = utils.array_tostring, table.concat -local merge,difference = tablex.merge,tablex.difference -local Map = require 'pl.Map' -local class = require 'pl.class' -local stdmt = utils.stdmt -local Set = stdmt.Set - --- the Set class -------------------- -class(Map,nil,Set) - --- note: Set has _no_ methods! -Set.__index = nil - -local function makeset (t) - return setmetatable(t,Set) -end - ---- create a set.
--- @param t may be a Set, Map or list-like table. --- @class function --- @name Set -function Set:_init (t) - t = t or {} - local mt = getmetatable(t) - if mt == Set or mt == Map then - for k in pairs(t) do self[k] = true end - else - for _,v in ipairs(t) do self[v] = true end - end -end - ---- string representation of a set. --- @within metamethods -function Set:__tostring () - return '['..concat(array_tostring(Set.values(self)),',')..']' -end - ---- get a list of the values in a set. --- @param self a Set --- @function Set.values --- @return a list -Set.values = Map.keys - ---- map a function over the values of a set. --- @param self a Set --- @param fn a function --- @param ... extra arguments to pass to the function. --- @return a new set -function Set.map (self,fn,...) - fn = utils.function_arg(1,fn) - local res = {} - for k in pairs(self) do - res[fn(k,...)] = true - end - return makeset(res) -end - ---- union of two sets (also +). --- @param self a Set --- @param set another set --- @return a new set -function Set.union (self,set) - return merge(self,set,true) -end - ---- modifies '+' operator to allow addition of non-Set elements ---- Preserves +/- semantics - does not modify first argument. -local function setadd(self,other) - local mt = getmetatable(other) - if mt == Set or mt == Map then - return Set.union(self,other) - else - local new = Set(self) - new[other] = true - return new - end -end - ---- union of sets. --- @within metamethods --- @function Set.__add - -Set.__add = setadd - ---- intersection of two sets (also *). --- @param self a Set --- @param set another set --- @return a new set --- @usage --- > s = Set{10,20,30} --- > t = Set{20,30,40} --- > = t --- [20,30,40] --- > = Set.intersection(s,t) --- [30,20] --- > = s*t --- [30,20] - -function Set.intersection (self,set) - return merge(self,set,false) -end - ---- intersection of sets. --- @within metamethods --- @function Set.__mul -Set.__mul = Set.intersection - ---- new set with elements in the set that are not in the other (also -). --- @param self a Set --- @param set another set --- @return a new set -function Set.difference (self,set) - return difference(self,set,false) -end - ---- modifies "-" operator to remove non-Set values from set. ---- Preserves +/- semantics - does not modify first argument. -local function setminus (self,other) - local mt = getmetatable(other) - if mt == Set or mt == Map then - return Set.difference(self,other) - else - local new = Set(self) - new[other] = nil - return new - end -end - ---- difference of sets. --- @within metamethods --- @function Set.__sub -Set.__sub = setminus - --- a new set with elements in _either_ the set _or_ other but not both (also ^). --- @param self a Set --- @param set another set --- @return a new set -function Set.symmetric_difference (self,set) - return difference(self,set,true) -end - ---- symmetric difference of sets. --- @within metamethods --- @function Set.__pow -Set.__pow = Set.symmetric_difference - ---- is the first set a subset of the second (also <)?. --- @param self a Set --- @param set another set --- @return true or false -function Set.issubset (self,set) - for k in pairs(self) do - if not set[k] then return false end - end - return true -end - ---- first set subset of second? --- @within metamethods --- @function Set.__lt -Set.__lt = Set.issubset - ---- is the set empty?. --- @param self a Set --- @return true or false -function Set.isempty (self) - return next(self) == nil -end - ---- are the sets disjoint? (no elements in common). --- Uses naive definition, i.e. that intersection is empty --- @param s1 a Set --- @param s2 another set --- @return true or false -function Set.isdisjoint (s1,s2) - return Set.isempty(Set.intersection(s1,s2)) -end - ---- size of this set (also # for 5.2). --- @param s a Set --- @return size --- @function Set.len -Set.len = tablex.size - ---- cardinality of set (5.2). --- @within metamethods --- @function Set.__len -Set.__len = Set.len - ---- equality between sets. --- @within metamethods -function Set.__eq (s1,s2) - return Set.issubset(s1,s2) and Set.issubset(s2,s1) -end - -return Set diff --git a/game/scripts/vscripts/pl/app.lua b/game/scripts/vscripts/pl/app.lua deleted file mode 100644 index 28f839e..0000000 --- a/game/scripts/vscripts/pl/app.lua +++ /dev/null @@ -1,309 +0,0 @@ ---- Application support functions. --- See @{01-introduction.md.Application_Support|the Guide} --- --- Dependencies: `pl.utils`, `pl.path` --- @module pl.app - -local io,package,require = _G.io, _G.package, _G.require -local utils = require 'pl.utils' -local path = require 'pl.path' - -local app = {} - ---- return the name of the current script running. --- The name will be the name as passed on the command line --- @return string filename -function app.script_name() - if _G.arg and _G.arg[0] then - return _G.arg[0] - end - return utils.raise("No script name found") -end - ---- prefixes the current script's path to the Lua module path. --- Applies to both the source and the binary module paths. It makes it easy for --- the main file of a multi-file program to access its modules in the same directory. --- `base` allows these modules to be put in a specified subdirectory, to allow for --- cleaner deployment and resolve potential conflicts between a script name and its --- library directory. --- --- Note: the path is prefixed, so it is searched first when requiring modules. --- @string base optional base directory (absolute, or relative path). --- @bool nofollow always use the invocation's directory, even if the invoked file is a symlink --- @treturn string the current script's path with a trailing slash -function app.require_here (base, nofollow) - local p = app.script_name() - if not path.isabs(p) then - p = path.join(path.currentdir(),p) - end - if not nofollow then - local t = path.link_attrib(p) - if t and t.mode == 'link' then - t = t.target - if not path.isabs(t) then - t = path.join(path.dirname(p), t) - end - p = t - end - end - p = path.normpath(path.dirname(p)) - if p:sub(-1,-1) ~= path.sep then - p = p..path.sep - end - if base then - if path.is_windows then - base = base:gsub('/','\\') - end - if path.isabs(base) then - p = base .. path.sep - else - p = p..base..path.sep - end - end - local so_ext = path.is_windows and 'dll' or 'so' - local lsep = package.path:find '^;' and '' or ';' - local csep = package.cpath:find '^;' and '' or ';' - package.path = ('%s?.lua;%s?%sinit.lua%s%s'):format(p,p,path.sep,lsep,package.path) - package.cpath = ('%s?.%s%s%s'):format(p,so_ext,csep,package.cpath) - return p -end - ---- return a suitable path for files private to this application. --- These will look like '~/.SNAME/file', with '~' as with expanduser and --- SNAME is the name of the script without .lua extension. --- If the directory does not exist, it will be created. --- @string file a filename (w/out path) --- @return a full pathname, or nil --- @return cannot create directory error --- @usage --- -- when run from a script called 'testapp' (on Windows): --- local app = require 'pl.app' --- print(app.appfile 'test.txt') --- -- C:\Documents and Settings\steve\.testapp\test.txt -function app.appfile(file) - local sfullname, err = app.script_name() - if not sfullname then return utils.raise(err) end - local sname = path.basename(sfullname) - local name = path.splitext(sname) - local dir = path.join(path.expanduser('~'),'.'..name) - if not path.isdir(dir) then - local ret = path.mkdir(dir) - if not ret then return utils.raise('cannot create '..dir) end - end - return path.join(dir,file) -end - ---- return string indicating operating system. --- @return 'Windows','OSX' or whatever uname returns (e.g. 'Linux') -function app.platform() - if path.is_windows then - return 'Windows' - else - local f = io.popen('uname') - local res = f:read() - if res == 'Darwin' then res = 'OSX' end - f:close() - return res - end -end - ---- return the full command-line used to invoke this script. --- It will not include the scriptname itself, see `app.script_name`. --- @return command-line --- @return name of Lua program used --- @usage --- -- execute: lua -lluacov -e 'print(_VERSION)' myscript.lua --- --- -- myscript.lua --- print(require("pl.app").lua()) --> "lua -lluacov -e 'print(_VERSION)'", "lua" -function app.lua() - local args = _G.arg - if not args then - return utils.raise "not in a main program" - end - - local cmd = {} - local i = -1 - while true do - table.insert(cmd, 1, args[i]) - if not args[i-1] then - return utils.quote_arg(cmd), args[i] - end - i = i - 1 - end -end - ---- parse command-line arguments into flags and parameters. --- Understands GNU-style command-line flags; short (`-f`) and long (`--flag`). --- --- These may be given a value with either '=' or ':' (`-k:2`,`--alpha=3.2`,`-n2`), --- a number value can be given without a space. If the flag is marked --- as having a value, then a space-separated value is also accepted (`-i hello`), --- see the `flags_with_values` argument). --- --- Multiple short args can be combined like so: ( `-abcd`). --- --- When specifying the `flags_valid` parameter, its contents can also contain --- aliasses, to convert short/long flags to the same output name. See the --- example below. --- --- Note: if a flag is repeated, the last value wins. --- @tparam {string} args an array of strings (default is the global `arg`) --- @tab flags_with_values any flags that take values, either list or hash --- table e.g. `{ out=true }` or `{ "out" }`. --- @tab flags_valid (optional) flags that are valid, either list or hashtable. --- If not given, everything --- will be accepted(everything in `flags_with_values` will automatically be allowed) --- @return a table of flags (flag=value pairs) --- @return an array of parameters --- @raise if args is nil, then the global `args` must be available! --- @usage --- -- Simple form: --- local flags, params = app.parse_args(nil, --- { "hello", "world" }, -- list of flags taking values --- { "l", "a", "b"}) -- list of allowed flags (value ones will be added) --- --- -- More complex example using aliasses: --- local valid = { --- long = "l", -- if 'l' is specified, it is reported as 'long' --- new = { "n", "old" }, -- here both 'n' and 'old' will go into 'new' --- } --- local values = { --- "value", -- will automatically be added to the allowed set of flags --- "new", -- will mark 'n' and 'old' as requiring a value as well --- } --- local flags, params = app.parse_args(nil, values, valid) --- --- -- command: myapp.lua -l --old:hello --value world param1 param2 --- -- will yield: --- flags = { --- long = true, -- input from 'l' --- new = "hello", -- input from 'old' --- value = "world", -- allowed because it was in 'values', note: space separated! --- } --- params = { --- [1] = "param1" --- [2] = "param2" --- } -function app.parse_args (args,flags_with_values, flags_valid) - if not args then - args = _G.arg - if not args then utils.raise "Not in a main program: 'arg' not found" end - end - - local with_values = {} - for k,v in pairs(flags_with_values or {}) do - if type(k) == "number" then - k = v - end - with_values[k] = true - end - - local valid - if not flags_valid then - -- if no allowed flags provided, we create a table that always returns - -- the keyname, no matter what you look up - valid = setmetatable({},{ __index = function(_, key) return key end }) - else - valid = {} - for k,aliasses in pairs(flags_valid) do - if type(k) == "number" then -- array/list entry - k = aliasses - end - if type(aliasses) == "string" then -- single alias - aliasses = { aliasses } - end - if type(aliasses) == "table" then -- list of aliasses - -- it's the alternate name, so add the proper mappings - for i, alias in ipairs(aliasses) do - valid[alias] = k - end - end - valid[k] = k - end - do - local new_with_values = {} -- needed to prevent "invalid key to 'next'" error - for k,v in pairs(with_values) do - if not valid[k] then - valid[k] = k -- add the with_value entry as a valid one - new_with_values[k] = true - else - new_with_values[valid[k]] = true --set, but by its alias - end - end - with_values = new_with_values - end - end - - -- now check that all flags with values are reported as such under all - -- of their aliasses - for k, main_alias in pairs(valid) do - if with_values[main_alias] then - with_values[k] = true - end - end - - local _args = {} - local flags = {} - local i = 1 - while i <= #args do - local a = args[i] - local v = a:match('^-(.+)') - local is_long - if not v then - -- we have a parameter - _args[#_args+1] = a - else - -- it's a flag - if v:find '^-' then - is_long = true - v = v:sub(2) - end - if with_values[v] then - if i == #args or args[i+1]:find '^-' then - return utils.raise ("no value for '"..v.."'") - end - flags[valid[v]] = args[i+1] - i = i + 1 - else - -- a value can also be indicated with = or : - local var,val = utils.splitv (v,'[=:]', false, 2) - var = var or v - val = val or true - if not is_long then - if #var > 1 then - if var:find '.%d+' then -- short flag, number value - val = var:sub(2) - var = var:sub(1,1) - else -- multiple short flags - for i = 1,#var do - local f = var:sub(i,i) - if not valid[f] then - return utils.raise("unknown flag '"..f.."'") - else - f = valid[f] - end - flags[f] = true - end - val = nil -- prevents use of var as a flag below - end - else -- single short flag (can have value, defaults to true) - val = val or true - end - end - if val then - if not valid[var] then - return utils.raise("unknown flag '"..var.."'") - else - var = valid[var] - end - flags[var] = val - end - end - end - i = i + 1 - end - return flags,_args -end - -return app diff --git a/game/scripts/vscripts/pl/array2d.lua b/game/scripts/vscripts/pl/array2d.lua deleted file mode 100644 index 6e884d1..0000000 --- a/game/scripts/vscripts/pl/array2d.lua +++ /dev/null @@ -1,585 +0,0 @@ ---- Operations on two-dimensional arrays. --- See @{02-arrays.md.Operations_on_two_dimensional_tables|The Guide} --- --- The size of the arrays is determined by using the length operator `#` hence --- the module is not `nil` safe, and the usual precautions apply. --- --- Note: all functions taking `i1,j1,i2,j2` as arguments will normalize the --- arguments using `default_range`. --- --- Dependencies: `pl.utils`, `pl.tablex`, `pl.types` --- @module pl.array2d - -local tonumber,tostring,io,ipairs,string,table = - _G.tonumber,_G.tostring,_G.io,_G.ipairs,_G.string,_G.table -local setmetatable,getmetatable = setmetatable,getmetatable - -local tablex = require 'pl.tablex' -local utils = require 'pl.utils' -local types = require 'pl.types' -local imap,tmap,reduce,keys,tmap2,tset,index_by = tablex.imap,tablex.map,tablex.reduce,tablex.keys,tablex.map2,tablex.set,tablex.index_by -local remove = table.remove -local splitv,fprintf,assert_arg = utils.splitv,utils.fprintf,utils.assert_arg -local byte = string.byte -local stdout = io.stdout -local min = math.min - - -local array2d = {} - -local function obj (int,out) - local mt = getmetatable(int) - if mt then - setmetatable(out,mt) - end - return out -end - -local function makelist (res) - return setmetatable(res, require('pl.List')) -end - ---- return the row and column size. --- Size is calculated using the Lua length operator #, so usual precautions --- regarding `nil` values apply. --- @array2d a a 2d array --- @treturn int number of rows (`#a`) --- @treturn int number of cols (`#a[1]`) -function array2d.size (a) - assert_arg(1,a,'table') - return #a,#a[1] -end - -do - local function index (t,k) - return t[k] - end - - --- extract a column from the 2D array. - -- @array2d a 2d array - -- @param j column index - -- @return 1d array - function array2d.column (a,j) - assert_arg(1,a,'table') - return makelist(imap(index,a,j)) - end -end -local column = array2d.column - ---- extract a row from the 2D array. --- Added in line with `column`, for read-only purposes directly --- accessing a[i] is more performant. --- @array2d a 2d array --- @param i row index --- @return 1d array (copy of the row) -function array2d.row(a,i) - assert_arg(1,a,'table') - local row = a[i] - local r = {} - for n,v in ipairs(row) do - r[n] = v - end - return makelist(r) -end - ---- map a function over a 2D array --- @func f a function of at least one argument --- @array2d a 2d array --- @param arg an optional extra argument to be passed to the function. --- @return 2d array -function array2d.map (f,a,arg) - assert_arg(2,a,'table') - f = utils.function_arg(1,f) - return obj(a,imap(function(row) return imap(f,row,arg) end, a)) -end - ---- reduce the rows using a function. --- @func f a binary function --- @array2d a 2d array --- @return 1d array --- @see pl.tablex.reduce -function array2d.reduce_rows (f,a) - assert_arg(1,a,'table') - return tmap(function(row) return reduce(f,row) end, a) -end - ---- reduce the columns using a function. --- @func f a binary function --- @array2d a 2d array --- @return 1d array --- @see pl.tablex.reduce -function array2d.reduce_cols (f,a) - assert_arg(1,a,'table') - return tmap(function(c) return reduce(f,column(a,c)) end, keys(a[1])) -end - ---- reduce a 2D array into a scalar, using two operations. --- @func opc operation to reduce the final result --- @func opr operation to reduce the rows --- @param a 2D array -function array2d.reduce2 (opc,opr,a) - assert_arg(3,a,'table') - local tmp = array2d.reduce_rows(opr,a) - return reduce(opc,tmp) -end - ---- map a function over two arrays. --- They can be both or either 2D arrays --- @func f function of at least two arguments --- @int ad order of first array (`1` if `a` is a list/array, `2` if it is a 2d array) --- @int bd order of second array (`1` if `b` is a list/array, `2` if it is a 2d array) --- @tab a 1d or 2d array --- @tab b 1d or 2d array --- @param arg optional extra argument to pass to function --- @return 2D array, unless both arrays are 1D -function array2d.map2 (f,ad,bd,a,b,arg) - assert_arg(1,a,'table') - assert_arg(2,b,'table') - f = utils.function_arg(1,f) - if ad == 1 and bd == 2 then - return imap(function(row) - return tmap2(f,a,row,arg) - end, b) - elseif ad == 2 and bd == 1 then - return imap(function(row) - return tmap2(f,row,b,arg) - end, a) - elseif ad == 1 and bd == 1 then - return tmap2(f,a,b) - elseif ad == 2 and bd == 2 then - return tmap2(function(rowa,rowb) - return tmap2(f,rowa,rowb,arg) - end, a,b) - end -end - ---- cartesian product of two 1d arrays. --- @func f a function of 2 arguments --- @array t1 a 1d table --- @array t2 a 1d table --- @return 2d table --- @usage product('..',{1,2},{'a','b'}) == {{'1a','2a'},{'1b','2b'}} -function array2d.product (f,t1,t2) - f = utils.function_arg(1,f) - assert_arg(2,t1,'table') - assert_arg(3,t2,'table') - local res = {} - for i,v in ipairs(t2) do - res[i] = tmap(f,t1,v) - end - return res -end - ---- flatten a 2D array. --- (this goes over columns first.) --- @array2d t 2d table --- @return a 1d table --- @usage flatten {{1,2},{3,4},{5,6}} == {1,2,3,4,5,6} -function array2d.flatten (t) - local res = {} - local k = 1 - local rows, cols = array2d.size(t) - for r = 1, rows do - local row = t[r] - for c = 1, cols do - res[k] = row[c] - k = k + 1 - end - end - return makelist(res) -end - ---- reshape a 2D array. Reshape the aray by specifying a new nr of rows. --- @array2d t 2d array --- @int nrows new number of rows --- @bool co use column-order (Fortran-style) (default false) --- @return a new 2d array -function array2d.reshape (t,nrows,co) - local nr,nc = array2d.size(t) - local ncols = nr*nc / nrows - local res = {} - local ir,ic = 1,1 - for i = 1,nrows do - local row = {} - for j = 1,ncols do - row[j] = t[ir][ic] - if not co then - ic = ic + 1 - if ic > nc then - ir = ir + 1 - ic = 1 - end - else - ir = ir + 1 - if ir > nr then - ic = ic + 1 - ir = 1 - end - end - end - res[i] = row - end - return obj(t,res) -end - ---- transpose a 2D array. --- @array2d t 2d array --- @return a new 2d array -function array2d.transpose(t) - assert_arg(1,t,'table') - local _, c = array2d.size(t) - return array2d.reshape(t,c,true) -end - ---- swap two rows of an array. --- @array2d t a 2d array --- @int i1 a row index --- @int i2 a row index --- @return t (same, modified 2d array) -function array2d.swap_rows (t,i1,i2) - assert_arg(1,t,'table') - t[i1],t[i2] = t[i2],t[i1] - return t -end - ---- swap two columns of an array. --- @array2d t a 2d array --- @int j1 a column index --- @int j2 a column index --- @return t (same, modified 2d array) -function array2d.swap_cols (t,j1,j2) - assert_arg(1,t,'table') - for _, row in ipairs(t) do - row[j1],row[j2] = row[j2],row[j1] - end - return t -end - ---- extract the specified rows. --- @array2d t 2d array --- @tparam {int} ridx a table of row indices --- @return a new 2d array with the extracted rows -function array2d.extract_rows (t,ridx) - return obj(t,index_by(t,ridx)) -end - ---- extract the specified columns. --- @array2d t 2d array --- @tparam {int} cidx a table of column indices --- @return a new 2d array with the extracted colums -function array2d.extract_cols (t,cidx) - assert_arg(1,t,'table') - local res = {} - for i = 1,#t do - res[i] = index_by(t[i],cidx) - end - return obj(t,res) -end - ---- remove a row from an array. --- @function array2d.remove_row --- @array2d t a 2d array --- @int i a row index -array2d.remove_row = remove - ---- remove a column from an array. --- @array2d t a 2d array --- @int j a column index -function array2d.remove_col (t,j) - assert_arg(1,t,'table') - for i = 1,#t do - remove(t[i],j) - end -end - -do - local function _parse (s) - local r, c = s:match 'R(%d+)C(%d+)' - if r then - r,c = tonumber(r),tonumber(c) - return r,c - end - c,r = s:match '(%a+)(%d+)' - if c then - local cv = 0 - for i = 1, #c do - cv = cv * 26 + byte(c:sub(i,i)) - byte 'A' + 1 - end - return tonumber(r), cv - end - error('bad cell specifier: '..s) - end - - --- parse a spreadsheet range or cell. - -- The range/cell can be specified either as 'A1:B2' or 'R1C1:R2C2' or for - -- single cells as 'A1' or 'R1C1'. - -- @string s a range (case insensitive). - -- @treturn int start row - -- @treturn int start col - -- @treturn int end row (or `nil` if the range was a single cell) - -- @treturn int end col (or `nil` if the range was a single cell) - function array2d.parse_range (s) - assert_arg(1,s,'string') - s = s:upper() - if s:find ':' then - local start,finish = splitv(s,':') - local i1,j1 = _parse(start) - local i2,j2 = _parse(finish) - return i1,j1,i2,j2 - else -- single value - local i,j = _parse(s) - return i,j - end - end -end - ---- get a slice of a 2D array. --- Same as `slice`. --- @see slice -function array2d.range (...) - return array2d.slice(...) -end - -local default_range do - local function norm_value(v, max) - if not v then return v end - if v < 0 then - v = max + v + 1 - end - if v < 1 then v = 1 end - if v > max then v = max end - return v - end - - --- normalizes coordinates to valid positive entries and defaults. - -- Negative indices will be counted from the end, too low, or too high - -- will be limited by the array sizes. - -- @array2d t a 2D array - -- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` - -- @tparam[opt=1] int j1 start col - -- @tparam[opt=N] int i2 end row - -- @tparam[opt=M] int j2 end col - -- @see parse_range - -- @return i1, j1, i2, j2 - function array2d.default_range (t,i1,j1,i2,j2) - if (type(i1) == 'string') and not (j1 or i2 or j2) then - i1, j1, i2, j2 = array2d.parse_range(i1) - end - local nr, nc = array2d.size(t) - i1 = norm_value(i1 or 1, nr) - j1 = norm_value(j1 or 1, nc) - i2 = norm_value(i2 or nr, nr) - j2 = norm_value(j2 or nc, nc) - return i1,j1,i2,j2 - end - default_range = array2d.default_range -end - ---- get a slice of a 2D array. Note that if the specified range has --- a 1D result, the rank of the result will be 1. --- @array2d t a 2D array --- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` --- @tparam[opt=1] int j1 start col --- @tparam[opt=N] int i2 end row --- @tparam[opt=M] int j2 end col --- @see parse_range --- @return an array, 2D in general but 1D in special cases. -function array2d.slice (t,i1,j1,i2,j2) - assert_arg(1,t,'table') - i1,j1,i2,j2 = default_range(t,i1,j1,i2,j2) - local res = {} - for i = i1,i2 do - local val - local row = t[i] - if j1 == j2 then - val = row[j1] - else - val = {} - for j = j1,j2 do - val[#val+1] = row[j] - end - end - res[#res+1] = val - end - if i1 == i2 then res = res[1] end - return obj(t,res) -end - ---- set a specified range of an array to a value. --- @array2d t a 2D array --- @param value the value (may be a function, called as `val(i,j)`) --- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` --- @tparam[opt=1] int j1 start col --- @tparam[opt=N] int i2 end row --- @tparam[opt=M] int j2 end col --- @see parse_range --- @see tablex.set -function array2d.set (t,value,i1,j1,i2,j2) - i1,j1,i2,j2 = default_range(t,i1,j1,i2,j2) - local i = i1 - if types.is_callable(value) then - local old_f = value - value = function(j) - return old_f(i,j) - end - end - while i <= i2 do - tset(t[i],value,j1,j2) - i = i + 1 - end -end - ---- write a 2D array to a file. --- @array2d t a 2D array --- @param f a file object (default stdout) --- @string fmt a format string (default is just to use tostring) --- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` --- @tparam[opt=1] int j1 start col --- @tparam[opt=N] int i2 end row --- @tparam[opt=M] int j2 end col --- @see parse_range -function array2d.write (t,f,fmt,i1,j1,i2,j2) - assert_arg(1,t,'table') - f = f or stdout - local rowop - if fmt then - rowop = function(row,j) fprintf(f,fmt,row[j]) end - else - rowop = function(row,j) f:write(tostring(row[j]),' ') end - end - local function newline() - f:write '\n' - end - array2d.forall(t,rowop,newline,i1,j1,i2,j2) -end - ---- perform an operation for all values in a 2D array. --- @array2d t 2D array --- @func row_op function to call on each value; `row_op(row,j)` --- @func end_row_op function to call at end of each row; `end_row_op(i)` --- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` --- @tparam[opt=1] int j1 start col --- @tparam[opt=N] int i2 end row --- @tparam[opt=M] int j2 end col --- @see parse_range -function array2d.forall (t,row_op,end_row_op,i1,j1,i2,j2) - assert_arg(1,t,'table') - i1,j1,i2,j2 = default_range(t,i1,j1,i2,j2) - for i = i1,i2 do - local row = t[i] - for j = j1,j2 do - row_op(row,j) - end - if end_row_op then end_row_op(i) end - end -end - ----- move a block from the destination to the source. --- @array2d dest a 2D array --- @int di start row in dest --- @int dj start col in dest --- @array2d src a 2D array --- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` --- @tparam[opt=1] int j1 start col --- @tparam[opt=N] int i2 end row --- @tparam[opt=M] int j2 end col --- @see parse_range -function array2d.move (dest,di,dj,src,i1,j1,i2,j2) - assert_arg(1,dest,'table') - assert_arg(4,src,'table') - i1,j1,i2,j2 = default_range(src,i1,j1,i2,j2) - local nr,nc = array2d.size(dest) - i2, j2 = min(nr,i2), min(nc,j2) - --i1, j1 = max(1,i1), max(1,j1) - dj = dj - 1 - for i = i1,i2 do - local drow, srow = dest[i+di-1], src[i] - for j = j1,j2 do - drow[j+dj] = srow[j] - end - end -end - ---- iterate over all elements in a 2D array, with optional indices. --- @array2d a 2D array --- @bool indices with indices (default false) --- @tparam[opt=1] int|string i1 start row or spreadsheet range passed to `parse_range` --- @tparam[opt=1] int j1 start col --- @tparam[opt=N] int i2 end row --- @tparam[opt=M] int j2 end col --- @see parse_range --- @return either `value` or `i,j,value` depending on the value of `indices` -function array2d.iter(a,indices,i1,j1,i2,j2) - assert_arg(1,a,'table') - i1,j1,i2,j2 = default_range(a,i1,j1,i2,j2) - local i,j = i1,j1-1 - local row = a[i] - return function() - j = j + 1 - if j > j2 then - j = j1 - i = i + 1 - row = a[i] - if i > i2 then - return nil - end - end - if indices then - return i,j,row[j] - else - return row[j] - end - end -end - ---- iterate over all columns. --- @array2d a a 2D array --- @return column, column-index -function array2d.columns(a) - assert_arg(1,a,'table') - local n = #a[1] - local i = 0 - return function() - i = i + 1 - if i > n then return nil end - return column(a,i), i - end -end - ---- iterate over all rows. --- Returns a copy of the row, for read-only purposes directly iterating --- is more performant; `ipairs(a)` --- @array2d a a 2D array --- @return row, row-index -function array2d.rows(a) - assert_arg(1,a,'table') - local n = #a - local i = 0 - return function() - i = i + 1 - if i > n then return nil end - return array2d.row(a,i), i - end -end - ---- new array of specified dimensions --- @int rows number of rows --- @int cols number of cols --- @param val initial value; if it's a function then use `val(i,j)` --- @return new 2d array -function array2d.new(rows,cols,val) - local res = {} - local fun = types.is_callable(val) - for i = 1,rows do - local row = {} - if fun then - for j = 1,cols do row[j] = val(i,j) end - else - for j = 1,cols do row[j] = val end - end - res[i] = row - end - return res -end - -return array2d diff --git a/game/scripts/vscripts/pl/class.lua b/game/scripts/vscripts/pl/class.lua deleted file mode 100644 index 49246ee..0000000 --- a/game/scripts/vscripts/pl/class.lua +++ /dev/null @@ -1,265 +0,0 @@ ---- Provides a reuseable and convenient framework for creating classes in Lua. --- Two possible notations: --- --- B = class(A) --- class.B(A) --- --- The latter form creates a named class within the current environment. Note --- that this implicitly brings in `pl.utils` as a dependency. --- --- See the Guide for further @{01-introduction.md.Simplifying_Object_Oriented_Programming_in_Lua|discussion} --- @module pl.class - -local error, getmetatable, io, pairs, rawget, rawset, setmetatable, tostring, type = - _G.error, _G.getmetatable, _G.io, _G.pairs, _G.rawget, _G.rawset, _G.setmetatable, _G.tostring, _G.type -local compat - --- this trickery is necessary to prevent the inheritance of 'super' and --- the resulting recursive call problems. -local function call_ctor (c,obj,...) - local init = rawget(c,'_init') - local parent_with_init = rawget(c,'_parent_with_init') - - if parent_with_init then - if not init then -- inheriting an init - init = rawget(parent_with_init, '_init') - parent_with_init = rawget(parent_with_init, '_parent_with_init') - end - if parent_with_init then -- super() points to one above whereever _init came from - rawset(obj,'super',function(obj,...) - call_ctor(parent_with_init,obj,...) - end) - end - else - -- Without this, calling super() where none exists will sometimes loop and stack overflow - rawset(obj,'super',nil) - end - - local res = init(obj,...) - if parent_with_init then -- If this execution of call_ctor set a super, unset it - rawset(obj,'super',nil) - end - - return res -end - ---- initializes an __instance__ upon creation. --- @function class:_init --- @param ... parameters passed to the constructor --- @usage local Cat = class() --- function Cat:_init(name) --- --self:super(name) -- call the ancestor initializer if needed --- self.name = name --- end --- --- local pussycat = Cat("pussycat") --- print(pussycat.name) --> pussycat - ---- checks whether an __instance__ is derived from some class. --- Works the other way around as `class_of`. It has two ways of using; --- 1) call with a class to check against, 2) call without params. --- @function instance:is_a --- @param some_class class to check against, or `nil` to return the class --- @return `true` if `instance` is derived from `some_class`, or if `some_class == nil` then --- it returns the class table of the instance --- @usage local pussycat = Lion() -- assuming Lion derives from Cat --- if pussycat:is_a(Cat) then --- -- it's true, it is a Lion, but also a Cat --- end --- --- if pussycat:is_a() == Lion then --- -- It's true --- end -local function is_a(self,klass) - if klass == nil then - -- no class provided, so return the class this instance is derived from - return getmetatable(self) - end - local m = getmetatable(self) - if not m then return false end --*can't be an object! - while m do - if m == klass then return true end - m = rawget(m,'_base') - end - return false -end - ---- checks whether an __instance__ is derived from some class. --- Works the other way around as `is_a`. --- @function some_class:class_of --- @param some_instance instance to check against --- @return `true` if `some_instance` is derived from `some_class` --- @usage local pussycat = Lion() -- assuming Lion derives from Cat --- if Cat:class_of(pussycat) then --- -- it's true --- end -local function class_of(klass,obj) - if type(klass) ~= 'table' or not rawget(klass,'is_a') then return false end - return klass.is_a(obj,klass) -end - ---- cast an object to another class. --- It is not clever (or safe!) so use carefully. --- @param some_instance the object to be changed --- @function some_class:cast -local function cast (klass, obj) - return setmetatable(obj,klass) -end - - -local function _class_tostring (obj) - local mt = obj._class - local name = rawget(mt,'_name') - setmetatable(obj,nil) - local str = tostring(obj) - setmetatable(obj,mt) - if name then str = name ..str:gsub('table','') end - return str -end - -local function tupdate(td,ts,dont_override) - for k,v in pairs(ts) do - if not dont_override or td[k] == nil then - td[k] = v - end - end -end - -local function _class(base,c_arg,c) - -- the class `c` will be the metatable for all its objects, - -- and they will look up their methods in it. - local mt = {} -- a metatable for the class to support __call and _handler - -- can define class by passing it a plain table of methods - local plain = type(base) == 'table' and not getmetatable(base) - if plain then - c = base - base = c._base - else - c = c or {} - end - - if type(base) == 'table' then - -- our new class is a shallow copy of the base class! - -- but be careful not to wipe out any methods we have been given at this point! - tupdate(c,base,plain) - c._base = base - -- inherit the 'not found' handler, if present - if rawget(c,'_handler') then mt.__index = c._handler end - elseif base ~= nil then - error("must derive from a table type",3) - end - - c.__index = c - setmetatable(c,mt) - if not plain then - if base and rawget(base,'_init') then c._parent_with_init = base end -- For super and inherited init - c._init = nil - end - - if base and rawget(base,'_class_init') then - base._class_init(c,c_arg) - end - - -- expose a ctor which can be called by () - mt.__call = function(class_tbl,...) - local obj - if rawget(c,'_create') then obj = c._create(...) end - if not obj then obj = {} end - setmetatable(obj,c) - - if rawget(c,'_init') or rawget(c,'_parent_with_init') then -- constructor exists - local res = call_ctor(c,obj,...) - if res then -- _if_ a ctor returns a value, it becomes the object... - obj = res - setmetatable(obj,c) - end - end - - if base and rawget(base,'_post_init') then - base._post_init(obj) - end - - return obj - end - -- Call Class.catch to set a handler for methods/properties not found in the class! - c.catch = function(self, handler) - if type(self) == "function" then - -- called using . instead of : - handler = self - end - c._handler = handler - mt.__index = handler - end - c.is_a = is_a - c.class_of = class_of - c.cast = cast - c._class = c - - if not rawget(c,'__tostring') then - c.__tostring = _class_tostring - end - - return c -end - ---- create a new class, derived from a given base class. --- Supporting two class creation syntaxes: --- either `Name = class(base)` or `class.Name(base)`. --- The first form returns the class directly and does not set its `_name`. --- The second form creates a variable `Name` in the current environment set --- to the class, and also sets `_name`. --- @function class --- @param base optional base class --- @param c_arg optional parameter to class constructor --- @param c optional table to be used as class -local class -class = setmetatable({},{ - __call = function(fun,...) - return _class(...) - end, - __index = function(tbl,key) - if key == 'class' then - io.stderr:write('require("pl.class").class is deprecated. Use require("pl.class")\n') - return class - end - compat = compat or require 'pl.compat' - local env = compat.getfenv(2) - return function(...) - local c = _class(...) - c._name = key - rawset(env,key,c) - return c - end - end -}) - -class.properties = class() - -function class.properties._class_init(klass) - klass.__index = function(t,key) - -- normal class lookup! - local v = klass[key] - if v then return v end - -- is it a getter? - v = rawget(klass,'get_'..key) - if v then - return v(t) - end - -- is it a field? - return rawget(t,'_'..key) - end - klass.__newindex = function (t,key,value) - -- if there's a setter, use that, otherwise directly set table - local p = 'set_'..key - local setter = klass[p] - if setter then - setter(t,value) - else - rawset(t,key,value) - end - end -end - - -return class - diff --git a/game/scripts/vscripts/pl/compat.lua b/game/scripts/vscripts/pl/compat.lua deleted file mode 100644 index dfcb91d..0000000 --- a/game/scripts/vscripts/pl/compat.lua +++ /dev/null @@ -1,252 +0,0 @@ ----------------- ---- Lua 5.1/5.2/5.3 compatibility. --- Injects `table.pack`, `table.unpack`, and `package.searchpath` in the global --- environment, to make sure they are available for Lua 5.1 and LuaJIT. --- --- All other functions are exported as usual in the returned module table. --- --- NOTE: everything in this module is also available in `pl.utils`. --- @module pl.compat -local compat = {} - ---- boolean flag this is Lua 5.1 (or LuaJIT). --- @field lua51 -compat.lua51 = _VERSION == 'Lua 5.1' - ---- boolean flag this is LuaJIT. --- @field jit -compat.jit = (tostring(assert):match('builtin') ~= nil) - ---- boolean flag this is LuaJIT with 5.2 compatibility compiled in. --- @field jit52 -if compat.jit then - -- 'goto' is a keyword when 52 compatibility is enabled in LuaJit - compat.jit52 = not loadstring("local goto = 1") -end - ---- the directory separator character for the current platform. --- @field dir_separator -compat.dir_separator = _G.package.config:sub(1,1) - ---- boolean flag this is a Windows platform. --- @field is_windows -compat.is_windows = compat.dir_separator == '\\' - ---- execute a shell command, in a compatible and platform independent way. --- This is a compatibility function that returns the same for Lua 5.1 and --- Lua 5.2+. --- --- NOTE: Windows systems can use signed 32bit integer exitcodes. Posix systems --- only use exitcodes 0-255, anything else is undefined. --- --- NOTE2: In Lua 5.2 and 5.3 a Windows exitcode of -1 would not properly be --- returned, this function will return it properly for all versions. --- @param cmd a shell command --- @return true if successful --- @return actual return code -function compat.execute(cmd) - local res1,res2,res3 = os.execute(cmd) - if res2 == "No error" and res3 == 0 and compat.is_windows then - -- os.execute bug in Lua 5.2/5.3 not reporting -1 properly on Windows - -- this was fixed in 5.4 - res3 = -1 - end - if compat.lua51 and not compat.jit52 then - if compat.is_windows then - return res1==0,res1 - else - res1 = res1 > 255 and res1 / 256 or res1 - return res1==0,res1 - end - else - if compat.is_windows then - return res3==0,res3 - else - return not not res1,res3 - end - end -end - ----------------- --- Load Lua code as a text or binary chunk (in a Lua 5.2 compatible way). --- @param ld code string or loader --- @param[opt] source name of chunk for errors --- @param[opt] mode 'b', 't' or 'bt' --- @param[opt] env environment to load the chunk in --- @function compat.load - ---------------- --- Get environment of a function (in a Lua 5.1 compatible way). --- Not 100% compatible, so with Lua 5.2 it may return nil for a function with no --- global references! --- Based on code by [Sergey Rozhenko](http://lua-users.org/lists/lua-l/2010-06/msg00313.html) --- @param f a function or a call stack reference --- @function compat.getfenv - ---------------- --- Set environment of a function (in a Lua 5.1 compatible way). --- @param f a function or a call stack reference --- @param env a table that becomes the new environment of `f` --- @function compat.setfenv - -if compat.lua51 then -- define Lua 5.2 style load() - if not compat.jit then -- but LuaJIT's load _is_ compatible - local lua51_load = load - function compat.load(str,src,mode,env) - local chunk,err - if type(str) == 'string' then - if str:byte(1) == 27 and not (mode or 'bt'):find 'b' then - return nil,"attempt to load a binary chunk" - end - chunk,err = loadstring(str,src) - else - chunk,err = lua51_load(str,src) - end - if chunk and env then setfenv(chunk,env) end - return chunk,err - end - else - compat.load = load - end - compat.setfenv, compat.getfenv = setfenv, getfenv -else - compat.load = load - -- setfenv/getfenv replacements for Lua 5.2 - -- by Sergey Rozhenko - -- http://lua-users.org/lists/lua-l/2010-06/msg00313.html - -- Roberto Ierusalimschy notes that it is possible for getfenv to return nil - -- in the case of a function with no globals: - -- http://lua-users.org/lists/lua-l/2010-06/msg00315.html - function compat.setfenv(f, t) - f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) - local name - local up = 0 - repeat - up = up + 1 - name = debug.getupvalue(f, up) - until name == '_ENV' or name == nil - if name then - debug.upvaluejoin(f, up, function() return name end, 1) -- use unique upvalue - debug.setupvalue(f, up, t) - end - if f ~= 0 then return f end - end - - function compat.getfenv(f) - local f = f or 0 - f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func) - local name, val - local up = 0 - repeat - up = up + 1 - name, val = debug.getupvalue(f, up) - until name == '_ENV' or name == nil - return val - end -end - - ---- Global exported functions (for Lua 5.1 & LuaJIT) --- @section lua52 - ---- pack an argument list into a table. --- @param ... any arguments --- @return a table with field n set to the length --- @function table.pack -if not table.pack then - function table.pack (...) -- luacheck: ignore - return {n=select('#',...); ...} - end -end - ---- unpack a table and return the elements. --- --- NOTE: this version does NOT honor the n field, and hence it is not nil-safe. --- See `utils.unpack` for a version that is nil-safe. --- @param t table to unpack --- @param[opt] i index from which to start unpacking, defaults to 1 --- @param[opt] j index of the last element to unpack, defaults to #t --- @return multiple return values from the table --- @function table.unpack --- @see utils.unpack -if not table.unpack then - table.unpack = unpack -- luacheck: ignore -end - ---- return the full path where a file name would be matched. --- This function was introduced in Lua 5.2, so this compatibility version --- will be injected in Lua 5.1 engines. --- @string name file name, possibly dotted --- @string path a path-template in the same form as package.path or package.cpath --- @string[opt] sep template separate character to be replaced by path separator. Default: "." --- @string[opt] rep the path separator to use, defaults to system separator. Default; "/" on Unixes, "\" on Windows. --- @see path.package_path --- @function package.searchpath --- @return on success: path of the file --- @return on failure: nil, error string listing paths tried -if not package.searchpath then - function package.searchpath (name,path,sep,rep) -- luacheck: ignore - if type(name) ~= "string" then - error(("bad argument #1 to 'searchpath' (string expected, got %s)"):format(type(path)), 2) - end - if type(path) ~= "string" then - error(("bad argument #2 to 'searchpath' (string expected, got %s)"):format(type(path)), 2) - end - if sep ~= nil and type(sep) ~= "string" then - error(("bad argument #3 to 'searchpath' (string expected, got %s)"):format(type(path)), 2) - end - if rep ~= nil and type(rep) ~= "string" then - error(("bad argument #4 to 'searchpath' (string expected, got %s)"):format(type(path)), 2) - end - sep = sep or "." - rep = rep or compat.dir_separator - do - local s, e = name:find(sep, nil, true) - while s do - name = name:sub(1, s-1) .. rep .. name:sub(e+1, -1) - s, e = name:find(sep, s + #rep + 1, true) - end - end - local tried = {} - for m in path:gmatch('[^;]+') do - local nm = m:gsub('?', name) - tried[#tried+1] = nm - local f = io.open(nm,'r') - if f then f:close(); return nm end - end - return nil, "\tno file '" .. table.concat(tried, "'\n\tno file '") .. "'" - end -end - ---- Global exported functions (for Lua < 5.4) --- @section lua54 - ---- raise a warning message. --- This functions mimics the `warn` function added in Lua 5.4. --- @function warn --- @param ... any arguments -if not rawget(_G, "warn") then - local enabled = false - local function warn(arg1, ...) - if type(arg1) == "string" and arg1:sub(1, 1) == "@" then - -- control message - if arg1 == "@on" then - enabled = true - return - end - if arg1 == "@off" then - enabled = false - return - end - return -- ignore unknown control messages - end - if enabled then - io.stderr:write("Lua warning: ", arg1, ...) - io.stderr:write("\n") - end - end - -- use rawset to bypass OpenResty's protection of global scope - rawset(_G, "warn", warn) -end - -return compat diff --git a/game/scripts/vscripts/pl/comprehension.lua b/game/scripts/vscripts/pl/comprehension.lua deleted file mode 100644 index 39be7c5..0000000 --- a/game/scripts/vscripts/pl/comprehension.lua +++ /dev/null @@ -1,285 +0,0 @@ ---- List comprehensions implemented in Lua. --- --- See the [wiki page](http://lua-users.org/wiki/ListComprehensions) --- --- local C= require 'pl.comprehension' . new() --- --- C ('x for x=1,10') () --- ==> {1,2,3,4,5,6,7,8,9,10} --- C 'x^2 for x=1,4' () --- ==> {1,4,9,16} --- C '{x,x^2} for x=1,4' () --- ==> {{1,1},{2,4},{3,9},{4,16}} --- C '2*x for x' {1,2,3} --- ==> {2,4,6} --- dbl = C '2*x for x' --- dbl {10,20,30} --- ==> {20,40,60} --- C 'x for x if x % 2 == 0' {1,2,3,4,5} --- ==> {2,4} --- C '{x,y} for x = 1,2 for y = 1,2' () --- ==> {{1,1},{1,2},{2,1},{2,2}} --- C '{x,y} for x for y' ({1,2},{10,20}) --- ==> {{1,10},{1,20},{2,10},{2,20}} --- assert(C 'sum(x^2 for x)' {2,3,4} == 2^2+3^2+4^2) --- --- (c) 2008 David Manura. Licensed under the same terms as Lua (MIT license). --- --- Dependencies: `pl.utils`, `pl.luabalanced` --- --- See @{07-functional.md.List_Comprehensions|the Guide} --- @module pl.comprehension - -local utils = require 'pl.utils' - -local status,lb = pcall(require, "pl.luabalanced") -if not status then - lb = require 'luabalanced' -end - -local math_max = math.max -local table_concat = table.concat - --- fold operations --- http://en.wikipedia.org/wiki/Fold_(higher-order_function) -local ops = { - list = {init=' {} ', accum=' __result[#__result+1] = (%s) '}, - table = {init=' {} ', accum=' local __k, __v = %s __result[__k] = __v '}, - sum = {init=' 0 ', accum=' __result = __result + (%s) '}, - min = {init=' nil ', accum=' local __tmp = %s ' .. - ' if __result then if __tmp < __result then ' .. - '__result = __tmp end else __result = __tmp end '}, - max = {init=' nil ', accum=' local __tmp = %s ' .. - ' if __result then if __tmp > __result then ' .. - '__result = __tmp end else __result = __tmp end '}, -} - - --- Parses comprehension string expr. --- Returns output expression list string, array of for types --- ('=', 'in' or nil) , array of input variable name --- strings , array of input variable value strings --- , array of predicate expression strings , --- operation name string , and number of placeholder --- parameters . --- --- The is equivalent to the mathematical set-builder notation: --- --- { | in , } --- --- @usage "x^2 for x" -- array values --- @usage "x^2 for x=1,10,2" -- numeric for --- @usage "k^v for k,v in pairs(_1)" -- iterator for --- @usage "(x+y)^2 for x for y if x > y" -- nested --- -local function parse_comprehension(expr) - local pos = 1 - - -- extract opname (if exists) - local opname - local tok, post = expr:match('^%s*([%a_][%w_]*)%s*%(()', pos) - local pose = #expr + 1 - if tok then - local tok2, posb = lb.match_bracketed(expr, post-1) - assert(tok2, 'syntax error') - if expr:match('^%s*$', posb) then - opname = tok - pose = posb - 1 - pos = post - end - end - opname = opname or "list" - - -- extract out expression list - local out; out, pos = lb.match_explist(expr, pos) - assert(out, "syntax error: missing expression list") - out = table_concat(out, ', ') - - -- extract "for" clauses - local fortypes = {} - local invarlists = {} - local invallists = {} - while 1 do - local post = expr:match('^%s*for%s+()', pos) - if not post then break end - pos = post - - -- extract input vars - local iv; iv, pos = lb.match_namelist(expr, pos) - assert(#iv > 0, 'syntax error: zero variables') - for _,ident in ipairs(iv) do - assert(not ident:match'^__', - "identifier " .. ident .. " may not contain __ prefix") - end - invarlists[#invarlists+1] = iv - - -- extract '=' or 'in' (optional) - local fortype, post = expr:match('^(=)%s*()', pos) - if not fortype then fortype, post = expr:match('^(in)%s+()', pos) end - if fortype then - pos = post - -- extract input value range - local il; il, pos = lb.match_explist(expr, pos) - assert(#il > 0, 'syntax error: zero expressions') - assert(fortype ~= '=' or #il == 2 or #il == 3, - 'syntax error: numeric for requires 2 or three expressions') - fortypes[#invarlists] = fortype - invallists[#invarlists] = il - else - fortypes[#invarlists] = false - invallists[#invarlists] = false - end - end - assert(#invarlists > 0, 'syntax error: missing "for" clause') - - -- extract "if" clauses - local preds = {} - while 1 do - local post = expr:match('^%s*if%s+()', pos) - if not post then break end - pos = post - local pred; pred, pos = lb.match_expression(expr, pos) - assert(pred, 'syntax error: predicated expression not found') - preds[#preds+1] = pred - end - - -- extract number of parameter variables (name matching "_%d+") - local stmp = ''; lb.gsub(expr, function(u, sin) -- strip comments/strings - if u == 'e' then stmp = stmp .. ' ' .. sin .. ' ' end - end) - local max_param = 0; stmp:gsub('[%a_][%w_]*', function(s) - local s = s:match('^_(%d+)$') - if s then max_param = math_max(max_param, tonumber(s)) end - end) - - if pos ~= pose then - assert(false, "syntax error: unrecognized " .. expr:sub(pos)) - end - - --DEBUG: - --print('----\n', string.format("%q", expr), string.format("%q", out), opname) - --for k,v in ipairs(invarlists) do print(k,v, invallists[k]) end - --for k,v in ipairs(preds) do print(k,v) end - - return out, fortypes, invarlists, invallists, preds, opname, max_param -end - - --- Create Lua code string representing comprehension. --- Arguments are in the form returned by parse_comprehension. -local function code_comprehension( - out, fortypes, invarlists, invallists, preds, opname, max_param -) - local op = assert(ops[opname]) - local code = op.accum:gsub('%%s', out) - - for i=#preds,1,-1 do local pred = preds[i] - code = ' if ' .. pred .. ' then ' .. code .. ' end ' - end - for i=#invarlists,1,-1 do - if not fortypes[i] then - local arrayname = '__in' .. i - local idx = '__idx' .. i - code = - ' for ' .. idx .. ' = 1, #' .. arrayname .. ' do ' .. - ' local ' .. invarlists[i][1] .. ' = ' .. arrayname .. '['..idx..'] ' .. - code .. ' end ' - else - code = - ' for ' .. - table_concat(invarlists[i], ', ') .. - ' ' .. fortypes[i] .. ' ' .. - table_concat(invallists[i], ', ') .. - ' do ' .. code .. ' end ' - end - end - code = ' local __result = ( ' .. op.init .. ' ) ' .. code - return code -end - - --- Convert code string represented by code_comprehension --- into Lua function. Also must pass ninputs = #invarlists, --- max_param, and invallists (from parse_comprehension). --- Uses environment env. -local function wrap_comprehension(code, ninputs, max_param, invallists, env) - assert(ninputs > 0) - local ts = {} - for i=1,max_param do - ts[#ts+1] = '_' .. i - end - for i=1,ninputs do - if not invallists[i] then - local name = '__in' .. i - ts[#ts+1] = name - end - end - if #ts > 0 then - code = ' local ' .. table_concat(ts, ', ') .. ' = ... ' .. code - end - code = code .. ' return __result ' - --print('DEBUG:', code) - local f, err = utils.load(code,'tmp','t',env) - if not f then assert(false, err .. ' with generated code ' .. code) end - return f -end - - --- Build Lua function from comprehension string. --- Uses environment env. -local function build_comprehension(expr, env) - local out, fortypes, invarlists, invallists, preds, opname, max_param - = parse_comprehension(expr) - local code = code_comprehension( - out, fortypes, invarlists, invallists, preds, opname, max_param) - local f = wrap_comprehension(code, #invarlists, max_param, invallists, env) - return f -end - - --- Creates new comprehension cache. --- Any list comprehension function created are set to the environment --- env (defaults to caller of new). -local function new(env) - -- Note: using a single global comprehension cache would have had - -- security implications (e.g. retrieving cached functions created - -- in other environments). - -- The cache lookup function could have instead been written to retrieve - -- the caller's environment, lookup up the cache private to that - -- environment, and then looked up the function in that cache. - -- That would avoid the need for this call to - -- explicitly manage caches; however, that might also have an undue - -- performance penalty. - - if not env then - env = utils.getfenv(2) - end - - local mt = {} - local cache = setmetatable({}, mt) - - -- Index operator builds, caches, and returns Lua function - -- corresponding to comprehension expression string. - -- - -- Example: f = comprehension['x^2 for x'] - -- - function mt:__index(expr) - local f = build_comprehension(expr, env) - self[expr] = f -- cache - return f - end - - -- Convenience syntax. - -- Allows comprehension 'x^2 for x' instead of comprehension['x^2 for x']. - mt.__call = mt.__index - - cache.new = new - - return cache -end - - -local comprehension = {} -comprehension.new = new - -return comprehension diff --git a/game/scripts/vscripts/pl/config.lua b/game/scripts/vscripts/pl/config.lua deleted file mode 100644 index 2e6db0c..0000000 --- a/game/scripts/vscripts/pl/config.lua +++ /dev/null @@ -1,207 +0,0 @@ ---- Reads configuration files into a Lua table. --- Understands INI files, classic Unix config files, and simple --- delimited columns of values. See @{06-data.md.Reading_Configuration_Files|the Guide} --- --- # test.config --- # Read timeout in seconds --- read.timeout=10 --- # Write timeout in seconds --- write.timeout=5 --- #acceptable ports --- ports = 1002,1003,1004 --- --- -- readconfig.lua --- local config = require 'config' --- local t = config.read 'test.config' --- print(pretty.write(t)) --- --- ### output ##### --- { --- ports = { --- 1002, --- 1003, --- 1004 --- }, --- write_timeout = 5, --- read_timeout = 10 --- } --- --- @module pl.config - -local type,tonumber,ipairs,io, table = _G.type,_G.tonumber,_G.ipairs,_G.io,_G.table - -local function split(s,re) - local res = {} - local t_insert = table.insert - re = '[^'..re..']+' - for k in s:gmatch(re) do t_insert(res,k) end - return res -end - -local function strip(s) - return s:gsub('^%s+',''):gsub('%s+$','') -end - -local function strip_quotes (s) - return s:gsub("['\"](.*)['\"]",'%1') -end - -local config = {} - ---- like io.lines(), but allows for lines to be continued with '\'. --- @param file a file-like object (anything where read() returns the next line) or a filename. --- Defaults to stardard input. --- @return an iterator over the lines, or nil --- @return error 'not a file-like object' or 'file is nil' -function config.lines(file) - local f,openf,err - local line = '' - if type(file) == 'string' then - f,err = io.open(file,'r') - if not f then return nil,err end - openf = true - else - f = file or io.stdin - if not file.read then return nil, 'not a file-like object' end - end - if not f then return nil, 'file is nil' end - return function() - local l = f:read() - while l do - -- only for non-blank lines that don't begin with either ';' or '#' - if l:match '%S' and not l:match '^%s*[;#]' then - -- does the line end with '\'? - local i = l:find '\\%s*$' - if i then -- if so, - line = line..l:sub(1,i-1) - elseif line == '' then - return l - else - l = line..l - line = '' - return l - end - end - l = f:read() - end - if openf then f:close() end - end -end - ---- read a configuration file into a table --- @param file either a file-like object or a string, which must be a filename --- @tab[opt] cnfg a configuration table that may contain these fields: --- --- * `smart` try to deduce what kind of config file we have (default false) --- * `variabilize` make names into valid Lua identifiers (default true) --- * `convert_numbers` try to convert values into numbers (default true) --- * `trim_space` ensure that there is no starting or trailing whitespace with values (default true) --- * `trim_quotes` remove quotes from strings (default false) --- * `list_delim` delimiter to use when separating columns (default ',') --- * `keysep` separator between key and value pairs (default '=') --- --- @return a table containing items, or `nil` --- @return error message (same as @{config.lines} -function config.read(file,cnfg) - local auto - - local iter,err = config.lines(file) - if not iter then return nil,err end - local line = iter() - cnfg = cnfg or {} - if cnfg.smart then - auto = true - if line:match '^[^=]+=' then - cnfg.keysep = '=' - elseif line:match '^[^:]+:' then - cnfg.keysep = ':' - cnfg.list_delim = ':' - elseif line:match '^%S+%s+' then - cnfg.keysep = ' ' - -- more than two columns assume that it's a space-delimited list - -- cf /etc/fstab with /etc/ssh/ssh_config - if line:match '^%S+%s+%S+%s+%S+' then - cnfg.list_delim = ' ' - end - cnfg.variabilize = false - end - end - - - local function check_cnfg (var,def) - local val = cnfg[var] - if val == nil then return def else return val end - end - - local initial_digits = '^[%d%+%-]' - local t = {} - local top_t = t - local variabilize = check_cnfg ('variabilize',true) - local list_delim = check_cnfg('list_delim',',') - local convert_numbers = check_cnfg('convert_numbers',true) - local convert_boolean = check_cnfg('convert_boolean',false) - local trim_space = check_cnfg('trim_space',true) - local trim_quotes = check_cnfg('trim_quotes',false) - local ignore_assign = check_cnfg('ignore_assign',false) - local keysep = check_cnfg('keysep','=') - local keypat = keysep == ' ' and '%s+' or '%s*'..keysep..'%s*' - if list_delim == ' ' then list_delim = '%s+' end - - local function process_name(key) - if variabilize then - key = key:gsub('[^%w]','_') - end - return key - end - - local function process_value(value) - if list_delim and value:find(list_delim) then - value = split(value,list_delim) - for i,v in ipairs(value) do - value[i] = process_value(v) - end - elseif convert_numbers and value:find(initial_digits) then - local val = tonumber(value) - if not val and value:match ' kB$' then - value = value:gsub(' kB','') - val = tonumber(value) - end - if val then value = val end - elseif convert_boolean and value == 'true' then - return true - elseif convert_boolean and value == 'false' then - return false - end - if type(value) == 'string' then - if trim_space then value = strip(value) end - if not trim_quotes and auto and value:match '^"' then - trim_quotes = true - end - if trim_quotes then value = strip_quotes(value) end - end - return value - end - - while line do - if line:find('^%[') then -- section! - local section = process_name(line:match('%[([^%]]+)%]')) - t = top_t - t[section] = {} - t = t[section] - else - line = line:gsub('^%s*','') - local i1,i2 = line:find(keypat) - if i1 and not ignore_assign then -- key,value assignment - local key = process_name(line:sub(1,i1-1)) - local value = process_value(line:sub(i2+1)) - t[key] = value - else -- a plain list of values... - t[#t+1] = process_value(line) - end - end - line = iter() - end - return top_t -end - -return config diff --git a/game/scripts/vscripts/pl/data.lua b/game/scripts/vscripts/pl/data.lua deleted file mode 100644 index a565ebc..0000000 --- a/game/scripts/vscripts/pl/data.lua +++ /dev/null @@ -1,654 +0,0 @@ ---- Reading and querying simple tabular data. --- --- data.read 'test.txt' --- ==> {{10,20},{2,5},{40,50},fieldnames={'x','y'},delim=','} --- --- Provides a way of creating basic SQL-like queries. --- --- require 'pl' --- local d = data.read('xyz.txt') --- local q = d:select('x,y,z where x > 3 and z < 2 sort by y') --- for x,y,z in q do --- print(x,y,z) --- end --- --- See @{06-data.md.Reading_Columnar_Data|the Guide} --- --- Dependencies: `pl.utils`, `pl.array2d` (fallback methods) --- @module pl.data - -local utils = require 'pl.utils' -local _DEBUG = rawget(_G,'_DEBUG') - -local patterns,function_arg,usplit,array_tostring = utils.patterns,utils.function_arg,utils.split,utils.array_tostring -local append,concat = table.insert,table.concat -local gsub = string.gsub -local io = io -local _G,print,type,tonumber,ipairs,setmetatable = _G,print,type,tonumber,ipairs,setmetatable - - -local data = {} - -local parse_select - -local function rstrip(s) - return (s:gsub('%s+$','')) -end - -local function strip (s) - return (rstrip(s):gsub('^%s*','')) -end - --- This gives `l` the standard List metatable, --- pulling in the List module. -local function makelist(l) - return setmetatable(l, require('pl.List')) -end - -local function map(fun,t) - local res = {} - for i = 1,#t do - res[i] = fun(t[i]) - end - return res -end - -local function split(line,delim,csv,n) - local massage - -- CSV fields may be double-quoted and may contain commas! - if csv and line:match '"' then - line = line:gsub('"([^"]+)"',function(str) - local s,cnt = str:gsub(',','\001') - if cnt > 0 then massage = true end - return s - end) - if massage then - massage = function(s) return (s:gsub('\001',',')) end - end - end - local res = (usplit(line,delim,false,n)) - if csv then - -- restore CSV commas-in-fields - if massage then res = map(massage,res) end - -- in CSV mode trailiing commas are significant! - if line:match ',$' then append(res,'') end - end - return makelist(res) -end - -local function find(t,v) - for i = 1,#t do - if v == t[i] then return i end - end -end - -local DataMT = { - column_by_name = function(self,name) - if type(name) == 'number' then - name = '$'..name - end - local arr = {} - for res in data.query(self,name) do - append(arr,res) - end - return makelist(arr) - end, - - copy_select = function(self,condn) - condn = parse_select(condn,self) - local iter = data.query(self,condn) - local res = {} - local row = makelist{iter()} - while #row > 0 do - append(res,row) - row = makelist{iter()} - end - res.delim = self.delim - return data.new(res,split(condn.fields,',')) - end, - - column_names = function(self) - return self.fieldnames - end, -} - -local array2d - -DataMT.__index = function(self,name) - local f = DataMT[name] - if f then return f end - if not array2d then - array2d = require 'pl.array2d' - end - return array2d[name] -end - ---- return a particular column as a list of values (method). --- @param name either name of column, or numerical index. --- @function Data.column_by_name - ---- return a query iterator on this data (method). --- @string condn the query expression --- @function Data.select --- @see data.query - ---- return a row iterator on this data (method). --- @string condn the query expression --- @function Data.select_row - ---- return a new data object based on this query (method). --- @string condn the query expression --- @function Data.copy_select - ---- return the field names of this data object (method). --- @function Data.column_names - ---- write out a row (method). --- @param f file-like object --- @function Data.write_row - ---- write data out to file (method). --- @param f file-like object --- @function Data.write - - --- [guessing delimiter] We check for comma, tab and spaces in that order. --- [issue] any other delimiters to be checked? -local delims = {',', '\t', ' ', ';'} - -local function guess_delim (line) - if line=='' then return ' ' end - for _,delim in ipairs(delims) do - if line:find(delim) then - return delim == ' ' and '%s+' or delim - end - end - return ' ' -end - --- [file parameter] If it's a string, we try open as a filename. If nil, then --- either stdin or stdout depending on the mode. Otherwise, check if this is --- a file-like object (implements read or write depending) -local function open_file (f,mode) - local opened, err - local reading = mode == 'r' - if type(f) == 'string' then - if f == 'stdin' then - f = io.stdin - elseif f == 'stdout' then - f = io.stdout - else - f,err = io.open(f,mode) - if not f then return nil,err end - opened = true - end - end - if f and ((reading and not f.read) or (not reading and not f.write)) then - return nil, "not a file-like object" - end - return f,nil,opened -end - ---- read a delimited file in a Lua table. --- By default, attempts to treat first line as separated list of fieldnames. --- @param file a filename or a file-like object --- @tab cnfg parsing options --- @string cnfg.delim a string pattern to split fields --- @array cnfg.fieldnames (i.e. don't read from first line) --- @bool cnfg.no_convert (default is to try conversion on first data line) --- @tab cnfg.convert table of custom conversion functions with column keys --- @int cnfg.numfields indices of columns known to be numbers --- @bool cnfg.last_field_collect only split as many fields as fieldnames. --- @int cnfg.thousands_dot thousands separator in Excel CSV is '.' --- @bool cnfg.csv fields may be double-quoted and contain commas; --- Also, empty fields are considered to be equivalent to zero. --- @return `data` object, or `nil` --- @return error message. May be a file error, 'not a file-like object' --- or a conversion error -function data.read(file,cnfg) - local count,line - local D = {} - if not cnfg then cnfg = {} end - local f,err,opened = open_file(file,'r') - if not f then return nil, err end - local thousands_dot = cnfg.thousands_dot - local csv = cnfg.csv - if csv then cnfg.delim = ',' end - - -- note that using dot as the thousands separator (@thousands_dot) - -- requires a special conversion function! For CSV, _empty fields_ are - -- considered to default to numerial zeroes. - local tonumber = tonumber - local function try_number(x) - if thousands_dot then x = x:gsub('%.(...)','%1') end - if csv and x == '' then x = '0' end - local v = tonumber(x) - if v == nil then return nil,"not a number" end - return v - end - - count = 1 - line = f:read() - if not line then return nil, "empty file" end - - -- first question: what is the delimiter? - D.delim = cnfg.delim and cnfg.delim or guess_delim(line) - local delim = D.delim - - local conversion - local numfields = {} - local function append_conversion (idx,conv) - conversion = conversion or {} - append(numfields,idx) - append(conversion,conv) - end - if cnfg.numfields then - for _,n in ipairs(cnfg.numfields) do append_conversion(n,try_number) end - end - - -- some space-delimited data starts with a space. This should not be a column, - -- although it certainly would be for comma-separated, etc. - local stripper - if delim == '%s+' and line:find(delim) == 1 then - stripper = function(s) return s:gsub('^%s+','') end - line = stripper(line) - end - -- first line will usually be field names. Unless fieldnames are specified, - -- we check if it contains purely numerical values for the case of reading - -- plain data files. - if not cnfg.fieldnames then - local fields,nums - fields = split(line,delim,csv) - if not cnfg.convert then - nums = map(tonumber,fields) - if #nums == #fields then -- they're ALL numbers! - append(D,nums) -- add the first converted row - -- and specify conversions for subsequent rows - for i = 1,#nums do append_conversion(i,try_number) end - else -- we'll try to check numbers just now.. - nums = nil - end - else -- [explicit column conversions] (any deduced number conversions will be added) - for idx,conv in pairs(cnfg.convert) do append_conversion(idx,conv) end - end - if nums == nil then - cnfg.fieldnames = fields - end - line = f:read() - count = count + 1 - if stripper then line = stripper(line) end - elseif type(cnfg.fieldnames) == 'string' then - cnfg.fieldnames = split(cnfg.fieldnames,delim,csv) - end - local nfields - -- at this point, the column headers have been read in. If the first - -- row consisted of numbers, it has already been added to the dataset. - if cnfg.fieldnames then - D.fieldnames = cnfg.fieldnames - -- [collecting end field] If @last_field_collect then we'll - -- only split as many fields as there are fieldnames - if cnfg.last_field_collect then - nfields = #D.fieldnames - end - -- [implicit column conversion] unless @no_convert, we need the numerical field indices - -- of the first data row. These can also be specified explicitly by @numfields. - if not cnfg.no_convert then - local fields = split(line,D.delim,csv,nfields) - for i = 1,#fields do - if not find(numfields,i) and try_number(fields[i]) then - append_conversion(i,try_number) - end - end - end - end - -- keep going until finished - while line do - if not line:find ('^%s*$') then -- [blank lines] ignore them! - if stripper then line = stripper(line) end - local fields = split(line,delim,csv,nfields) - if conversion then -- there were field conversions... - for k = 1,#numfields do - local i,conv = numfields[k],conversion[k] - local val,err = conv(fields[i]) - if val == nil then - return nil, err..": "..fields[i].." at line "..count - else - fields[i] = val - end - end - end - append(D,fields) - end - line = f:read() - count = count + 1 - end - if opened then f:close() end - if delim == '%s+' then D.delim = ' ' end - if not D.fieldnames then D.fieldnames = {} end - return data.new(D) -end - -local function write_row (data,f,row,delim) - data.temp = array_tostring(row,data.temp) - f:write(concat(data.temp,delim),'\n') -end - -function DataMT:write_row(f,row) - write_row(self,f,row,self.delim) -end - ---- write 2D data to a file. --- Does not assume that the data has actually been --- generated with `new` or `read`. --- @param data 2D array --- @param file filename or file-like object --- @tparam[opt] {string} fieldnames list of fields (optional) --- @string[opt='\t'] delim delimiter (default tab) --- @return true or nil, error -function data.write (data,file,fieldnames,delim) - local f,err,opened = open_file(file,'w') - if not f then return nil, err end - if not fieldnames then - fieldnames = data.fieldnames - end - delim = delim or '\t' - if fieldnames and #fieldnames > 0 then - f:write(concat(fieldnames,delim),'\n') - end - for i = 1,#data do - write_row(data,f,data[i],delim) - end - if opened then f:close() end - return true -end - - -function DataMT:write(file) - data.write(self,file,self.fieldnames,self.delim) -end - -local function massage_fieldnames (fields,copy) - -- fieldnames must be valid Lua identifiers; ignore any surrounding padding - -- but keep the original fieldnames... - for i = 1,#fields do - local f = strip(fields[i]) - copy[i] = f - fields[i] = f:gsub('%W','_') - end -end - ---- create a new dataset from a table of rows. --- Can specify the fieldnames, else the table must have a field called --- 'fieldnames', which is either a string of delimiter-separated names, --- or a table of names.
--- If the table does not have a field called 'delim', then an attempt will be --- made to guess it from the fieldnames string, defaults otherwise to tab. --- @param d the table. --- @tparam[opt] {string} fieldnames optional fieldnames --- @return the table. -function data.new (d,fieldnames) - d.fieldnames = d.fieldnames or fieldnames or '' - if not d.delim and type(d.fieldnames) == 'string' then - d.delim = guess_delim(d.fieldnames) - d.fieldnames = split(d.fieldnames,d.delim) - end - d.fieldnames = makelist(d.fieldnames) - d.original_fieldnames = {} - massage_fieldnames(d.fieldnames,d.original_fieldnames) - setmetatable(d,DataMT) - -- a query with just the fieldname will return a sequence - -- of values, which seq.copy turns into a table. - return d -end - -local sorted_query = [[ -return function (t) - local i = 0 - local v - local ls = {} - for i,v in ipairs(t) do - if CONDITION then - ls[#ls+1] = v - end - end - table.sort(ls,function(v1,v2) - return SORT_EXPR - end) - local n = #ls - return function() - i = i + 1 - v = ls[i] - if i > n then return end - return FIELDLIST - end -end -]] - --- question: is this optimized case actually worth the extra code? -local simple_query = [[ -return function (t) - local n = #t - local i = 0 - local v - return function() - repeat - i = i + 1 - v = t[i] - until i > n or CONDITION - if i > n then return end - return FIELDLIST - end -end -]] - -local function is_string (s) - return type(s) == 'string' -end - -local field_error - -local function fieldnames_as_string (data) - return concat(data.fieldnames,',') -end - -local function massage_fields(data,f) - local idx - if f:find '^%d+$' then - idx = tonumber(f) - else - idx = find(data.fieldnames,f) - end - if idx then - return 'v['..idx..']' - else - field_error = f..' not found in '..fieldnames_as_string(data) - return f - end -end - - -local function process_select (data,parms) - --- preparing fields ---- - field_error = nil - local fields = parms.fields - local numfields = fields:find '%$' or #data.fieldnames == 0 - if fields:find '^%s*%*%s*' then - if not numfields then - fields = fieldnames_as_string(data) - else - local ncol = #data[1] - fields = {} - for i = 1,ncol do append(fields,'$'..i) end - fields = concat(fields,',') - end - end - local idpat = patterns.IDEN - if numfields then - idpat = '%$(%d+)' - else - -- massage field names to replace non-identifier chars - fields = rstrip(fields):gsub('[^,%w]','_') - end - local massage_fields = utils.bind1(massage_fields,data) - local ret = gsub(fields,idpat,massage_fields) - if field_error then return nil,field_error end - parms.fields = fields - parms.proc_fields = ret - parms.where = parms.where or 'true' - if is_string(parms.where) then - parms.where = gsub(parms.where,idpat,massage_fields) - field_error = nil - end - return true -end - - -parse_select = function(s,data) - local endp - local parms = {} - local w1,w2 = s:find('where ') - local s1,s2 = s:find('sort by ') - if w1 then -- where clause! - endp = (s1 or 0)-1 - parms.where = s:sub(w2+1,endp) - end - if s1 then -- sort by clause (must be last!) - parms.sort_by = s:sub(s2+1) - end - endp = (w1 or s1 or 0)-1 - parms.fields = s:sub(1,endp) - local status,err = process_select(data,parms) - if not status then return nil,err - else return parms end -end - ---- create a query iterator from a select string. --- Select string has this format:
--- FIELDLIST [ where LUA-CONDN [ sort by FIELD] ]
--- FIELDLIST is a comma-separated list of valid fields, or '*'.

--- The condition can also be a table, with fields 'fields' (comma-sep string or --- table), 'sort_by' (string) and 'where' (Lua expression string or function) --- @param data table produced by read --- @param condn select string or table --- @param context a list of tables to be searched when resolving functions --- @param return_row if true, wrap the results in a row table --- @return an iterator over the specified fields, or nil --- @return an error message -function data.query(data,condn,context,return_row) - local err - if is_string(condn) then - condn,err = parse_select(condn,data) - if not condn then return nil,err end - elseif type(condn) == 'table' then - if type(condn.fields) == 'table' then - condn.fields = concat(condn.fields,',') - end - if not condn.proc_fields then - local status,err = process_select(data,condn) - if not status then return nil,err end - end - else - return nil, "condition must be a string or a table" - end - local query - if condn.sort_by then -- use sorted_query - query = sorted_query - else - query = simple_query - end - local fields = condn.proc_fields or condn.fields - if return_row then - fields = '{'..fields..'}' - end - query = query:gsub('FIELDLIST',fields) - if is_string(condn.where) then - query = query:gsub('CONDITION',condn.where) - condn.where = nil - else - query = query:gsub('CONDITION','_condn(v)') - condn.where = function_arg(0,condn.where,'condition.where must be callable') - end - if condn.sort_by then - local expr,sort_var,sort_dir - local sort_by = condn.sort_by - local i1,i2 = sort_by:find('%s+') - if i1 then - sort_var,sort_dir = sort_by:sub(1,i1-1),sort_by:sub(i2+1) - else - sort_var = sort_by - sort_dir = 'asc' - end - if sort_var:match '^%$' then sort_var = sort_var:sub(2) end - sort_var = massage_fields(data,sort_var) - if field_error then return nil,field_error end - if sort_dir == 'asc' then - sort_dir = '<' - else - sort_dir = '>' - end - expr = ('%s %s %s'):format(sort_var:gsub('v','v1'),sort_dir,sort_var:gsub('v','v2')) - query = query:gsub('SORT_EXPR',expr) - end - if condn.where then - query = 'return function(_condn) '..query..' end' - end - if _DEBUG then print(query) end - - local fn,err = utils.load(query,'tmp') - if not fn then return nil,err end - fn = fn() -- get the function - if condn.where then - fn = fn(condn.where) - end - local qfun = fn(data) - if context then - -- [specifying context for condition] @context is a list of tables which are - -- 'injected'into the condition's custom context - append(context,_G) - local lookup = {} - utils.setfenv(qfun,lookup) - setmetatable(lookup,{ - __index = function(tbl,key) - -- _G.print(tbl,key) - for k,t in ipairs(context) do - if t[key] then return t[key] end - end - end - }) - end - return qfun -end - - -DataMT.select = data.query -DataMT.select_row = function(d,condn,context) - return data.query(d,condn,context,true) -end - ---- Filter input using a query. --- @string Q a query string --- @param infile filename or file-like object --- @param outfile filename or file-like object --- @bool dont_fail true if you want to return an error, not just fail -function data.filter (Q,infile,outfile,dont_fail) - local d = data.read(infile or 'stdin') - local out = open_file(outfile or 'stdout') - local iter,err = d:select(Q) - local delim = d.delim - if not iter then - err = 'error: '..err - if dont_fail then - return nil,err - else - utils.quit(1,err) - end - end - while true do - local res = {iter()} - if #res == 0 then break end - out:write(concat(res,delim),'\n') - end -end - -return data - diff --git a/game/scripts/vscripts/pl/dir.lua b/game/scripts/vscripts/pl/dir.lua deleted file mode 100644 index cde16dc..0000000 --- a/game/scripts/vscripts/pl/dir.lua +++ /dev/null @@ -1,527 +0,0 @@ ---- Listing files in directories and creating/removing directory paths. --- --- Dependencies: `pl.utils`, `pl.path` --- --- Soft Dependencies: `alien`, `ffi` (either are used on Windows for copying/moving files) --- @module pl.dir - -local utils = require 'pl.utils' -local path = require 'pl.path' -local is_windows = path.is_windows -local ldir = path.dir -local mkdir = path.mkdir -local rmdir = path.rmdir -local sub = string.sub -local os,pcall,ipairs,pairs,require,setmetatable = os,pcall,ipairs,pairs,require,setmetatable -local remove = os.remove -local append = table.insert -local assert_arg,assert_string,raise = utils.assert_arg,utils.assert_string,utils.raise - -local exists, isdir = path.exists, path.isdir -local sep = path.sep - -local dir = {} - -local function makelist(l) - return setmetatable(l, require('pl.List')) -end - -local function assert_dir (n,val) - assert_arg(n,val,'string',path.isdir,'not a directory',4) -end - -local function filemask(mask) - mask = utils.escape(path.normcase(mask)) - return '^'..mask:gsub('%%%*','.*'):gsub('%%%?','.')..'$' -end - ---- Test whether a file name matches a shell pattern. --- Both parameters are case-normalized if operating system is --- case-insensitive. --- @string filename A file name. --- @string pattern A shell pattern. The only special characters are --- `'*'` and `'?'`: `'*'` matches any sequence of characters and --- `'?'` matches any single character. --- @treturn bool --- @raise dir and mask must be strings -function dir.fnmatch(filename,pattern) - assert_string(1,filename) - assert_string(2,pattern) - return path.normcase(filename):find(filemask(pattern)) ~= nil -end - ---- Return a list of all file names within an array which match a pattern. --- @tab filenames An array containing file names. --- @string pattern A shell pattern (see `fnmatch`). --- @treturn List(string) List of matching file names. --- @raise dir and mask must be strings -function dir.filter(filenames,pattern) - assert_arg(1,filenames,'table') - assert_string(2,pattern) - local res = {} - local mask = filemask(pattern) - for i,f in ipairs(filenames) do - if path.normcase(f):find(mask) then append(res,f) end - end - return makelist(res) -end - -local function _listfiles(dirname,filemode,match) - local res = {} - local check = utils.choose(filemode,path.isfile,path.isdir) - if not dirname then dirname = '.' end - for f in ldir(dirname) do - if f ~= '.' and f ~= '..' then - local p = path.join(dirname,f) - if check(p) and (not match or match(f)) then - append(res,p) - end - end - end - return makelist(res) -end - ---- return a list of all files in a directory which match a shell pattern. --- @string[opt='.'] dirname A directory. --- @string[opt] mask A shell pattern (see `fnmatch`). If not given, all files are returned. --- @treturn {string} list of files --- @raise dirname and mask must be strings -function dir.getfiles(dirname,mask) - dirname = dirname or '.' - assert_dir(1,dirname) - if mask then assert_string(2,mask) end - local match - if mask then - mask = filemask(mask) - match = function(f) - return path.normcase(f):find(mask) - end - end - return _listfiles(dirname,true,match) -end - ---- return a list of all subdirectories of the directory. --- @string[opt='.'] dirname A directory. --- @treturn {string} a list of directories --- @raise dir must be a valid directory -function dir.getdirectories(dirname) - dirname = dirname or '.' - assert_dir(1,dirname) - return _listfiles(dirname,false) -end - -local alien,ffi,ffi_checked,CopyFile,MoveFile,GetLastError,win32_errors,cmd_tmpfile - -local function execute_command(cmd,parms) - if not cmd_tmpfile then cmd_tmpfile = path.tmpname () end - local err = path.is_windows and ' > ' or ' 2> ' - cmd = cmd..' '..parms..err..utils.quote_arg(cmd_tmpfile) - local ret = utils.execute(cmd) - if not ret then - local err = (utils.readfile(cmd_tmpfile):gsub('\n(.*)','')) - remove(cmd_tmpfile) - return false,err - else - remove(cmd_tmpfile) - return true - end -end - -local function find_ffi_copyfile () - if not ffi_checked then - ffi_checked = true - local res - res,alien = pcall(require,'alien') - if not res then - alien = nil - res, ffi = pcall(require,'ffi') - end - if not res then - ffi = nil - return - end - else - return - end - if alien then - -- register the Win32 CopyFile and MoveFile functions - local kernel = alien.load('kernel32.dll') - CopyFile = kernel.CopyFileA - CopyFile:types{'string','string','int',ret='int',abi='stdcall'} - MoveFile = kernel.MoveFileA - MoveFile:types{'string','string',ret='int',abi='stdcall'} - GetLastError = kernel.GetLastError - GetLastError:types{ret ='int', abi='stdcall'} - elseif ffi then - ffi.cdef [[ - int CopyFileA(const char *src, const char *dest, int iovr); - int MoveFileA(const char *src, const char *dest); - int GetLastError(); - ]] - CopyFile = ffi.C.CopyFileA - MoveFile = ffi.C.MoveFileA - GetLastError = ffi.C.GetLastError - end - win32_errors = { - ERROR_FILE_NOT_FOUND = 2, - ERROR_PATH_NOT_FOUND = 3, - ERROR_ACCESS_DENIED = 5, - ERROR_WRITE_PROTECT = 19, - ERROR_BAD_UNIT = 20, - ERROR_NOT_READY = 21, - ERROR_WRITE_FAULT = 29, - ERROR_READ_FAULT = 30, - ERROR_SHARING_VIOLATION = 32, - ERROR_LOCK_VIOLATION = 33, - ERROR_HANDLE_DISK_FULL = 39, - ERROR_BAD_NETPATH = 53, - ERROR_NETWORK_BUSY = 54, - ERROR_DEV_NOT_EXIST = 55, - ERROR_FILE_EXISTS = 80, - ERROR_OPEN_FAILED = 110, - ERROR_INVALID_NAME = 123, - ERROR_BAD_PATHNAME = 161, - ERROR_ALREADY_EXISTS = 183, - } -end - -local function two_arguments (f1,f2) - return utils.quote_arg(f1)..' '..utils.quote_arg(f2) -end - -local function file_op (is_copy,src,dest,flag) - if flag == 1 and path.exists(dest) then - return false,"cannot overwrite destination" - end - if is_windows then - -- if we haven't tried to load Alien/LuaJIT FFI before, then do so - find_ffi_copyfile() - -- fallback if there's no Alien, just use DOS commands *shudder* - -- 'rename' involves a copy and then deleting the source. - if not CopyFile then - if path.is_windows then - src = src:gsub("/","\\") - dest = dest:gsub("/","\\") - end - local res, err = execute_command('copy',two_arguments(src,dest)) - if not res then return false,err end - if not is_copy then - return execute_command('del',utils.quote_arg(src)) - end - return true - else - if path.isdir(dest) then - dest = path.join(dest,path.basename(src)) - end - local ret - if is_copy then ret = CopyFile(src,dest,flag) - else ret = MoveFile(src,dest) end - if ret == 0 then - local err = GetLastError() - for name,value in pairs(win32_errors) do - if value == err then return false,name end - end - return false,"Error #"..err - else return true - end - end - else -- for Unix, just use cp for now - return execute_command(is_copy and 'cp' or 'mv', - two_arguments(src,dest)) - end -end - ---- copy a file. --- @string src source file --- @string dest destination file or directory --- @bool flag true if you want to force the copy (default) --- @treturn bool operation succeeded --- @raise src and dest must be strings -function dir.copyfile (src,dest,flag) - assert_string(1,src) - assert_string(2,dest) - flag = flag==nil or flag - return file_op(true,src,dest,flag and 0 or 1) -end - ---- move a file. --- @string src source file --- @string dest destination file or directory --- @treturn bool operation succeeded --- @raise src and dest must be strings -function dir.movefile (src,dest) - assert_string(1,src) - assert_string(2,dest) - return file_op(false,src,dest,0) -end - -local function _dirfiles(dirname,attrib) - local dirs = {} - local files = {} - for f in ldir(dirname) do - if f ~= '.' and f ~= '..' then - local p = path.join(dirname,f) - local mode = attrib(p,'mode') - if mode=='directory' then - append(dirs,f) - else - append(files,f) - end - end - end - return makelist(dirs), makelist(files) -end - - ---- return an iterator which walks through a directory tree starting at root. --- The iterator returns (root,dirs,files) --- Note that dirs and files are lists of names (i.e. you must say path.join(root,d) --- to get the actual full path) --- If bottom_up is false (or not present), then the entries at the current level are returned --- before we go deeper. This means that you can modify the returned list of directories before --- continuing. --- This is a clone of os.walk from the Python libraries. --- @string root A starting directory --- @bool bottom_up False if we start listing entries immediately. --- @bool follow_links follow symbolic links --- @return an iterator returning root,dirs,files --- @raise root must be a directory -function dir.walk(root,bottom_up,follow_links) - assert_dir(1,root) - local attrib - if path.is_windows or not follow_links then - attrib = path.attrib - else - attrib = path.link_attrib - end - - local to_scan = { root } - local to_return = {} - local iter = function() - while #to_scan > 0 do - local current_root = table.remove(to_scan) - local dirs,files = _dirfiles(current_root, attrib) - for _, d in ipairs(dirs) do - table.insert(to_scan, current_root..path.sep..d) - end - if not bottom_up then - return current_root, dirs, files - else - table.insert(to_return, { current_root, dirs, files }) - end - end - if #to_return > 0 then - return utils.unpack(table.remove(to_return)) - end - end - - return iter -end - ---- remove a whole directory tree. --- Symlinks in the tree will be deleted without following them. --- @string fullpath A directory path (must be an actual directory, not a symlink) --- @return true or nil --- @return error if failed --- @raise fullpath must be a string -function dir.rmtree(fullpath) - assert_dir(1,fullpath) - if path.islink(fullpath) then return false,'will not follow symlink' end - for root,dirs,files in dir.walk(fullpath,true) do - if path.islink(root) then - -- sub dir is a link, remove link, do not follow - if is_windows then - -- Windows requires using "rmdir". Deleting the link like a file - -- will instead delete all files from the target directory!! - local res, err = rmdir(root) - if not res then return nil,err .. ": " .. root end - else - local res, err = remove(root) - if not res then return nil,err .. ": " .. root end - end - else - for i,f in ipairs(files) do - local res, err = remove(path.join(root,f)) - if not res then return nil,err .. ": " .. path.join(root,f) end - end - local res, err = rmdir(root) - if not res then return nil,err .. ": " .. root end - end - end - return true -end - - -do - local dirpat - if path.is_windows then - dirpat = '(.+)\\[^\\]+$' - else - dirpat = '(.+)/[^/]+$' - end - - local _makepath - function _makepath(p) - -- windows root drive case - if p:find '^%a:[\\]*$' then - return true - end - if not path.isdir(p) then - local subp = p:match(dirpat) - if subp then - local ok, err = _makepath(subp) - if not ok then return nil, err end - end - return mkdir(p) - else - return true - end - end - - --- create a directory path. - -- This will create subdirectories as necessary! - -- @string p A directory path - -- @return true on success, nil + errormsg on failure - -- @raise failure to create - function dir.makepath (p) - assert_string(1,p) - if path.is_windows then - p = p:gsub("/", "\\") - end - return _makepath(path.abspath(p)) - end -end - ---- clone a directory tree. Will always try to create a new directory structure --- if necessary. --- @string path1 the base path of the source tree --- @string path2 the new base path for the destination --- @func file_fun an optional function to apply on all files --- @bool verbose an optional boolean to control the verbosity of the output. --- It can also be a logging function that behaves like print() --- @return true, or nil --- @return error message, or list of failed directory creations --- @return list of failed file operations --- @raise path1 and path2 must be strings --- @usage clonetree('.','../backup',copyfile) -function dir.clonetree (path1,path2,file_fun,verbose) - assert_string(1,path1) - assert_string(2,path2) - if verbose == true then verbose = print end - local abspath,normcase,isdir,join = path.abspath,path.normcase,path.isdir,path.join - local faildirs,failfiles = {},{} - if not isdir(path1) then return raise 'source is not a valid directory' end - path1 = abspath(normcase(path1)) - path2 = abspath(normcase(path2)) - if verbose then verbose('normalized:',path1,path2) end - -- particularly NB that the new path isn't fully contained in the old path - if path1 == path2 then return raise "paths are the same" end - local _,i2 = path2:find(path1,1,true) - if i2 == #path1 and path2:sub(i2+1,i2+1) == path.sep then - return raise 'destination is a subdirectory of the source' - end - local cp = path.common_prefix (path1,path2) - local idx = #cp - if idx == 0 then -- no common path, but watch out for Windows paths! - if path1:sub(2,2) == ':' then idx = 3 end - end - for root,dirs,files in dir.walk(path1) do - local opath = path2..root:sub(idx) - if verbose then verbose('paths:',opath,root) end - if not isdir(opath) then - local ret = dir.makepath(opath) - if not ret then append(faildirs,opath) end - if verbose then verbose('creating:',opath,ret) end - end - if file_fun then - for i,f in ipairs(files) do - local p1 = join(root,f) - local p2 = join(opath,f) - local ret = file_fun(p1,p2) - if not ret then append(failfiles,p2) end - if verbose then - verbose('files:',p1,p2,ret) - end - end - end - end - return true,faildirs,failfiles -end - - --- each entry of the stack is an array with three items: --- 1. the name of the directory --- 2. the lfs iterator function --- 3. the lfs iterator userdata -local function treeiter(iterstack) - local diriter = iterstack[#iterstack] - if not diriter then - return -- done - end - - local dirname = diriter[1] - local entry = diriter[2](diriter[3]) - if not entry then - table.remove(iterstack) - return treeiter(iterstack) -- tail-call to try next - end - - if entry ~= "." and entry ~= ".." then - entry = dirname .. sep .. entry - if exists(entry) then -- Just in case a symlink is broken. - local is_dir = isdir(entry) - if is_dir then - table.insert(iterstack, { entry, ldir(entry) }) - end - return entry, is_dir - end - end - - return treeiter(iterstack) -- tail-call to try next -end - - ---- return an iterator over all entries in a directory tree --- @string d a directory --- @return an iterator giving pathname and mode (true for dir, false otherwise) --- @raise d must be a non-empty string -function dir.dirtree( d ) - assert( d and d ~= "", "directory parameter is missing or empty" ) - - local last = sub ( d, -1 ) - if last == sep or last == '/' then - d = sub( d, 1, -2 ) - end - - local iterstack = { {d, ldir(d)} } - - return treeiter, iterstack -end - - ---- Recursively returns all the file starting at 'path'. It can optionally take a shell pattern and --- only returns files that match 'shell_pattern'. If a pattern is given it will do a case insensitive search. --- @string[opt='.'] start_path A directory. --- @string[opt='*'] shell_pattern A shell pattern (see `fnmatch`). --- @treturn List(string) containing all the files found recursively starting at 'path' and filtered by 'shell_pattern'. --- @raise start_path must be a directory -function dir.getallfiles( start_path, shell_pattern ) - start_path = start_path or '.' - assert_dir(1,start_path) - shell_pattern = shell_pattern or "*" - - local files = {} - local normcase = path.normcase - for filename, mode in dir.dirtree( start_path ) do - if not mode then - local mask = filemask( shell_pattern ) - if normcase(filename):find( mask ) then - files[#files + 1] = filename - end - end - end - - return makelist(files) -end - -return dir diff --git a/game/scripts/vscripts/pl/file.lua b/game/scripts/vscripts/pl/file.lua deleted file mode 100644 index b8058c4..0000000 --- a/game/scripts/vscripts/pl/file.lua +++ /dev/null @@ -1,55 +0,0 @@ ---- File manipulation functions: reading, writing, moving and copying. --- --- This module wraps a number of functions from other modules into a --- file related module for convenience. --- --- Dependencies: `pl.utils`, `pl.dir`, `pl.path` --- @module pl.file -local os = os -local utils = require 'pl.utils' -local dir = require 'pl.dir' -local path = require 'pl.path' - -local file = {} - ---- return the contents of a file as a string. --- This function is a copy of `utils.readfile`. --- @function file.read -file.read = utils.readfile - ---- write a string to a file. --- This function is a copy of `utils.writefile`. --- @function file.write -file.write = utils.writefile - ---- copy a file. --- This function is a copy of `dir.copyfile`. --- @function file.copy -file.copy = dir.copyfile - ---- move a file. --- This function is a copy of `dir.movefile`. --- @function file.move -file.move = dir.movefile - ---- Return the time of last access as the number of seconds since the epoch. --- This function is a copy of `path.getatime`. --- @function file.access_time -file.access_time = path.getatime - ----Return when the file was created. --- This function is a copy of `path.getctime`. --- @function file.creation_time -file.creation_time = path.getctime - ---- Return the time of last modification. --- This function is a copy of `path.getmtime`. --- @function file.modified_time -file.modified_time = path.getmtime - ---- Delete a file. --- This function is a copy of `os.remove`. --- @function file.delete -file.delete = os.remove - -return file diff --git a/game/scripts/vscripts/pl/func.lua b/game/scripts/vscripts/pl/func.lua deleted file mode 100644 index daac0fc..0000000 --- a/game/scripts/vscripts/pl/func.lua +++ /dev/null @@ -1,393 +0,0 @@ ---- Functional helpers like composition, binding and placeholder expressions. --- Placeholder expressions are useful for short anonymous functions, and were --- inspired by the Boost Lambda library. --- --- > utils.import 'pl.func' --- > ls = List{10,20,30} --- > = ls:map(_1+1) --- {11,21,31} --- --- They can also be used to _bind_ particular arguments of a function. --- --- > p = bind(print,'start>',_0) --- > p(10,20,30) --- > start> 10 20 30 --- --- See @{07-functional.md.Creating_Functions_from_Functions|the Guide} --- --- Dependencies: `pl.utils`, `pl.tablex` --- @module pl.func -local type,setmetatable,getmetatable,rawset = type,setmetatable,getmetatable,rawset -local concat,append = table.concat,table.insert -local tostring = tostring -local utils = require 'pl.utils' -local pairs,rawget,unpack,pack = pairs,rawget,utils.unpack,utils.pack -local tablex = require 'pl.tablex' -local map = tablex.map -local _DEBUG = rawget(_G,'_DEBUG') -local assert_arg = utils.assert_arg - -local func = {} - --- metatable for Placeholder Expressions (PE) -local _PEMT = {} - -local function P (t) - setmetatable(t,_PEMT) - return t -end - -func.PE = P - -local function isPE (obj) - return getmetatable(obj) == _PEMT -end - -func.isPE = isPE - --- construct a placeholder variable (e.g _1 and _2) -local function PH (idx) - return P {op='X',repr='_'..idx, index=idx} -end - --- construct a constant placeholder variable (e.g _C1 and _C2) -local function CPH (idx) - return P {op='X',repr='_C'..idx, index=idx} -end - -func._1,func._2,func._3,func._4,func._5 = PH(1),PH(2),PH(3),PH(4),PH(5) -func._0 = P{op='X',repr='...',index=0} - -function func.Var (name) - local ls = utils.split(name,'[%s,]+') - local res = {} - for i = 1, #ls do - append(res,P{op='X',repr=ls[i],index=0}) - end - return unpack(res) -end - -function func._ (value) - return P{op='X',repr=value,index='wrap'} -end - -local repr - -func.Nil = func.Var 'nil' - -function _PEMT.__index(obj,key) - return P{op='[]',obj,key} -end - -function _PEMT.__call(fun,...) - return P{op='()',fun,...} -end - -function _PEMT.__tostring (e) - return repr(e) -end - -function _PEMT.__unm(arg) - return P{op='unm',arg} -end - -function func.Not (arg) - return P{op='not',arg} -end - -function func.Len (arg) - return P{op='#',arg} -end - - -local function binreg(context,t) - for name,op in pairs(t) do - rawset(context,name,function(x,y) - return P{op=op,x,y} - end) - end -end - -local function import_name (name,fun,context) - rawset(context,name,function(...) - return P{op='()',fun,...} - end) -end - -local imported_functions = {} - -local function is_global_table (n) - return type(_G[n]) == 'table' -end - ---- wrap a table of functions. This makes them available for use in --- placeholder expressions. --- @string tname a table name --- @tab context context to put results, defaults to environment of caller -function func.import(tname,context) - assert_arg(1,tname,'string',is_global_table,'arg# 1: not a name of a global table') - local t = _G[tname] - context = context or _G - for name,fun in pairs(t) do - import_name(name,fun,context) - imported_functions[fun] = name - end -end - ---- register a function for use in placeholder expressions. --- @func fun a function --- @string[opt] name an optional name --- @return a placeholder functiond -function func.register (fun,name) - assert_arg(1,fun,'function') - if name then - assert_arg(2,name,'string') - imported_functions[fun] = name - end - return function(...) - return P{op='()',fun,...} - end -end - -function func.lookup_imported_name (fun) - return imported_functions[fun] -end - -local function _arg(...) return ... end - -function func.Args (...) - return P{op='()',_arg,...} -end - --- binary operators with their precedences (see Lua manual) --- precedences might be incremented by one before use depending on --- left- or right-associativity, space them out -local binary_operators = { - ['or'] = 0, - ['and'] = 2, - ['=='] = 4, ['~='] = 4, ['<'] = 4, ['>'] = 4, ['<='] = 4, ['>='] = 4, - ['..'] = 6, - ['+'] = 8, ['-'] = 8, - ['*'] = 10, ['/'] = 10, ['%'] = 10, - ['^'] = 14 -} - --- unary operators with their precedences -local unary_operators = { - ['not'] = 12, ['#'] = 12, ['unm'] = 12 -} - --- comparisons (as prefix functions) -binreg (func,{And='and',Or='or',Eq='==',Lt='<',Gt='>',Le='<=',Ge='>='}) - --- standard binary operators (as metamethods) -binreg (_PEMT,{__add='+',__sub='-',__mul='*',__div='/',__mod='%',__pow='^',__concat='..'}) - -binreg (_PEMT,{__eq='=='}) - ---- all elements of a table except the first. --- @tab ls a list-like table. -function func.tail (ls) - assert_arg(1,ls,'table') - local res = {} - for i = 2,#ls do - append(res,ls[i]) - end - return res -end - ---- create a string representation of a placeholder expression. --- @param e a placeholder expression --- @param lastpred not used -function repr (e,lastpred) - local tail = func.tail - if isPE(e) then - local pred = binary_operators[e.op] or unary_operators[e.op] - if pred then - -- binary or unary operator - local s - if binary_operators[e.op] then - local left_pred = pred - local right_pred = pred - if e.op == '..' or e.op == '^' then - left_pred = left_pred + 1 - else - right_pred = right_pred + 1 - end - local left_arg = repr(e[1], left_pred) - local right_arg = repr(e[2], right_pred) - s = left_arg..' '..e.op..' '..right_arg - else - local op = e.op == 'unm' and '-' or e.op - s = op..' '..repr(e[1], pred) - end - if lastpred and lastpred > pred then - s = '('..s..')' - end - return s - else -- either postfix, or a placeholder - local ls = map(repr,e) - if e.op == '[]' then - return ls[1]..'['..ls[2]..']' - elseif e.op == '()' then - local fn - if ls[1] ~= nil then -- was _args, undeclared! - fn = ls[1] - else - fn = '' - end - return fn..'('..concat(tail(ls),',')..')' - else - return e.repr - end - end - elseif type(e) == 'string' then - return '"'..e..'"' - elseif type(e) == 'function' then - local name = func.lookup_imported_name(e) - if name then return name else return tostring(e) end - else - return tostring(e) --should not really get here! - end -end -func.repr = repr - --- collect all the non-PE values in this PE into vlist, and replace each occurence --- with a constant PH (_C1, etc). Return the maximum placeholder index found. -local collect_values -function collect_values (e,vlist) - if isPE(e) then - if e.op ~= 'X' then - local m = 0 - for i = 1,#e do - local subx = e[i] - local pe = isPE(subx) - if pe then - if subx.op == 'X' and subx.index == 'wrap' then - subx = subx.repr - pe = false - else - m = math.max(m,collect_values(subx,vlist)) - end - end - if not pe then - append(vlist,subx) - e[i] = CPH(#vlist) - end - end - return m - else -- was a placeholder, it has an index... - return e.index - end - else -- plain value has no placeholder dependence - return 0 - end -end -func.collect_values = collect_values - ---- instantiate a PE into an actual function. First we find the largest placeholder used, --- e.g. _2; from this a list of the formal parameters can be build. Then we collect and replace --- any non-PE values from the PE, and build up a constant binding list. --- Finally, the expression can be compiled, and e.__PE_function is set. --- @param e a placeholder expression --- @return a function -function func.instantiate (e) - local consts,values,parms = {},{},{} - local rep, err, fun - local n = func.collect_values(e,values) - for i = 1,#values do - append(consts,'_C'..i) - if _DEBUG then print(i,values[i]) end - end - for i =1,n do - append(parms,'_'..i) - end - consts = concat(consts,',') - parms = concat(parms,',') - rep = repr(e) - local fstr = ('return function(%s) return function(%s) return %s end end'):format(consts,parms,rep) - if _DEBUG then print(fstr) end - fun,err = utils.load(fstr,'fun') - if not fun then return nil,err end - fun = fun() -- get wrapper - fun = fun(unpack(values)) -- call wrapper (values could be empty) - e.__PE_function = fun - return fun -end - ---- instantiate a PE unless it has already been done. --- @param e a placeholder expression --- @return the function -function func.I(e) - if rawget(e,'__PE_function') then - return e.__PE_function - else return func.instantiate(e) - end -end - -utils.add_function_factory(_PEMT,func.I) - ---- bind the first parameter of the function to a value. --- @function func.bind1 --- @func fn a function of one or more arguments --- @param p a value --- @return a function of one less argument --- @usage (bind1(math.max,10))(20) == math.max(10,20) -func.bind1 = utils.bind1 -func.curry = func.bind1 - ---- create a function which chains two functions. --- @func f a function of at least one argument --- @func g a function of at least one argument --- @return a function --- @usage printf = compose(io.write,string.format) -function func.compose (f,g) - return function(...) return f(g(...)) end -end - ---- bind the arguments of a function to given values. --- `bind(fn,v,_2)` is equivalent to `bind1(fn,v)`. --- @func fn a function of at least one argument --- @param ... values or placeholder variables --- @return a function --- @usage (bind(f,_1,a))(b) == f(a,b) --- @usage (bind(f,_2,_1))(a,b) == f(b,a) -function func.bind(fn,...) - local args = pack(...) - local holders,parms,bvalues,values = {},{},{'fn'},{} - local nv,maxplace,varargs = 1,0,false - for i = 1,args.n do - local a = args[i] - if isPE(a) and a.op == 'X' then - append(holders,a.repr) - maxplace = math.max(maxplace,a.index) - if a.index == 0 then varargs = true end - else - local v = '_v'..nv - append(bvalues,v) - append(holders,v) - append(values,a) - nv = nv + 1 - end - end - for np = 1,maxplace do - append(parms,'_'..np) - end - if varargs then append(parms,'...') end - bvalues = concat(bvalues,',') - parms = concat(parms,',') - holders = concat(holders,',') - local fstr = ([[ -return function (%s) - return function(%s) return fn(%s) end -end -]]):format(bvalues,parms,holders) - if _DEBUG then print(fstr) end - local res = utils.load(fstr) - res = res() - return res(fn,unpack(values)) -end - -return func - - diff --git a/game/scripts/vscripts/pl/import_into.lua b/game/scripts/vscripts/pl/import_into.lua deleted file mode 100644 index 46aaa3e..0000000 --- a/game/scripts/vscripts/pl/import_into.lua +++ /dev/null @@ -1,91 +0,0 @@ --------------- --- PL loader, for loading all PL libraries, only on demand. --- Whenever a module is implicitly accesssed, the table will have the module automatically injected. --- (e.g. `_ENV.tablex`) --- then that module is dynamically loaded. The submodules are all brought into --- the table that is provided as the argument, or returned in a new table. --- If a table is provided, that table's metatable is clobbered, but the values are not. --- This module returns a single function, which is passed the environment. --- If this is `true`, then return a 'shadow table' as the module --- See @{01-introduction.md.To_Inject_or_not_to_Inject_|the Guide} - --- @module pl.import_into - -return function(env) - local mod - if env == true then - mod = {} - env = {} - end - local env = env or {} - - local modules = { - utils = true,path=true,dir=true,tablex=true,stringio=true,sip=true, - input=true,seq=true,lexer=true,stringx=true, - config=true,pretty=true,data=true,func=true,text=true, - operator=true,lapp=true,array2d=true, - comprehension=true,xml=true,types=true, - test = true, app = true, file = true, class = true, - luabalanced = true, permute = true, template = true, - url = true, compat = true, - -- classes -- - List = true, Map = true, Set = true, - OrderedMap = true, MultiMap = true, Date = true, - } - rawset(env,'utils',require 'pl.utils') - - for name,klass in pairs(env.utils.stdmt) do - klass.__index = function(t,key) - return require ('pl.'..name)[key] - end; - end - - -- ensure that we play nice with libraries that also attach a metatable - -- to the global table; always forward to a custom __index if we don't - -- match - - local _hook,_prev_index - local gmt = {} - local prevenvmt = getmetatable(env) - if prevenvmt then - _prev_index = prevenvmt.__index - if prevenvmt.__newindex then - gmt.__newindex = prevenvmt.__newindex - end - end - - function gmt.hook(handler) - _hook = handler - end - - function gmt.__index(t,name) - local found = modules[name] - -- either true, or the name of the module containing this class. - -- either way, we load the required module and make it globally available. - if found then - -- e..g pretty.dump causes pl.pretty to become available as 'pretty' - rawset(env,name,require('pl.'..name)) - return env[name] - else - local res - if _hook then - res = _hook(t,name) - if res then return res end - end - if _prev_index then - return _prev_index(t,name) - end - end - end - - if mod then - function gmt.__newindex(t,name,value) - mod[name] = value - rawset(t,name,value) - end - end - - setmetatable(env,gmt) - - return env,mod or env -end diff --git a/game/scripts/vscripts/pl/init.lua b/game/scripts/vscripts/pl/init.lua deleted file mode 100644 index c27a890..0000000 --- a/game/scripts/vscripts/pl/init.lua +++ /dev/null @@ -1,11 +0,0 @@ --------------- --- Entry point for loading all PL libraries only on demand, into the global space. --- Requiring 'pl' means that whenever a module is implicitly accesssed --- (e.g. `utils.split`) --- then that module is dynamically loaded. The submodules are all brought into --- the global space. ---Updated to use @{pl.import_into} --- @module pl -require'pl.import_into'(_G) - -if rawget(_G,'PENLIGHT_STRICT') then require 'pl.strict' end diff --git a/game/scripts/vscripts/pl/input.lua b/game/scripts/vscripts/pl/input.lua deleted file mode 100644 index f81de87..0000000 --- a/game/scripts/vscripts/pl/input.lua +++ /dev/null @@ -1,171 +0,0 @@ ---- Iterators for extracting words or numbers from an input source. --- --- require 'pl' --- local total,n = seq.sum(input.numbers()) --- print('average',total/n) --- --- _source_ is defined as a string or a file-like object (i.e. has a read() method which returns the next line) --- --- See @{06-data.md.Reading_Unstructured_Text_Data|here} --- --- Dependencies: `pl.utils` --- @module pl.input -local strfind = string.find -local strsub = string.sub -local strmatch = string.match -local utils = require 'pl.utils' -local unpack = utils.unpack -local pairs,type,tonumber = pairs,type,tonumber -local patterns = utils.patterns -local io = io - -local input = {} - ---- create an iterator over all tokens. --- based on allwords from PiL, 7.1 --- @func getter any function that returns a line of text --- @string pattern --- @string[opt] fn Optionally can pass a function to process each token as it's found. --- @return an iterator -function input.alltokens (getter,pattern,fn) - local line = getter() -- current line - local pos = 1 -- current position in the line - return function () -- iterator function - while line do -- repeat while there are lines - local s, e = strfind(line, pattern, pos) - if s then -- found a word? - pos = e + 1 -- next position is after this token - local res = strsub(line, s, e) -- return the token - if fn then res = fn(res) end - return res - else - line = getter() -- token not found; try next line - pos = 1 -- restart from first position - end - end - return nil -- no more lines: end of traversal - end -end -local alltokens = input.alltokens - --- question: shd this _split_ a string containing line feeds? - ---- create a function which grabs the next value from a source. If the source is a string, then the getter --- will return the string and thereafter return nil. If not specified then the source is assumed to be stdin. --- @param f a string or a file-like object (i.e. has a read() method which returns the next line) --- @return a getter function -function input.create_getter(f) - if f then - if type(f) == 'string' then - local ls = utils.split(f,'\n') - local i,n = 0,#ls - return function() - i = i + 1 - if i > n then return nil end - return ls[i] - end - else - -- anything that supports the read() method! - if not f.read then error('not a file-like object') end - return function() return f:read() end - end - else - return io.read -- i.e. just read from stdin - end -end - ---- generate a sequence of numbers from a source. --- @param f A source --- @return An iterator -function input.numbers(f) - return alltokens(input.create_getter(f), - '('..patterns.FLOAT..')',tonumber) -end - ---- generate a sequence of words from a source. --- @param f A source --- @return An iterator -function input.words(f) - return alltokens(input.create_getter(f),"%w+") -end - -local function apply_tonumber (no_fail,...) - local args = {...} - for i = 1,#args do - local n = tonumber(args[i]) - if n == nil then - if not no_fail then return nil,args[i] end - else - args[i] = n - end - end - return args -end - ---- parse an input source into fields. --- By default, will fail if it cannot convert a field to a number. --- @param ids a list of field indices, or a maximum field index --- @string delim delimiter to parse fields (default space) --- @param f a source @see create_getter --- @tab opts option table, `{no_fail=true}` --- @return an iterator with the field values --- @usage for x,y in fields {2,3} do print(x,y) end -- 2nd and 3rd fields from stdin -function input.fields (ids,delim,f,opts) - local sep - local s - local getter = input.create_getter(f) - local no_fail = opts and opts.no_fail - local no_convert = opts and opts.no_convert - if not delim or delim == ' ' then - delim = '%s' - sep = '%s+' - s = '%s*' - else - sep = delim - s = '' - end - local max_id = 0 - if type(ids) == 'table' then - for i,id in pairs(ids) do - if id > max_id then max_id = id end - end - else - max_id = ids - ids = {} - for i = 1,max_id do ids[#ids+1] = i end - end - local pat = '[^'..delim..']*' - local k = 1 - for i = 1,max_id do - if ids[k] == i then - k = k + 1 - s = s..'('..pat..')' - else - s = s..pat - end - if i < max_id then - s = s..sep - end - end - local linecount = 1 - return function() - local line,results,err - repeat - line = getter() - linecount = linecount + 1 - if not line then return nil end - if no_convert then - results = {strmatch(line,s)} - else - results,err = apply_tonumber(no_fail,strmatch(line,s)) - if not results then - utils.quit("line "..(linecount-1)..": cannot convert '"..err.."' to number") - end - end - until #results > 0 - return unpack(results) - end -end - -return input - diff --git a/game/scripts/vscripts/pl/lapp.lua b/game/scripts/vscripts/pl/lapp.lua deleted file mode 100644 index 3bd752d..0000000 --- a/game/scripts/vscripts/pl/lapp.lua +++ /dev/null @@ -1,458 +0,0 @@ ---- Simple command-line parsing using human-readable specification. --- Supports GNU-style parameters. --- --- lapp = require 'pl.lapp' --- local args = lapp [[ --- Does some calculations --- -o,--offset (default 0.0) Offset to add to scaled number --- -s,--scale (number) Scaling factor --- (number) Number to be scaled --- ]] --- --- print(args.offset + args.scale * args.number) --- --- Lines beginning with `'-'` are flags; there may be a short and a long name; --- lines beginning with `''` are arguments. Anything in parens after --- the flag/argument is either a default, a type name or a range constraint. --- --- See @{08-additional.md.Command_line_Programs_with_Lapp|the Guide} --- --- Dependencies: `pl.sip` --- @module pl.lapp - -local status,sip = pcall(require,'pl.sip') -if not status then - sip = require 'sip' -end -local match = sip.match_at_start -local append,tinsert = table.insert,table.insert - -sip.custom_pattern('X','(%a[%w_%-]*)') - -local function lines(s) return s:gmatch('([^\n]*)\n') end -local function lstrip(str) return str:gsub('^%s+','') end -local function strip(str) return lstrip(str):gsub('%s+$','') end -local function at(s,k) return s:sub(k,k) end - -local lapp = {} - -local open_files,parms,aliases,parmlist,usage,script - -lapp.callback = false -- keep Strict happy - -local filetypes = { - stdin = {io.stdin,'file-in'}, stdout = {io.stdout,'file-out'}, - stderr = {io.stderr,'file-out'} -} - ---- controls whether to dump usage on error. --- Defaults to true -lapp.show_usage_error = true - ---- quit this script immediately. --- @string msg optional message --- @bool no_usage suppress 'usage' display -function lapp.quit(msg,no_usage) - if no_usage == 'throw' then - error(msg) - end - if msg then - io.stderr:write(msg..'\n\n') - end - if not no_usage then - io.stderr:write(usage) - end - os.exit(1) -end - ---- print an error to stderr and quit. --- @string msg a message --- @bool no_usage suppress 'usage' display -function lapp.error(msg,no_usage) - if not lapp.show_usage_error then - no_usage = true - elseif lapp.show_usage_error == 'throw' then - no_usage = 'throw' - end - lapp.quit(script..': '..msg,no_usage) -end - ---- open a file. --- This will quit on error, and keep a list of file objects for later cleanup. --- @string file filename --- @string[opt] opt same as second parameter of `io.open` -function lapp.open (file,opt) - local val,err = io.open(file,opt) - if not val then lapp.error(err,true) end - append(open_files,val) - return val -end - ---- quit if the condition is false. --- @bool condn a condition --- @string msg message text -function lapp.assert(condn,msg) - if not condn then - lapp.error(msg) - end -end - -local function range_check(x,min,max,parm) - lapp.assert(min <= x and max >= x,parm..' out of range') -end - -local function xtonumber(s) - local val = tonumber(s) - if not val then lapp.error("unable to convert to number: "..s) end - return val -end - -local types = {} - -local builtin_types = {string=true,number=true,['file-in']='file',['file-out']='file',boolean=true} - -local function convert_parameter(ps,val) - if ps.converter then - val = ps.converter(val) - end - if ps.type == 'number' then - val = xtonumber(val) - elseif builtin_types[ps.type] == 'file' then - val = lapp.open(val,(ps.type == 'file-in' and 'r') or 'w' ) - elseif ps.type == 'boolean' then - return val - end - if ps.constraint then - ps.constraint(val) - end - return val -end - ---- add a new type to Lapp. These appear in parens after the value like --- a range constraint, e.g. ' (integer) Process PID' --- @string name name of type --- @param converter either a function to convert values, or a Lua type name. --- @func[opt] constraint optional function to verify values, should use lapp.error --- if failed. -function lapp.add_type (name,converter,constraint) - types[name] = {converter=converter,constraint=constraint} -end - -local function force_short(short) - lapp.assert(#short==1,short..": short parameters should be one character") -end - --- deducing type of variable from default value; -local function process_default (sval,vtype) - local val, success - if not vtype or vtype == 'number' then - val = tonumber(sval) - end - if val then -- we have a number! - return val,'number' - elseif filetypes[sval] then - local ft = filetypes[sval] - return ft[1],ft[2] - else - if sval == 'true' and not vtype then - return true, 'boolean' - end - if sval:match '^["\']' then sval = sval:sub(2,-2) end - - local ps = types[vtype] or {} - ps.type = vtype - - local show_usage_error = lapp.show_usage_error - lapp.show_usage_error = "throw" - success, val = pcall(convert_parameter, ps, sval) - lapp.show_usage_error = show_usage_error - if success then - return val, vtype or 'string' - end - - return sval,vtype or 'string' - end -end - ---- process a Lapp options string. --- Usually called as `lapp()`. --- @string str the options text --- @tparam {string} args a table of arguments (default is `_G.arg`) --- @return a table with parameter-value pairs -function lapp.process_options_string(str,args) - local results = {} - local varargs - local arg = args or _G.arg - open_files = {} - parms = {} - aliases = {} - parmlist = {} - - local function check_varargs(s) - local res,cnt = s:gsub('^%.%.%.%s*','') - return res, (cnt > 0) - end - - local function set_result(ps,parm,val) - parm = type(parm) == "string" and parm:gsub("%W", "_") or parm -- so foo-bar becomes foo_bar in Lua - if not ps.varargs then - results[parm] = val - else - if not results[parm] then - results[parm] = { val } - else - append(results[parm],val) - end - end - end - - usage = str - - for _,a in ipairs(arg) do - if a == "-h" or a == "--help" then - return lapp.quit() - end - end - - - for line in lines(str) do - local res = {} - local optparm,defval,vtype,constraint,rest - line = lstrip(line) - local function check(str) - return match(str,line,res) - end - - -- flags: either '-', '-,--' or '--' - if check '-$v{short}, --$o{long} $' or check '-$v{short} $' or check '--$o{long} $' then - if res.long then - optparm = res.long:gsub('[^%w%-]','_') -- I'm not sure the $o pattern will let anything else through? - if #res.rest == 1 then optparm = optparm .. res.rest end - if res.short then aliases[res.short] = optparm end - else - optparm = res.short - end - if res.short and not lapp.slack then force_short(res.short) end - res.rest, varargs = check_varargs(res.rest) - elseif check '$<{name} $' then -- is it ? - -- so becomes input_file ... - optparm,rest = res.name:match '([^%.]+)(.*)' - -- follow lua legal variable names - optparm = optparm:sub(1,1):gsub('%A','_') .. optparm:sub(2):gsub('%W', '_') - varargs = rest == '...' - append(parmlist,optparm) - end - -- this is not a pure doc line and specifies the flag/parameter type - if res.rest then - line = res.rest - res = {} - local optional - local defval_str - -- do we have ([optional] [] [default ])? - if match('$({def} $',line,res) or match('$({def}',line,res) then - local typespec = strip(res.def) - local ftype, rest = typespec:match('^(%S+)(.*)$') - rest = strip(rest) - if ftype == 'optional' then - ftype, rest = rest:match('^(%S+)(.*)$') - rest = strip(rest) - optional = true - end - local default - if ftype == 'default' then - default = true - if rest == '' then lapp.error("value must follow default") end - else -- a type specification - if match('$f{min}..$f{max}',ftype,res) then - -- a numerical range like 1..10 - local min,max = res.min,res.max - vtype = 'number' - constraint = function(x) - range_check(x,min,max,optparm) - end - elseif not ftype:match '|' then -- plain type - vtype = ftype - else - -- 'enum' type is a string which must belong to - -- one of several distinct values - local enums = ftype - local enump = '|' .. enums .. '|' - vtype = 'string' - constraint = function(s) - lapp.assert(enump:find('|'..s..'|', 1, true), - "value '"..s.."' not in "..enums - ) - end - end - end - res.rest = rest - typespec = res.rest - -- optional 'default value' clause. Type is inferred as - -- 'string' or 'number' if there's no explicit type - if default or match('default $r{rest}',typespec,res) then - defval_str = res.rest - defval,vtype = process_default(res.rest,vtype) - end - else -- must be a plain flag, no extra parameter required - defval = false - vtype = 'boolean' - end - local ps = { - type = vtype, - defval = defval, - defval_str = defval_str, - required = defval == nil and not optional, - comment = res.rest or optparm, - constraint = constraint, - varargs = varargs - } - varargs = nil - if types[vtype] then - local converter = types[vtype].converter - if type(converter) == 'string' then - ps.type = converter - else - ps.converter = converter - end - ps.constraint = types[vtype].constraint - elseif not builtin_types[vtype] and vtype then - lapp.error(vtype.." is unknown type") - end - parms[optparm] = ps - end - end - -- cool, we have our parms, let's parse the command line args - local iparm = 1 - local iextra = 1 - local i = 1 - local parm,ps,val - local end_of_flags = false - - local function check_parm (parm) - local eqi = parm:find '[=:]' - if eqi then - tinsert(arg,i+1,parm:sub(eqi+1)) - parm = parm:sub(1,eqi-1) - end - return parm,eqi - end - - local function is_flag (parm) - return parms[aliases[parm] or parm] - end - - while i <= #arg do - local theArg = arg[i] - local res = {} - -- after '--' we don't parse args and they end up in - -- the array part of the result (args[1] etc) - if theArg == '--' then - end_of_flags = true - iparm = #parmlist + 1 - i = i + 1 - theArg = arg[i] - if not theArg then - break - end - end - -- look for a flag, - or -- - if not end_of_flags and (match('--$S{long}',theArg,res) or match('-$S{short}',theArg,res)) then - if res.long then -- long option - parm = check_parm(res.long) - elseif #res.short == 1 or is_flag(res.short) then - parm = res.short - else - local parmstr,eq = check_parm(res.short) - if not eq then - parm = at(parmstr,1) - local flag = is_flag(parm) - if flag and flag.type ~= 'boolean' then - --if isdigit(at(parmstr,2)) then - -- a short option followed by a digit is an exception (for AW;)) - -- push ahead into the arg array - tinsert(arg,i+1,parmstr:sub(2)) - else - -- push multiple flags into the arg array! - for k = 2,#parmstr do - tinsert(arg,i+k-1,'-'..at(parmstr,k)) - end - end - else - parm = parmstr - end - end - if aliases[parm] then parm = aliases[parm] end - if not parms[parm] and (parm == 'h' or parm == 'help') then - lapp.quit() - end - else -- a parameter - parm = parmlist[iparm] - if not parm then - -- extra unnamed parameters are indexed starting at 1 - parm = iextra - ps = { type = 'string' } - parms[parm] = ps - iextra = iextra + 1 - else - ps = parms[parm] - end - if not ps.varargs then - iparm = iparm + 1 - end - val = theArg - end - ps = parms[parm] - if not ps then lapp.error("unrecognized parameter: "..parm) end - if ps.type ~= 'boolean' then -- we need a value! This should follow - if not val then - i = i + 1 - val = arg[i] - theArg = val - end - lapp.assert(val,parm.." was expecting a value") - else -- toggle boolean flags (usually false -> true) - val = not ps.defval - end - ps.used = true - val = convert_parameter(ps,val) - set_result(ps,parm,val) - if builtin_types[ps.type] == 'file' then - set_result(ps,parm..'_name',theArg) - end - if lapp.callback then - lapp.callback(parm,theArg,res) - end - i = i + 1 - val = nil - end - -- check unused parms, set defaults and check if any required parameters were missed - for parm,ps in pairs(parms) do - if not ps.used then - if ps.required then lapp.error("missing required parameter: "..parm) end - set_result(ps,parm,ps.defval) - if builtin_types[ps.type] == "file" then - set_result(ps, parm .. "_name", ps.defval_str) - end - end - end - return results -end - -if arg then - script = arg[0] - script = script or rawget(_G,"LAPP_SCRIPT") or "unknown" - -- strip dir and extension to get current script name - script = script:gsub('.+[\\/]',''):gsub('%.%a+$','') -else - script = "inter" -end - - -setmetatable(lapp, { - __call = function(tbl,str,args) return lapp.process_options_string(str,args) end, -}) - - -return lapp - - diff --git a/game/scripts/vscripts/pl/lexer.lua b/game/scripts/vscripts/pl/lexer.lua deleted file mode 100644 index 9219716..0000000 --- a/game/scripts/vscripts/pl/lexer.lua +++ /dev/null @@ -1,515 +0,0 @@ ---- Lexical scanner for creating a sequence of tokens from text. --- `lexer.scan(s)` returns an iterator over all tokens found in the --- string `s`. This iterator returns two values, a token type string --- (such as 'string' for quoted string, 'iden' for identifier) and the value of the --- token. --- --- Versions specialized for Lua and C are available; these also handle block comments --- and classify keywords as 'keyword' tokens. For example: --- --- > s = 'for i=1,n do' --- > for t,v in lexer.lua(s) do print(t,v) end --- keyword for --- iden i --- = = --- number 1 --- , , --- iden n --- keyword do --- --- See the Guide for further @{06-data.md.Lexical_Scanning|discussion} --- @module pl.lexer - -local strfind = string.find -local strsub = string.sub -local append = table.insert - - -local function assert_arg(idx,val,tp) - if type(val) ~= tp then - error("argument "..idx.." must be "..tp, 2) - end -end - -local lexer = {} - -local NUMBER1 = '^[%+%-]?%d+%.?%d*[eE][%+%-]?%d+' -local NUMBER1a = '^[%+%-]?%d*%.%d+[eE][%+%-]?%d+' -local NUMBER2 = '^[%+%-]?%d+%.?%d*' -local NUMBER2a = '^[%+%-]?%d*%.%d+' -local NUMBER3 = '^0x[%da-fA-F]+' -local NUMBER4 = '^%d+%.?%d*[eE][%+%-]?%d+' -local NUMBER4a = '^%d*%.%d+[eE][%+%-]?%d+' -local NUMBER5 = '^%d+%.?%d*' -local NUMBER5a = '^%d*%.%d+' -local IDEN = '^[%a_][%w_]*' -local WSPACE = '^%s+' -local STRING1 = "^(['\"])%1" -- empty string -local STRING2 = [[^(['"])(\*)%2%1]] -local STRING3 = [[^(['"]).-[^\](\*)%2%1]] -local CHAR1 = "^''" -local CHAR2 = [[^'(\*)%1']] -local CHAR3 = [[^'.-[^\](\*)%1']] -local PREPRO = '^#.-[^\\]\n' - -local plain_matches,lua_matches,cpp_matches,lua_keyword,cpp_keyword - -local function tdump(tok) - return tok,tok -end - -local function ndump(tok,options) - if options and options.number then - tok = tonumber(tok) - end - return "number",tok -end - --- regular strings, single or double quotes; usually we want them --- without the quotes -local function sdump(tok,options) - if options and options.string then - tok = tok:sub(2,-2) - end - return "string",tok -end - --- long Lua strings need extra work to get rid of the quotes -local function sdump_l(tok,options,findres) - if options and options.string then - local quotelen = 3 - if findres[3] then - quotelen = quotelen + findres[3]:len() - end - tok = tok:sub(quotelen, -quotelen) - if tok:sub(1, 1) == "\n" then - tok = tok:sub(2) - end - end - return "string",tok -end - -local function chdump(tok,options) - if options and options.string then - tok = tok:sub(2,-2) - end - return "char",tok -end - -local function cdump(tok) - return "comment",tok -end - -local function wsdump (tok) - return "space",tok -end - -local function pdump (tok) - return "prepro",tok -end - -local function plain_vdump(tok) - return "iden",tok -end - -local function lua_vdump(tok) - if lua_keyword[tok] then - return "keyword",tok - else - return "iden",tok - end -end - -local function cpp_vdump(tok) - if cpp_keyword[tok] then - return "keyword",tok - else - return "iden",tok - end -end - ---- create a plain token iterator from a string or file-like object. --- @tparam string|file s a string or a file-like object with `:read()` method returning lines. --- @tab matches an optional match table - array of token descriptions. --- A token is described by a `{pattern, action}` pair, where `pattern` should match --- token body and `action` is a function called when a token of described type is found. --- @tab[opt] filter a table of token types to exclude, by default `{space=true}` --- @tab[opt] options a table of options; by default, `{number=true,string=true}`, --- which means convert numbers and strip string quotes. -function lexer.scan(s,matches,filter,options) - local file = type(s) ~= 'string' and s - filter = filter or {space=true} - options = options or {number=true,string=true} - if filter then - if filter.space then filter[wsdump] = true end - if filter.comments then - filter[cdump] = true - end - end - if not matches then - if not plain_matches then - plain_matches = { - {WSPACE,wsdump}, - {NUMBER3,ndump}, - {IDEN,plain_vdump}, - {NUMBER1,ndump}, - {NUMBER1a,ndump}, - {NUMBER2,ndump}, - {NUMBER2a,ndump}, - {STRING1,sdump}, - {STRING2,sdump}, - {STRING3,sdump}, - {'^.',tdump} - } - end - matches = plain_matches - end - - local line_nr = 0 - local next_line = file and file:read() - local sz = file and 0 or #s - local idx = 1 - - local tlist_i - local tlist - - local first_hit = true - - local function iter(res) - local tp = type(res) - - if tlist then -- returning the inserted token list - local cur = tlist[tlist_i] - if cur then - tlist_i = tlist_i + 1 - return cur[1], cur[2] - else - tlist = nil - end - end - - if tp == 'string' then -- search up to some special pattern - local i1,i2 = strfind(s,res,idx) - if i1 then - local tok = strsub(s,i1,i2) - idx = i2 + 1 - return '', tok - else - idx = sz + 1 - return '', '' - end - - elseif tp == 'table' then -- insert a token list - tlist_i = 1 - tlist = res - return '', '' - - elseif tp ~= 'nil' then -- return position - return line_nr, idx - - else -- look for next token - if first_hit then - if not file then line_nr = 1 end - first_hit = false - end - - if idx > sz then - if file then - if not next_line then - return -- past the end of file, done - end - s = next_line - line_nr = line_nr + 1 - next_line = file:read() - if next_line then - s = s .. '\n' - end - idx, sz = 1, #s - else - return -- past the end of input, done - end - end - - for _,m in ipairs(matches) do - local pat = m[1] - local fun = m[2] - local findres = {strfind(s,pat,idx)} - local i1, i2 = findres[1], findres[2] - if i1 then - local tok = strsub(s,i1,i2) - idx = i2 + 1 - local ret1, ret2 - if not (filter and filter[fun]) then - lexer.finished = idx > sz - ret1, ret2 = fun(tok, options, findres) - end - if not file and tok:find("\n") then - -- Update line number. - local _, newlines = tok:gsub("\n", {}) - line_nr = line_nr + newlines - end - if ret1 then - return ret1, ret2 -- found a match - else - return iter() -- tail-call to try again - end - end - end - end - end - - return iter -end - -local function isstring (s) - return type(s) == 'string' -end - ---- insert tokens into a stream. --- @param tok a token stream --- @param a1 a string is the type, a table is a token list and --- a function is assumed to be a token-like iterator (returns type & value) --- @string a2 a string is the value -function lexer.insert (tok,a1,a2) - if not a1 then return end - local ts - if isstring(a1) and isstring(a2) then - ts = {{a1,a2}} - elseif type(a1) == 'function' then - ts = {} - for t,v in a1() do - append(ts,{t,v}) - end - else - ts = a1 - end - tok(ts) -end - ---- get everything in a stream upto a newline. --- @param tok a token stream --- @return a string -function lexer.getline (tok) - local _,v = tok('.-\n') - return v -end - ---- get current line number. --- @param tok a token stream --- @return the line number. --- if the input source is a file-like object, --- also return the column. -function lexer.lineno (tok) - return tok(0) -end - ---- get the rest of the stream. --- @param tok a token stream --- @return a string -function lexer.getrest (tok) - local _,v = tok('.+') - return v -end - ---- get the Lua keywords as a set-like table. --- So `res["and"]` etc would be `true`. --- @return a table -function lexer.get_keywords () - if not lua_keyword then - lua_keyword = { - ["and"] = true, ["break"] = true, ["do"] = true, - ["else"] = true, ["elseif"] = true, ["end"] = true, - ["false"] = true, ["for"] = true, ["function"] = true, - ["if"] = true, ["in"] = true, ["local"] = true, ["nil"] = true, - ["not"] = true, ["or"] = true, ["repeat"] = true, - ["return"] = true, ["then"] = true, ["true"] = true, - ["until"] = true, ["while"] = true - } - end - return lua_keyword -end - ---- create a Lua token iterator from a string or file-like object. --- Will return the token type and value. --- @string s the string --- @tab[opt] filter a table of token types to exclude, by default `{space=true,comments=true}` --- @tab[opt] options a table of options; by default, `{number=true,string=true}`, --- which means convert numbers and strip string quotes. -function lexer.lua(s,filter,options) - filter = filter or {space=true,comments=true} - lexer.get_keywords() - if not lua_matches then - lua_matches = { - {WSPACE,wsdump}, - {NUMBER3,ndump}, - {IDEN,lua_vdump}, - {NUMBER4,ndump}, - {NUMBER4a,ndump}, - {NUMBER5,ndump}, - {NUMBER5a,ndump}, - {STRING1,sdump}, - {STRING2,sdump}, - {STRING3,sdump}, - {'^%-%-%[(=*)%[.-%]%1%]',cdump}, - {'^%-%-.-\n',cdump}, - {'^%[(=*)%[.-%]%1%]',sdump_l}, - {'^==',tdump}, - {'^~=',tdump}, - {'^<=',tdump}, - {'^>=',tdump}, - {'^%.%.%.',tdump}, - {'^%.%.',tdump}, - {'^.',tdump} - } - end - return lexer.scan(s,lua_matches,filter,options) -end - ---- create a C/C++ token iterator from a string or file-like object. --- Will return the token type type and value. --- @string s the string --- @tab[opt] filter a table of token types to exclude, by default `{space=true,comments=true}` --- @tab[opt] options a table of options; by default, `{number=true,string=true}`, --- which means convert numbers and strip string quotes. -function lexer.cpp(s,filter,options) - filter = filter or {space=true,comments=true} - if not cpp_keyword then - cpp_keyword = { - ["class"] = true, ["break"] = true, ["do"] = true, ["sizeof"] = true, - ["else"] = true, ["continue"] = true, ["struct"] = true, - ["false"] = true, ["for"] = true, ["public"] = true, ["void"] = true, - ["private"] = true, ["protected"] = true, ["goto"] = true, - ["if"] = true, ["static"] = true, ["const"] = true, ["typedef"] = true, - ["enum"] = true, ["char"] = true, ["int"] = true, ["bool"] = true, - ["long"] = true, ["float"] = true, ["true"] = true, ["delete"] = true, - ["double"] = true, ["while"] = true, ["new"] = true, - ["namespace"] = true, ["try"] = true, ["catch"] = true, - ["switch"] = true, ["case"] = true, ["extern"] = true, - ["return"] = true,["default"] = true,['unsigned'] = true,['signed'] = true, - ["union"] = true, ["volatile"] = true, ["register"] = true,["short"] = true, - } - end - if not cpp_matches then - cpp_matches = { - {WSPACE,wsdump}, - {PREPRO,pdump}, - {NUMBER3,ndump}, - {IDEN,cpp_vdump}, - {NUMBER4,ndump}, - {NUMBER4a,ndump}, - {NUMBER5,ndump}, - {NUMBER5a,ndump}, - {CHAR1,chdump}, - {CHAR2,chdump}, - {CHAR3,chdump}, - {STRING1,sdump}, - {STRING2,sdump}, - {STRING3,sdump}, - {'^//.-\n',cdump}, - {'^/%*.-%*/',cdump}, - {'^==',tdump}, - {'^!=',tdump}, - {'^<=',tdump}, - {'^>=',tdump}, - {'^->',tdump}, - {'^&&',tdump}, - {'^||',tdump}, - {'^%+%+',tdump}, - {'^%-%-',tdump}, - {'^%+=',tdump}, - {'^%-=',tdump}, - {'^%*=',tdump}, - {'^/=',tdump}, - {'^|=',tdump}, - {'^%^=',tdump}, - {'^::',tdump}, - {'^.',tdump} - } - end - return lexer.scan(s,cpp_matches,filter,options) -end - ---- get a list of parameters separated by a delimiter from a stream. --- @param tok the token stream --- @string[opt=')'] endtoken end of list. Can be '\n' --- @string[opt=','] delim separator --- @return a list of token lists. -function lexer.get_separated_list(tok,endtoken,delim) - endtoken = endtoken or ')' - delim = delim or ',' - local parm_values = {} - local level = 1 -- used to count ( and ) - local tl = {} - local function tappend (tl,t,val) - val = val or t - append(tl,{t,val}) - end - local is_end - if endtoken == '\n' then - is_end = function(t,val) - return t == 'space' and val:find '\n' - end - else - is_end = function (t) - return t == endtoken - end - end - local token,value - while true do - token,value=tok() - if not token then return nil,'EOS' end -- end of stream is an error! - if is_end(token,value) and level == 1 then - append(parm_values,tl) - break - elseif token == '(' then - level = level + 1 - tappend(tl,'(') - elseif token == ')' then - level = level - 1 - if level == 0 then -- finished with parm list - append(parm_values,tl) - break - else - tappend(tl,')') - end - elseif token == delim and level == 1 then - append(parm_values,tl) -- a new parm - tl = {} - else - tappend(tl,token,value) - end - end - return parm_values,{token,value} -end - ---- get the next non-space token from the stream. --- @param tok the token stream. -function lexer.skipws (tok) - local t,v = tok() - while t == 'space' do - t,v = tok() - end - return t,v -end - -local skipws = lexer.skipws - ---- get the next token, which must be of the expected type. --- Throws an error if this type does not match! --- @param tok the token stream --- @string expected_type the token type --- @bool no_skip_ws whether we should skip whitespace -function lexer.expecting (tok,expected_type,no_skip_ws) - assert_arg(1,tok,'function') - assert_arg(2,expected_type,'string') - local t,v - if no_skip_ws then - t,v = tok() - else - t,v = skipws(tok) - end - if t ~= expected_type then error ("expecting "..expected_type,2) end - return v -end - -return lexer diff --git a/game/scripts/vscripts/pl/luabalanced.lua b/game/scripts/vscripts/pl/luabalanced.lua deleted file mode 100644 index a1f7dc6..0000000 --- a/game/scripts/vscripts/pl/luabalanced.lua +++ /dev/null @@ -1,264 +0,0 @@ ---- Extract delimited Lua sequences from strings. --- Inspired by Damian Conway's Text::Balanced in Perl.
---
    ---
  • [1] Lua Wiki Page
  • ---
  • [2] http://search.cpan.org/dist/Text-Balanced/lib/Text/Balanced.pm
  • ---

---
--- local lb = require "pl.luabalanced"
--- --Extract Lua expression starting at position 4.
---  print(lb.match_expression("if x^2 + x > 5 then print(x) end", 4))
---  --> x^2 + x > 5     16
--- --Extract Lua string starting at (default) position 1.
--- print(lb.match_string([["test\"123" .. "more"]]))
--- --> "test\"123"     12
--- 
--- (c) 2008, David Manura, Licensed under the same terms as Lua (MIT license). --- @class module --- @name pl.luabalanced - -local M = {} - -local assert = assert - --- map opening brace <-> closing brace. -local ends = { ['('] = ')', ['{'] = '}', ['['] = ']' } -local begins = {}; for k,v in pairs(ends) do begins[v] = k end - - --- Match Lua string in string starting at position . --- Returns , , where is the matched --- string (or nil on no match) and is the character --- following the match (or on no match). --- Supports all Lua string syntax: "...", '...', [[...]], [=[...]=], etc. -local function match_string(s, pos) - pos = pos or 1 - local posa = pos - local c = s:sub(pos,pos) - if c == '"' or c == "'" then - pos = pos + 1 - while 1 do - pos = assert(s:find("[" .. c .. "\\]", pos), 'syntax error') - if s:sub(pos,pos) == c then - local part = s:sub(posa, pos) - return part, pos + 1 - else - pos = pos + 2 - end - end - else - local sc = s:match("^%[(=*)%[", pos) - if sc then - local _; _, pos = s:find("%]" .. sc .. "%]", pos) - assert(pos) - local part = s:sub(posa, pos) - return part, pos + 1 - else - return nil, pos - end - end -end -M.match_string = match_string - - --- Match bracketed Lua expression, e.g. "(...)", "{...}", "[...]", "[[...]]", --- [=[...]=], etc. --- Function interface is similar to match_string. -local function match_bracketed(s, pos) - pos = pos or 1 - local posa = pos - local ca = s:sub(pos,pos) - if not ends[ca] then - return nil, pos - end - local stack = {} - while 1 do - pos = s:find('[%(%{%[%)%}%]\"\']', pos) - assert(pos, 'syntax error: unbalanced') - local c = s:sub(pos,pos) - if c == '"' or c == "'" then - local part; part, pos = match_string(s, pos) - assert(part) - elseif ends[c] then -- open - local mid, posb - if c == '[' then mid, posb = s:match('^%[(=*)%[()', pos) end - if mid then - pos = s:match('%]' .. mid .. '%]()', posb) - assert(pos, 'syntax error: long string not terminated') - if #stack == 0 then - local part = s:sub(posa, pos-1) - return part, pos - end - else - stack[#stack+1] = c - pos = pos + 1 - end - else -- close - assert(stack[#stack] == assert(begins[c]), 'syntax error: unbalanced') - stack[#stack] = nil - if #stack == 0 then - local part = s:sub(posa, pos) - return part, pos+1 - end - pos = pos + 1 - end - end -end -M.match_bracketed = match_bracketed - - --- Match Lua comment, e.g. "--...\n", "--[[...]]", "--[=[...]=]", etc. --- Function interface is similar to match_string. -local function match_comment(s, pos) - pos = pos or 1 - if s:sub(pos, pos+1) ~= '--' then - return nil, pos - end - pos = pos + 2 - local partt, post = match_string(s, pos) - if partt then - return '--' .. partt, post - end - local part; part, pos = s:match('^([^\n]*\n?)()', pos) - return '--' .. part, pos -end - - --- Match Lua expression, e.g. "a + b * c[e]". --- Function interface is similar to match_string. -local wordop = {['and']=true, ['or']=true, ['not']=true} -local is_compare = {['>']=true, ['<']=true, ['~']=true} -local function match_expression(s, pos) - pos = pos or 1 - local _ - local posa = pos - local lastident - local poscs, posce - while pos do - local c = s:sub(pos,pos) - if c == '"' or c == "'" or c == '[' and s:find('^[=%[]', pos+1) then - local part; part, pos = match_string(s, pos) - assert(part, 'syntax error') - elseif c == '-' and s:sub(pos+1,pos+1) == '-' then - -- note: handle adjacent comments in loop to properly support - -- backtracing (poscs/posce). - poscs = pos - while s:sub(pos,pos+1) == '--' do - local part; part, pos = match_comment(s, pos) - assert(part) - pos = s:match('^%s*()', pos) - posce = pos - end - elseif c == '(' or c == '{' or c == '[' then - _, pos = match_bracketed(s, pos) - elseif c == '=' and s:sub(pos+1,pos+1) == '=' then - pos = pos + 2 -- skip over two-char op containing '=' - elseif c == '=' and is_compare[s:sub(pos-1,pos-1)] then - pos = pos + 1 -- skip over two-char op containing '=' - elseif c:match'^[%)%}%];,=]' then - local part = s:sub(posa, pos-1) - return part, pos - elseif c:match'^[%w_]' then - local newident,newpos = s:match('^([%w_]+)()', pos) - if pos ~= posa and not wordop[newident] then -- non-first ident - local pose = ((posce == pos) and poscs or pos) - 1 - while s:match('^%s', pose) do pose = pose - 1 end - local ce = s:sub(pose,pose) - if ce:match'[%)%}\'\"%]]' or - ce:match'[%w_]' and not wordop[lastident] - then - local part = s:sub(posa, pos-1) - return part, pos - end - end - lastident, pos = newident, newpos - else - pos = pos + 1 - end - pos = s:find('[%(%{%[%)%}%]\"\';,=%w_%-]', pos) - end - local part = s:sub(posa, #s) - return part, #s+1 -end -M.match_expression = match_expression - - --- Match name list (zero or more names). E.g. "a,b,c" --- Function interface is similar to match_string, --- but returns array as match. -local function match_namelist(s, pos) - pos = pos or 1 - local list = {} - while 1 do - local c = #list == 0 and '^' or '^%s*,%s*' - local item, post = s:match(c .. '([%a_][%w_]*)%s*()', pos) - if item then pos = post else break end - list[#list+1] = item - end - return list, pos -end -M.match_namelist = match_namelist - - --- Match expression list (zero or more expressions). E.g. "a+b,b*c". --- Function interface is similar to match_string, --- but returns array as match. -local function match_explist(s, pos) - pos = pos or 1 - local list = {} - while 1 do - if #list ~= 0 then - local post = s:match('^%s*,%s*()', pos) - if post then pos = post else break end - end - local item; item, pos = match_expression(s, pos) - assert(item, 'syntax error') - list[#list+1] = item - end - return list, pos -end -M.match_explist = match_explist - - --- Replace snippets of code in Lua code string --- using replacement function f(u,sin) --> sout. --- is the type of snippet ('c' = comment, 's' = string, --- 'e' = any other code). --- Snippet is replaced with (unless is nil or false, in --- which case the original snippet is kept) --- This is somewhat analogous to string.gsub . -local function gsub(s, f) - local pos = 1 - local posa = 1 - local sret = '' - while 1 do - pos = s:find('[%-\'\"%[]', pos) - if not pos then break end - if s:match('^%-%-', pos) then - local exp = s:sub(posa, pos-1) - if #exp > 0 then sret = sret .. (f('e', exp) or exp) end - local comment; comment, pos = match_comment(s, pos) - sret = sret .. (f('c', assert(comment)) or comment) - posa = pos - else - local posb = s:find('^[\'\"%[]', pos) - local str - if posb then str, pos = match_string(s, posb) end - if str then - local exp = s:sub(posa, posb-1) - if #exp > 0 then sret = sret .. (f('e', exp) or exp) end - sret = sret .. (f('s', str) or str) - posa = pos - else - pos = pos + 1 - end - end - end - local exp = s:sub(posa) - if #exp > 0 then sret = sret .. (f('e', exp) or exp) end - return sret -end -M.gsub = gsub - - -return M diff --git a/game/scripts/vscripts/pl/operator.lua b/game/scripts/vscripts/pl/operator.lua deleted file mode 100644 index 60eaffd..0000000 --- a/game/scripts/vscripts/pl/operator.lua +++ /dev/null @@ -1,209 +0,0 @@ ---- Lua operators available as functions. --- --- (similar to the Python module of the same name) --- --- There is a module field `optable` which maps the operator strings --- onto these functions, e.g. `operator.optable['()']==operator.call` --- --- Operator strings like '>' and '{}' can be passed to most Penlight functions --- expecting a function argument. --- --- @module pl.operator - -local strfind = string.find - -local operator = {} - ---- apply function to some arguments **()** --- @param fn a function or callable object --- @param ... arguments -function operator.call(fn,...) - return fn(...) -end - ---- get the indexed value from a table **[]** --- @param t a table or any indexable object --- @param k the key -function operator.index(t,k) - return t[k] -end - ---- returns true if arguments are equal **==** --- @param a value --- @param b value -function operator.eq(a,b) - return a==b -end - ---- returns true if arguments are not equal **~=** - -- @param a value --- @param b value -function operator.neq(a,b) - return a~=b -end - ---- returns true if a is less than b **<** --- @param a value --- @param b value -function operator.lt(a,b) - return a < b -end - ---- returns true if a is less or equal to b **<=** --- @param a value --- @param b value -function operator.le(a,b) - return a <= b -end - ---- returns true if a is greater than b **>** --- @param a value --- @param b value -function operator.gt(a,b) - return a > b -end - ---- returns true if a is greater or equal to b **>=** --- @param a value --- @param b value -function operator.ge(a,b) - return a >= b -end - ---- returns length of string or table **#** --- @param a a string or a table -function operator.len(a) - return #a -end - ---- add two values **+** --- @param a value --- @param b value -function operator.add(a,b) - return a+b -end - ---- subtract b from a **-** --- @param a value --- @param b value -function operator.sub(a,b) - return a-b -end - ---- multiply two values __*__ --- @param a value --- @param b value -function operator.mul(a,b) - return a*b -end - ---- divide first value by second **/** --- @param a value --- @param b value -function operator.div(a,b) - return a/b -end - ---- raise first to the power of second **^** --- @param a value --- @param b value -function operator.pow(a,b) - return a^b -end - ---- modulo; remainder of a divided by b **%** --- @param a value --- @param b value -function operator.mod(a,b) - return a%b -end - ---- concatenate two values (either strings or `__concat` defined) **..** --- @param a value --- @param b value -function operator.concat(a,b) - return a..b -end - ---- return the negative of a value **-** --- @param a value -function operator.unm(a) - return -a -end - ---- false if value evaluates as true **not** --- @param a value -function operator.lnot(a) - return not a -end - ---- true if both values evaluate as true **and** --- @param a value --- @param b value -function operator.land(a,b) - return a and b -end - ---- true if either value evaluate as true **or** --- @param a value --- @param b value -function operator.lor(a,b) - return a or b -end - ---- make a table from the arguments **{}** --- @param ... non-nil arguments --- @return a table -function operator.table (...) - return {...} -end - ---- match two strings **~**. --- uses @{string.find} -function operator.match (a,b) - return strfind(a,b)~=nil -end - ---- the null operation. --- @param ... arguments --- @return the arguments -function operator.nop (...) - return ... -end - ----- Map from operator symbol to function. --- Most of these map directly from operators; --- But note these extras --- --- * __'()'__ `call` --- * __'[]'__ `index` --- * __'{}'__ `table` --- * __'~'__ `match` --- --- @table optable --- @field operator - operator.optable = { - ['+']=operator.add, - ['-']=operator.sub, - ['*']=operator.mul, - ['/']=operator.div, - ['%']=operator.mod, - ['^']=operator.pow, - ['..']=operator.concat, - ['()']=operator.call, - ['[]']=operator.index, - ['<']=operator.lt, - ['<=']=operator.le, - ['>']=operator.gt, - ['>=']=operator.ge, - ['==']=operator.eq, - ['~=']=operator.neq, - ['#']=operator.len, - ['and']=operator.land, - ['or']=operator.lor, - ['{}']=operator.table, - ['~']=operator.match, - ['']=operator.nop, -} - -return operator diff --git a/game/scripts/vscripts/pl/path.lua b/game/scripts/vscripts/pl/path.lua deleted file mode 100644 index 1e044e1..0000000 --- a/game/scripts/vscripts/pl/path.lua +++ /dev/null @@ -1,572 +0,0 @@ ---- Path manipulation and file queries. --- --- This is modelled after Python's os.path library (10.1); see @{04-paths.md|the Guide}. --- --- NOTE: the functions assume the paths being dealt with to originate --- from the OS the application is running on. Windows drive letters are not --- to be used when running on a Unix system for example. The one exception --- is Windows paths to allow both forward and backward slashes (since Lua --- also accepts those) --- --- Dependencies: `pl.utils`, `lfs` --- @module pl.path - --- imports and locals -local _G = _G -local sub = string.sub -local getenv = os.getenv -local tmpnam = os.tmpname -local package = package -local append, concat, remove = table.insert, table.concat, table.remove -local utils = require 'pl.utils' -local assert_string,raise = utils.assert_string,utils.raise - -local res,lfs = _G.pcall(_G.require,'lfs') -if not res then - error("pl.path requires LuaFileSystem") -end - -local attrib = lfs.attributes -local currentdir = lfs.currentdir -local link_attrib = lfs.symlinkattributes - -local path = {} - -local function err_func(name, param, err, code) - local ret = ("%s failed"):format(tostring(name)) - if param ~= nil then - ret = ret .. (" for '%s'"):format(tostring(param)) - end - ret = ret .. (": %s"):format(tostring(err)) - if code ~= nil then - ret = ret .. (" (code %s)"):format(tostring(code)) - end - return ret -end - ---- Lua iterator over the entries of a given directory. --- Implicit link to [`luafilesystem.dir`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function dir -path.dir = lfs.dir - ---- Creates a directory. --- Implicit link to [`luafilesystem.mkdir`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function mkdir -path.mkdir = function(d) - local ok, err, code = lfs.mkdir(d) - if not ok then - return ok, err_func("mkdir", d, err, code), code - end - return ok, err, code -end - ---- Removes a directory. --- Implicit link to [`luafilesystem.rmdir`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function rmdir -path.rmdir = function(d) - local ok, err, code = lfs.rmdir(d) - if not ok then - return ok, err_func("rmdir", d, err, code), code - end - return ok, err, code -end - ---- Gets attributes. --- Implicit link to [`luafilesystem.attributes`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function attrib -path.attrib = function(d, r) - local ok, err, code = attrib(d, r) - if not ok then - return ok, err_func("attrib", d, err, code), code - end - return ok, err, code -end - ---- Get the working directory. --- Implicit link to [`luafilesystem.currentdir`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function currentdir -path.currentdir = function() - local ok, err, code = currentdir() - if not ok then - return ok, err_func("currentdir", nil, err, code), code - end - return ok, err, code -end - ---- Gets symlink attributes. --- Implicit link to [`luafilesystem.symlinkattributes`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function link_attrib -path.link_attrib = function(d, r) - local ok, err, code = link_attrib(d, r) - if not ok then - return ok, err_func("link_attrib", d, err, code), code - end - return ok, err, code -end - ---- Changes the working directory. --- On Windows, if a drive is specified, it also changes the current drive. If --- only specifying the drive, it will only switch drive, but not modify the path. --- Implicit link to [`luafilesystem.chdir`](https://keplerproject.github.io/luafilesystem/manual.html#reference) --- @function chdir -path.chdir = function(d) - local ok, err, code = lfs.chdir(d) - if not ok then - return ok, err_func("chdir", d, err, code), code - end - return ok, err, code -end - ---- is this a directory? --- @string P A file path -function path.isdir(P) - assert_string(1,P) - return attrib(P,'mode') == 'directory' -end - ---- is this a file? --- @string P A file path -function path.isfile(P) - assert_string(1,P) - return attrib(P,'mode') == 'file' -end - --- is this a symbolic link? --- @string P A file path -function path.islink(P) - assert_string(1,P) - if link_attrib then - return link_attrib(P,'mode')=='link' - else - return false - end -end - ---- return size of a file. --- @string P A file path -function path.getsize(P) - assert_string(1,P) - return attrib(P,'size') -end - ---- does a path exist? --- @string P A file path --- @return the file path if it exists (either as file, directory, socket, etc), nil otherwise -function path.exists(P) - assert_string(1,P) - return attrib(P,'mode') ~= nil and P -end - ---- Return the time of last access as the number of seconds since the epoch. --- @string P A file path -function path.getatime(P) - assert_string(1,P) - return attrib(P,'access') -end - ---- Return the time of last modification as the number of seconds since the epoch. --- @string P A file path -function path.getmtime(P) - assert_string(1,P) - return attrib(P,'modification') -end - ----Return the system's ctime as the number of seconds since the epoch. --- @string P A file path -function path.getctime(P) - assert_string(1,P) - return path.attrib(P,'change') -end - - -local function at(s,i) - return sub(s,i,i) -end - -path.is_windows = utils.is_windows - -local sep, other_sep, seps --- constant sep is the directory separator for this platform. --- constant dirsep is the separator in the PATH environment variable -if path.is_windows then - path.sep = '\\'; other_sep = '/' - path.dirsep = ';' - seps = { ['/'] = true, ['\\'] = true } -else - path.sep = '/' - path.dirsep = ':' - seps = { ['/'] = true } -end -sep = path.sep - ---- are we running Windows? --- @class field --- @name path.is_windows - ---- path separator for this platform. --- @class field --- @name path.sep - ---- separator for PATH for this platform --- @class field --- @name path.dirsep - ---- given a path, return the directory part and a file part. --- if there's no directory part, the first value will be empty --- @string P A file path --- @return directory part --- @return file part --- @usage --- local dir, file = path.splitpath("some/dir/myfile.txt") --- assert(dir == "some/dir") --- assert(file == "myfile.txt") --- --- local dir, file = path.splitpath("some/dir/") --- assert(dir == "some/dir") --- assert(file == "") --- --- local dir, file = path.splitpath("some_dir") --- assert(dir == "") --- assert(file == "some_dir") -function path.splitpath(P) - assert_string(1,P) - local i = #P - local ch = at(P,i) - while i > 0 and ch ~= sep and ch ~= other_sep do - i = i - 1 - ch = at(P,i) - end - if i == 0 then - return '',P - else - return sub(P,1,i-1), sub(P,i+1) - end -end - ---- return an absolute path. --- @string P A file path --- @string[opt] pwd optional start path to use (default is current dir) -function path.abspath(P,pwd) - assert_string(1,P) - if pwd then assert_string(2,pwd) end - local use_pwd = pwd ~= nil - if not use_pwd and not currentdir() then return P end - P = P:gsub('[\\/]$','') - pwd = pwd or currentdir() - if not path.isabs(P) then - P = path.join(pwd,P) - elseif path.is_windows and not use_pwd and at(P,2) ~= ':' and at(P,2) ~= '\\' then - P = pwd:sub(1,2)..P -- attach current drive to path like '\\fred.txt' - end - return path.normpath(P) -end - ---- given a path, return the root part and the extension part. --- if there's no extension part, the second value will be empty --- @string P A file path --- @treturn string root part (everything upto the "."", maybe empty) --- @treturn string extension part (including the ".", maybe empty) --- @usage --- local file_path, ext = path.splitext("/bonzo/dog_stuff/cat.txt") --- assert(file_path == "/bonzo/dog_stuff/cat") --- assert(ext == ".txt") --- --- local file_path, ext = path.splitext("") --- assert(file_path == "") --- assert(ext == "") -function path.splitext(P) - assert_string(1,P) - local i = #P - local ch = at(P,i) - while i > 0 and ch ~= '.' do - if seps[ch] then - return P,'' - end - i = i - 1 - ch = at(P,i) - end - if i == 0 then - return P,'' - else - return sub(P,1,i-1),sub(P,i) - end -end - ---- return the directory part of a path --- @string P A file path --- @treturn string everything before the last dir-separator --- @see splitpath --- @usage --- path.dirname("/some/path/file.txt") -- "/some/path" --- path.dirname("file.txt") -- "" (empty string) -function path.dirname(P) - assert_string(1,P) - local p1 = path.splitpath(P) - return p1 -end - ---- return the file part of a path --- @string P A file path --- @treturn string --- @see splitpath --- @usage --- path.basename("/some/path/file.txt") -- "file.txt" --- path.basename("/some/path/file/") -- "" (empty string) -function path.basename(P) - assert_string(1,P) - local _,p2 = path.splitpath(P) - return p2 -end - ---- get the extension part of a path. --- @string P A file path --- @treturn string --- @see splitext --- @usage --- path.extension("/some/path/file.txt") -- ".txt" --- path.extension("/some/path/file_txt") -- "" (empty string) -function path.extension(P) - assert_string(1,P) - local _,p2 = path.splitext(P) - return p2 -end - ---- is this an absolute path? --- @string P A file path --- @usage --- path.isabs("hello/path") -- false --- path.isabs("/hello/path") -- true --- -- Windows; --- path.isabs("hello\path") -- false --- path.isabs("\hello\path") -- true --- path.isabs("C:\hello\path") -- true --- path.isabs("C:hello\path") -- false -function path.isabs(P) - assert_string(1,P) - if path.is_windows and at(P,2) == ":" then - return seps[at(P,3)] ~= nil - end - return seps[at(P,1)] ~= nil -end - ---- return the path resulting from combining the individual paths. --- if the second (or later) path is absolute, we return the last absolute path (joined with any non-absolute paths following). --- empty elements (except the last) will be ignored. --- @string p1 A file path --- @string p2 A file path --- @string ... more file paths --- @treturn string the combined path --- @usage --- path.join("/first","second","third") -- "/first/second/third" --- path.join("first","second/third") -- "first/second/third" --- path.join("/first","/second","third") -- "/second/third" -function path.join(p1,p2,...) - assert_string(1,p1) - assert_string(2,p2) - if select('#',...) > 0 then - local p = path.join(p1,p2) - local args = {...} - for i = 1,#args do - assert_string(i,args[i]) - p = path.join(p,args[i]) - end - return p - end - if path.isabs(p2) then return p2 end - local endc = at(p1,#p1) - if endc ~= path.sep and endc ~= other_sep and endc ~= "" then - p1 = p1..path.sep - end - return p1..p2 -end - ---- normalize the case of a pathname. On Unix, this returns the path unchanged, --- for Windows it converts; --- --- * the path to lowercase --- * forward slashes to backward slashes --- @string P A file path --- @usage path.normcase("/Some/Path/File.txt") --- -- Windows: "\some\path\file.txt" --- -- Others : "/Some/Path/File.txt" -function path.normcase(P) - assert_string(1,P) - if path.is_windows then - return P:gsub('/','\\'):lower() - else - return P - end -end - ---- normalize a path name. --- `A//B`, `A/./B`, and `A/foo/../B` all become `A/B`. --- --- An empty path results in '.'. --- @string P a file path -function path.normpath(P) - assert_string(1,P) - -- Split path into anchor and relative path. - local anchor = '' - if path.is_windows then - if P:match '^\\\\' then -- UNC - anchor = '\\\\' - P = P:sub(3) - elseif seps[at(P, 1)] then - anchor = '\\' - P = P:sub(2) - elseif at(P, 2) == ':' then - anchor = P:sub(1, 2) - P = P:sub(3) - if seps[at(P, 1)] then - anchor = anchor..'\\' - P = P:sub(2) - end - end - P = P:gsub('/','\\') - else - -- According to POSIX, in path start '//' and '/' are distinct, - -- but '///+' is equivalent to '/'. - if P:match '^//' and at(P, 3) ~= '/' then - anchor = '//' - P = P:sub(3) - elseif at(P, 1) == '/' then - anchor = '/' - P = P:match '^/*(.*)$' - end - end - local parts = {} - for part in P:gmatch('[^'..sep..']+') do - if part == '..' then - if #parts ~= 0 and parts[#parts] ~= '..' then - remove(parts) - else - append(parts, part) - end - elseif part ~= '.' then - append(parts, part) - end - end - P = anchor..concat(parts, sep) - if P == '' then P = '.' end - return P -end - ---- relative path from current directory or optional start point --- @string P a path --- @string[opt] start optional start point (default current directory) -function path.relpath (P,start) - assert_string(1,P) - if start then assert_string(2,start) end - local split,min,append = utils.split, math.min, table.insert - P = path.abspath(P,start) - start = start or currentdir() - local compare - if path.is_windows then - P = P:gsub("/","\\") - start = start:gsub("/","\\") - compare = function(v) return v:lower() end - else - compare = function(v) return v end - end - local startl, Pl = split(start,sep), split(P,sep) - local n = min(#startl,#Pl) - if path.is_windows and n > 0 and at(Pl[1],2) == ':' and Pl[1] ~= startl[1] then - return P - end - local k = n+1 -- default value if this loop doesn't bail out! - for i = 1,n do - if compare(startl[i]) ~= compare(Pl[i]) then - k = i - break - end - end - local rell = {} - for i = 1, #startl-k+1 do rell[i] = '..' end - if k <= #Pl then - for i = k,#Pl do append(rell,Pl[i]) end - end - return table.concat(rell,sep) -end - - ---- Replace a starting '~' with the user's home directory. --- In windows, if HOME isn't set, then USERPROFILE is used in preference to --- HOMEDRIVE HOMEPATH. This is guaranteed to be writeable on all versions of Windows. --- @string P A file path -function path.expanduser(P) - assert_string(1,P) - if at(P,1) == '~' then - local home = getenv('HOME') - if not home then -- has to be Windows - home = getenv 'USERPROFILE' or (getenv 'HOMEDRIVE' .. getenv 'HOMEPATH') - end - return home..sub(P,2) - else - return P - end -end - - ----Return a suitable full path to a new temporary file name. --- unlike os.tmpname(), it always gives you a writeable path (uses TEMP environment variable on Windows) -function path.tmpname () - local res = tmpnam() - -- On Windows if Lua is compiled using MSVC14 os.tmpname - -- already returns an absolute path within TEMP env variable directory, - -- no need to prepend it. - if path.is_windows and not res:find(':') then - res = getenv('TEMP')..res - end - return res -end - ---- return the largest common prefix path of two paths. --- @string path1 a file path --- @string path2 a file path --- @return the common prefix (Windows: separators will be normalized, casing will be original) -function path.common_prefix (path1,path2) - assert_string(1,path1) - assert_string(2,path2) - -- get them in order! - if #path1 > #path2 then path2,path1 = path1,path2 end - local compare - if path.is_windows then - path1 = path1:gsub("/", "\\") - path2 = path2:gsub("/", "\\") - compare = function(v) return v:lower() end - else - compare = function(v) return v end - end - for i = 1,#path1 do - if compare(at(path1,i)) ~= compare(at(path2,i)) then - local cp = path1:sub(1,i-1) - if at(path1,i-1) ~= sep then - cp = path.dirname(cp) - end - return cp - end - end - if at(path2,#path1+1) ~= sep then path1 = path.dirname(path1) end - return path1 - --return '' -end - ---- return the full path where a particular Lua module would be found. --- Both package.path and package.cpath is searched, so the result may --- either be a Lua file or a shared library. --- @string mod name of the module --- @return on success: path of module, lua or binary --- @return on error: nil, error string listing paths tried -function path.package_path(mod) - assert_string(1,mod) - local res, err1, err2 - res, err1 = package.searchpath(mod,package.path) - if res then return res,true end - res, err2 = package.searchpath(mod,package.cpath) - if res then return res,false end - return raise ('cannot find module on path\n' .. err1 .. "\n" .. err2) -end - - ----- finis ----- -return path diff --git a/game/scripts/vscripts/pl/permute.lua b/game/scripts/vscripts/pl/permute.lua deleted file mode 100644 index ce646f4..0000000 --- a/game/scripts/vscripts/pl/permute.lua +++ /dev/null @@ -1,196 +0,0 @@ ---- Permutation operations. --- --- Dependencies: `pl.utils`, `pl.tablex` --- @module pl.permute -local tablex = require 'pl.tablex' -local utils = require 'pl.utils' -local copy = tablex.deepcopy -local append = table.insert -local assert_arg = utils.assert_arg - - -local permute = {} - - ---- an iterator over all order-permutations of the elements of a list. --- Please note that the same list is returned each time, so do not keep references! --- @param a list-like table --- @return an iterator which provides the next permutation as a list -function permute.order_iter(a) - assert_arg(1,a,'table') - - local t = #a - local stack = { 1 } - local function iter() - local h = #stack - local n = t - h + 1 - - local i = stack[h] - if i > t then - return - end - - if n == 0 then - table.remove(stack) - h = h - 1 - - stack[h] = stack[h] + 1 - return a - - elseif i <= n then - - -- put i-th element as the last one - a[n], a[i] = a[i], a[n] - - -- generate all permutations of the other elements - table.insert(stack, 1) - - else - - table.remove(stack) - h = h - 1 - - n = n + 1 - i = stack[h] - - -- restore i-th element - a[n], a[i] = a[i], a[n] - - stack[h] = stack[h] + 1 - end - return iter() -- tail-call - end - - return iter -end - - ---- construct a table containing all the order-permutations of a list. --- @param a list-like table --- @return a table of tables --- @usage permute.order_table {1,2,3} --> {{2,3,1},{3,2,1},{3,1,2},{1,3,2},{2,1,3},{1,2,3}} -function permute.order_table (a) - assert_arg(1,a,'table') - local res = {} - for t in permute.iter(a) do - append(res,copy(t)) - end - return res -end - - - ---- an iterator over all permutations of the elements of the given lists. --- @param ... list-like tables, they are nil-safe if a length-field `n` is provided (see `utils.pack`) --- @return an iterator which provides the next permutation as return values in the same order as the provided lists, preceeded by an index --- @usage --- local strs = utils.pack("one", nil, "three") -- adds an 'n' field for nil-safety --- local bools = utils.pack(true, false) --- local iter = permute.list_iter(strs, bools) --- --- print(iter()) --> 1, one, true --- print(iter()) --> 2, nil, true --- print(iter()) --> 3, three, true --- print(iter()) --> 4, one, false --- print(iter()) --> 5, nil, false --- print(iter()) --> 6, three, false -function permute.list_iter(...) - local elements = {...} - local pointers = {} - local sizes = {} - local size = #elements - for i, list in ipairs(elements) do - assert_arg(i,list,'table') - pointers[i] = 1 - sizes[i] = list.n or #list - end - local count = 0 - - return function() - if pointers[size] > sizes[size] then return end -- we're done - count = count + 1 - local r = { n = #elements } - local cascade_up = true - for i = 1, size do - r[i] = elements[i][pointers[i]] - if cascade_up then - pointers[i] = pointers[i] + 1 - if pointers[i] <= sizes[i] then - -- this list is not done yet, stop cascade - cascade_up = false - else - -- this list is done - if i ~= size then - -- reset pointer - pointers[i] = 1 - end - end - end - end - return count, utils.unpack(r) - end -end - - - ---- construct a table containing all the permutations of a set of lists. --- @param ... list-like tables, they are nil-safe if a length-field `n` is provided --- @return a list of lists, the sub-lists have an 'n' field for nil-safety --- @usage --- local strs = utils.pack("one", nil, "three") -- adds an 'n' field for nil-safety --- local bools = utils.pack(true, false) --- local results = permute.list_table(strs, bools) --- -- results = { --- -- { "one, true, n = 2 } --- -- { nil, true, n = 2 }, --- -- { "three, true, n = 2 }, --- -- { "one, false, n = 2 }, --- -- { nil, false, n = 2 }, --- -- { "three", false, n = 2 }, --- -- } -function permute.list_table(...) - local iter = permute.list_iter(...) - local results = {} - local i = 1 - while true do - local values = utils.pack(iter()) - if values[1] == nil then return results end - for i = 1, values.n do values[i] = values[i+1] end - values.n = values.n - 1 - results[i] = values - i = i + 1 - end -end - - --- backward compat, to be deprecated - ---- deprecated. --- @param ... --- @see permute.order_iter -function permute.iter(...) - utils.raise_deprecation { - source = "Penlight " .. utils._VERSION, - message = "function 'iter' was renamed to 'order_iter'", - version_removed = "2.0.0", - deprecated_after = "1.9.2", - } - - return permute.order_iter(...) -end - ---- deprecated. --- @param ... --- @see permute.order_iter -function permute.table(...) - utils.raise_deprecation { - source = "Penlight " .. utils._VERSION, - message = "function 'table' was renamed to 'order_table'", - version_removed = "2.0.0", - deprecated_after = "1.9.2", - } - - return permute.order_table(...) -end - -return permute diff --git a/game/scripts/vscripts/pl/pretty.lua b/game/scripts/vscripts/pl/pretty.lua deleted file mode 100644 index 9f3fb9d..0000000 --- a/game/scripts/vscripts/pl/pretty.lua +++ /dev/null @@ -1,438 +0,0 @@ ---- Pretty-printing Lua tables. --- Also provides a sandboxed Lua table reader and --- a function to present large numbers in human-friendly format. --- --- Dependencies: `pl.utils`, `pl.lexer`, `pl.stringx`, `debug` --- @module pl.pretty - -local append = table.insert -local concat = table.concat -local mfloor, mhuge = math.floor, math.huge -local mtype = math.type -local utils = require 'pl.utils' -local lexer = require 'pl.lexer' -local debug = require 'debug' -local quote_string = require'pl.stringx'.quote_string -local assert_arg = utils.assert_arg - -local original_tostring = tostring - --- Patch tostring to format numbers with better precision --- and to produce cross-platform results for --- infinite values and NaN. -local function tostring(value) - if type(value) ~= "number" then - return original_tostring(value) - elseif value ~= value then - return "NaN" - elseif value == mhuge then - return "Inf" - elseif value == -mhuge then - return "-Inf" - elseif (_VERSION ~= "Lua 5.3" or mtype(value) == "integer") and mfloor(value) == value then - return ("%d"):format(value) - else - local res = ("%.14g"):format(value) - if _VERSION == "Lua 5.3" and mtype(value) == "float" and not res:find("%.") then - -- Number is internally a float but looks like an integer. - -- Insert ".0" after first run of digits. - res = res:gsub("%d+", "%0.0", 1) - end - return res - end -end - -local pretty = {} - -local function save_global_env() - local env = {} - env.hook, env.mask, env.count = debug.gethook() - - -- env.hook is "external hook" if is a C hook function - if env.hook~="external hook" then - debug.sethook() - end - - env.string_mt = getmetatable("") - debug.setmetatable("", nil) - return env -end - -local function restore_global_env(env) - if env then - debug.setmetatable("", env.string_mt) - if env.hook~="external hook" then - debug.sethook(env.hook, env.mask, env.count) - end - end -end - ---- Read a string representation of a Lua table. --- This function loads and runs the string as Lua code, but bails out --- if it contains a function definition. --- Loaded string is executed in an empty environment. --- @string s string to read in `{...}` format, possibly with some whitespace --- before or after the curly braces. A single line comment may be present --- at the beginning. --- @return a table in case of success. --- If loading the string failed, return `nil` and error message. --- If executing loaded string failed, return `nil` and the error it raised. -function pretty.read(s) - assert_arg(1,s,'string') - if s:find '^%s*%-%-' then -- may start with a comment.. - s = s:gsub('%-%-.-\n','') - end - if not s:find '^%s*{' then return nil,"not a Lua table" end - if s:find '[^\'"%w_]function[^\'"%w_]' then - local tok = lexer.lua(s) - for t,v in tok do - if t == 'keyword' and v == 'function' then - return nil,"cannot have functions in table definition" - end - end - end - s = 'return '..s - local chunk,err = utils.load(s,'tbl','t',{}) - if not chunk then return nil,err end - local global_env = save_global_env() - local ok,ret = pcall(chunk) - restore_global_env(global_env) - if ok then return ret - else - return nil,ret - end -end - ---- Read a Lua chunk. --- @string s Lua code. --- @tab[opt] env environment used to run the code, empty by default. --- @bool[opt] paranoid abort loading if any looping constructs a found in the code --- and disable string methods. --- @return the environment in case of success or `nil` and syntax or runtime error --- if something went wrong. -function pretty.load (s, env, paranoid) - env = env or {} - if paranoid then - local tok = lexer.lua(s) - for t,v in tok do - if t == 'keyword' - and (v == 'for' or v == 'repeat' or v == 'function' or v == 'goto') - then - return nil,"looping not allowed" - end - end - end - local chunk,err = utils.load(s,'tbl','t',env) - if not chunk then return nil,err end - local global_env = paranoid and save_global_env() - local ok,err = pcall(chunk) - restore_global_env(global_env) - if not ok then return nil,err end - return env -end - -local function quote_if_necessary (v) - if not v then return '' - else - --AAS - if v:find ' ' then v = quote_string(v) end - end - return v -end - -local keywords - -local function is_identifier (s) - return type(s) == 'string' and s:find('^[%a_][%w_]*$') and not keywords[s] -end - -local function quote (s) - if type(s) == 'table' then - return pretty.write(s,'') - else - --AAS - return quote_string(s)-- ('%q'):format(tostring(s)) - end -end - -local function index (numkey,key) - --AAS - if not numkey then - key = quote(key) - key = key:find("^%[") and (" " .. key .. " ") or key - end - return '['..key..']' -end - - ---- Create a string representation of a Lua table. --- This function never fails, but may complain by returning an --- extra value. Normally puts out one item per line, using --- the provided indent; set the second parameter to an empty string --- if you want output on one line. --- --- *NOTE:* this is NOT a serialization function, not a full blown --- debug function. Checkout out respectively the --- [serpent](https://github.com/pkulchenko/serpent) --- or [inspect](https://github.com/kikito/inspect.lua) --- Lua modules for that if you need them. --- @tab tbl Table to serialize to a string. --- @string[opt] space The indent to use. --- Defaults to two spaces; pass an empty string for no indentation. --- @bool[opt] not_clever Pass `true` for plain output, e.g `{['key']=1}`. --- Defaults to `false`. --- @return a string --- @return an optional error message -function pretty.write (tbl,space,not_clever) - if type(tbl) ~= 'table' then - local res = tostring(tbl) - if type(tbl) == 'string' then return quote(tbl) end - return res, 'not a table' - end - if not keywords then - keywords = lexer.get_keywords() - end - local set = ' = ' - if space == '' then set = '=' end - space = space or ' ' - local lines = {} - local line = '' - local tables = {} - - - local function put(s) - if #s > 0 then - line = line..s - end - end - - local function putln (s) - if #line > 0 then - line = line..s - append(lines,line) - line = '' - else - append(lines,s) - end - end - - local function eat_last_comma () - local n = #lines - local lastch = lines[n]:sub(-1,-1) - if lastch == ',' then - lines[n] = lines[n]:sub(1,-2) - end - end - - - -- safe versions for iterators since 5.3+ honors metamethods that can throw - -- errors - local ipairs = function(t) - local i = 0 - local ok, v - local getter = function() return t[i] end - return function() - i = i + 1 - ok, v = pcall(getter) - if v == nil or not ok then return end - return i, t[i] - end - end - local pairs = function(t) - local k, v, ok - local getter = function() return next(t, k) end - return function() - ok, k, v = pcall(getter) - if not ok then return end - return k, v - end - end - - local writeit - writeit = function (t,oldindent,indent) - local tp = type(t) - if tp ~= 'string' and tp ~= 'table' then - putln(quote_if_necessary(tostring(t))..',') - elseif tp == 'string' then - -- if t:find('\n') then - -- putln('[[\n'..t..']],') - -- else - -- putln(quote(t)..',') - -- end - --AAS - putln(quote_string(t) ..",") - elseif tp == 'table' then - if tables[t] then - putln(',') - return - end - tables[t] = true - local newindent = indent..space - putln('{') - local used = {} - if not not_clever then - for i,val in ipairs(t) do - put(indent) - writeit(val,indent,newindent) - used[i] = true - end - end - local ordered_keys = {} - for k,v in pairs(t) do - if type(k) ~= 'number' then - ordered_keys[#ordered_keys + 1] = k - end - end - table.sort(ordered_keys, function (a, b) - if type(a) == type(b) then - return tostring(a) < tostring(b) - else - return type(a) < type(b) - end - end) - local function write_entry (key, val) - local tkey = type(key) - local numkey = tkey == 'number' - if not_clever then - key = tostring(key) - put(indent..index(numkey,key)..set) - writeit(val,indent,newindent) - else - if not numkey or not used[key] then -- non-array indices - if tkey ~= 'string' then - key = tostring(key) - end - if numkey or not is_identifier(key) then - key = index(numkey,key) - end - put(indent..key..set) - writeit(val,indent,newindent) - end - end - end - for i = 1, #ordered_keys do - local key = ordered_keys[i] - local val = t[key] - write_entry(key, val) - end - for key,val in pairs(t) do - if type(key) == 'number' then - write_entry(key, val) - end - end - tables[t] = nil - eat_last_comma() - putln(oldindent..'},') - else - putln(tostring(t)..',') - end - end - writeit(tbl,'',space) - eat_last_comma() - return concat(lines,#space > 0 and '\n' or '') -end - ---- Dump a Lua table out to a file or stdout. --- @tab t The table to write to a file or stdout. --- @string[opt] filename File name to write too. Defaults to writing --- to stdout. -function pretty.dump (t, filename) - if not filename then - print(pretty.write(t)) - return true - else - return utils.writefile(filename, pretty.write(t)) - end -end - ---- Dump a series of arguments to stdout for debug purposes. --- This function is attached to the module table `__call` method, to make it --- extra easy to access. So the full: --- --- print(require("pl.pretty").write({...})) --- --- Can be shortened to: --- --- require"pl.pretty" (...) --- --- Any `nil` entries will be printed as `""` to make them explicit. --- @param ... the parameters to dump to stdout. --- @usage --- -- example debug output --- require"pl.pretty" ("hello", nil, "world", { bye = "world", true} ) --- --- -- output: --- { --- ["arg 1"] = "hello", --- ["arg 2"] = "", --- ["arg 3"] = "world", --- ["arg 4"] = { --- true, --- bye = "world" --- } --- } -function pretty.debug(...) - local n = select("#", ...) - local t = { ... } - for i = 1, n do - local value = t[i] - if value == nil then - value = "" - end - t[i] = nil - t["arg " .. i] = value - end - - print(pretty.write(t)) - return true -end - - -local memp,nump = {'B','KiB','MiB','GiB'},{'','K','M','B'} - -local function comma (val) - local thou = math.floor(val/1000) - if thou > 0 then return comma(thou)..','.. tostring(val % 1000) - else return tostring(val) end -end - ---- Format large numbers nicely for human consumption. --- @number num a number. --- @string[opt] kind one of `'M'` (memory in `KiB`, `MiB`, etc.), --- `'N'` (postfixes are `'K'`, `'M'` and `'B'`), --- or `'T'` (use commas as thousands separator), `'N'` by default. --- @int[opt] prec number of digits to use for `'M'` and `'N'`, `1` by default. -function pretty.number (num,kind,prec) - local fmt = '%.'..(prec or 1)..'f%s' - if kind == 'T' then - return comma(num) - else - local postfixes, fact - if kind == 'M' then - fact = 1024 - postfixes = memp - else - fact = 1000 - postfixes = nump - end - local div = fact - local k = 1 - while num >= div and k <= #postfixes do - div = div * fact - k = k + 1 - end - div = div / fact - if k > #postfixes then k = k - 1; div = div/fact end - if k > 1 then - return fmt:format(num/div,postfixes[k] or 'duh') - else - return num..postfixes[1] - end - end -end - -return setmetatable(pretty, { - __call = function(self, ...) - return self.debug(...) - end -}) diff --git a/game/scripts/vscripts/pl/seq.lua b/game/scripts/vscripts/pl/seq.lua deleted file mode 100644 index 1c08d20..0000000 --- a/game/scripts/vscripts/pl/seq.lua +++ /dev/null @@ -1,544 +0,0 @@ ---- Manipulating iterators as sequences. --- See @{07-functional.md.Sequences|The Guide} --- --- Dependencies: `pl.utils`, `pl.types`, `debug` --- @module pl.seq - -local next,assert,pairs,tonumber,type,setmetatable = next,assert,pairs,tonumber,type,setmetatable -local strfind,format = string.find,string.format -local mrandom = math.random -local tsort,tappend = table.sort,table.insert -local io = io -local utils = require 'pl.utils' -local callable = require 'pl.types'.is_callable -local function_arg = utils.function_arg -local assert_arg = utils.assert_arg -local debug = require 'debug' - -local seq = {} - --- given a number, return a function(y) which returns true if y > x --- @param x a number -function seq.greater_than(x) - return function(v) - return tonumber(v) > x - end -end - --- given a number, returns a function(y) which returns true if y < x --- @param x a number -function seq.less_than(x) - return function(v) - return tonumber(v) < x - end -end - --- given any value, return a function(y) which returns true if y == x --- @param x a value -function seq.equal_to(x) - if type(x) == "number" then - return function(v) - return tonumber(v) == x - end - else - return function(v) - return v == x - end - end -end - ---- given a string, return a function(y) which matches y against the string. --- @param s a string -function seq.matching(s) - return function(v) - return strfind(v,s) - end -end - -local nexti - ---- sequence adaptor for a table. Note that if any generic function is --- passed a table, it will automatically use seq.list() --- @param t a list-like table --- @usage sum(list(t)) is the sum of all elements of t --- @usage for x in list(t) do...end -function seq.list(t) - assert_arg(1,t,'table') - if not nexti then - nexti = ipairs{} - end - local key,value = 0 - return function() - key,value = nexti(t,key) - return value - end -end - ---- return the keys of the table. --- @param t an arbitrary table --- @return iterator over keys -function seq.keys(t) - assert_arg(1,t,'table') - local key - return function() - key = next(t,key) - return key - end -end - -local list = seq.list -local function default_iter(iter) - if type(iter) == 'table' then return list(iter) - else return iter end -end - -seq.iter = default_iter - ---- create an iterator over a numerical range. Like the standard Python function xrange. --- @param start a number --- @param finish a number greater than start -function seq.range(start,finish) - local i = start - 1 - return function() - i = i + 1 - if i > finish then return nil - else return i end - end -end - --- count the number of elements in the sequence which satisfy the predicate --- @param iter a sequence --- @param condn a predicate function (must return either true or false) --- @param optional argument to be passed to predicate as second argument. --- @return count -function seq.count(iter,condn,arg) - local i = 0 - seq.foreach(iter,function(val) - if condn(val,arg) then i = i + 1 end - end) - return i -end - ---- return the minimum and the maximum value of the sequence. --- @param iter a sequence --- @return minimum value --- @return maximum value -function seq.minmax(iter) - local vmin,vmax = 1e70,-1e70 - for v in default_iter(iter) do - v = tonumber(v) - if v < vmin then vmin = v end - if v > vmax then vmax = v end - end - return vmin,vmax -end - ---- return the sum and element count of the sequence. --- @param iter a sequence --- @param fn an optional function to apply to the values -function seq.sum(iter,fn) - local s = 0 - local i = 0 - for v in default_iter(iter) do - if fn then v = fn(v) end - s = s + v - i = i + 1 - end - return s,i -end - ---- create a table from the sequence. (This will make the result a List.) --- @param iter a sequence --- @return a List --- @usage copy(list(ls)) is equal to ls --- @usage copy(list {1,2,3}) == List{1,2,3} -function seq.copy(iter) - local res,k = {},1 - for v in default_iter(iter) do - res[k] = v - k = k + 1 - end - setmetatable(res, require('pl.List')) - return res -end - ---- create a table of pairs from the double-valued sequence. --- @param iter a double-valued sequence --- @param i1 used to capture extra iterator values --- @param i2 as with pairs & ipairs --- @usage copy2(ipairs{10,20,30}) == {{1,10},{2,20},{3,30}} --- @return a list-like table -function seq.copy2 (iter,i1,i2) - local res,k = {},1 - for v1,v2 in iter,i1,i2 do - res[k] = {v1,v2} - k = k + 1 - end - return res -end - ---- create a table of 'tuples' from a multi-valued sequence. --- A generalization of copy2 above --- @param iter a multiple-valued sequence --- @return a list-like table -function seq.copy_tuples (iter) - iter = default_iter(iter) - local res = {} - local row = {iter()} - while #row > 0 do - tappend(res,row) - row = {iter()} - end - return res -end - ---- return an iterator of random numbers. --- @param n the length of the sequence --- @param l same as the first optional argument to math.random --- @param u same as the second optional argument to math.random --- @return a sequence -function seq.random(n,l,u) - local rand - assert(type(n) == 'number') - if u then - rand = function() return mrandom(l,u) end - elseif l then - rand = function() return mrandom(l) end - else - rand = mrandom - end - - return function() - if n == 0 then return nil - else - n = n - 1 - return rand() - end - end -end - ---- return an iterator to the sorted elements of a sequence. --- @param iter a sequence --- @param comp an optional comparison function (comp(x,y) is true if x < y) -function seq.sort(iter,comp) - local t = seq.copy(iter) - tsort(t,comp) - return list(t) -end - ---- return an iterator which returns elements of two sequences. --- @param iter1 a sequence --- @param iter2 a sequence --- @usage for x,y in seq.zip(ls1,ls2) do....end -function seq.zip(iter1,iter2) - iter1 = default_iter(iter1) - iter2 = default_iter(iter2) - return function() - return iter1(),iter2() - end -end - ---- Makes a table where the key/values are the values and value counts of the sequence. --- This version works with 'hashable' values like strings and numbers. --- `pl.tablex.count_map` is more general. --- @param iter a sequence --- @return a map-like table --- @return a table --- @see pl.tablex.count_map -function seq.count_map(iter) - local t = {} - local v - for s in default_iter(iter) do - v = t[s] - if v then t[s] = v + 1 - else t[s] = 1 end - end - return setmetatable(t, require('pl.Map')) -end - --- given a sequence, return all the unique values in that sequence. --- @param iter a sequence --- @param returns_table true if we return a table, not a sequence --- @return a sequence or a table; defaults to a sequence. -function seq.unique(iter,returns_table) - local t = seq.count_map(iter) - local res,k = {},1 - for key in pairs(t) do res[k] = key; k = k + 1 end - table.sort(res) - if returns_table then - return res - else - return list(res) - end -end - ---- print out a sequence iter with a separator. --- @param iter a sequence --- @param sep the separator (default space) --- @param nfields maximum number of values per line (default 7) --- @param fmt optional format function for each value -function seq.printall(iter,sep,nfields,fmt) - local write = io.write - if not sep then sep = ' ' end - if not nfields then - if sep == '\n' then nfields = 1e30 - else nfields = 7 end - end - if fmt then - local fstr = fmt - fmt = function(v) return format(fstr,v) end - end - local k = 1 - for v in default_iter(iter) do - if fmt then v = fmt(v) end - if k < nfields then - write(v,sep) - k = k + 1 - else - write(v,'\n') - k = 1 - end - end - write '\n' -end - --- return an iterator running over every element of two sequences (concatenation). --- @param iter1 a sequence --- @param iter2 a sequence -function seq.splice(iter1,iter2) - iter1 = default_iter(iter1) - iter2 = default_iter(iter2) - local iter = iter1 - return function() - local ret = iter() - if ret == nil then - if iter == iter1 then - iter = iter2 - return iter() - else return nil end - else - return ret - end - end -end - ---- return a sequence where every element of a sequence has been transformed --- by a function. If you don't supply an argument, then the function will --- receive both values of a double-valued sequence, otherwise behaves rather like --- tablex.map. --- @param fn a function to apply to elements; may take two arguments --- @param iter a sequence of one or two values --- @param arg optional argument to pass to function. -function seq.map(fn,iter,arg) - fn = function_arg(1,fn) - iter = default_iter(iter) - return function() - local v1,v2 = iter() - if v1 == nil then return nil end - return fn(v1,arg or v2) or false - end -end - ---- filter a sequence using a predicate function. --- @param iter a sequence of one or two values --- @param pred a boolean function; may take two arguments --- @param arg optional argument to pass to function. -function seq.filter (iter,pred,arg) - pred = function_arg(2,pred) - return function () - local v1,v2 - while true do - v1,v2 = iter() - if v1 == nil then return nil end - if pred(v1,arg or v2) then return v1,v2 end - end - end -end - ---- 'reduce' a sequence using a binary function. --- @func fn a function of two arguments --- @param iter a sequence --- @param initval optional initial value --- @usage seq.reduce(operator.add,seq.list{1,2,3,4}) == 10 --- @usage seq.reduce('-',{1,2,3,4,5}) == -13 -function seq.reduce (fn,iter,initval) - fn = function_arg(1,fn) - iter = default_iter(iter) - local val = initval or iter() - if val == nil then return nil end - for v in iter do - val = fn(val,v) - end - return val -end - ---- take the first n values from the sequence. --- @param iter a sequence of one or two values --- @param n number of items to take --- @return a sequence of at most n items -function seq.take (iter,n) - iter = default_iter(iter) - return function() - if n < 1 then return end - local val1,val2 = iter() - if not val1 then return end - n = n - 1 - return val1,val2 - end -end - ---- skip the first n values of a sequence --- @param iter a sequence of one or more values --- @param n number of items to skip -function seq.skip (iter,n) - n = n or 1 - for i = 1,n do - if iter() == nil then return list{} end - end - return iter -end - ---- a sequence with a sequence count and the original value. --- enum(copy(ls)) is a roundabout way of saying ipairs(ls). --- @param iter a single or double valued sequence --- @return sequence of (i,v), i = 1..n and v is from iter. -function seq.enum (iter) - local i = 0 - iter = default_iter(iter) - return function () - local val1,val2 = iter() - if not val1 then return end - i = i + 1 - return i,val1,val2 - end -end - ---- map using a named method over a sequence. --- @param iter a sequence --- @param name the method name --- @param arg1 optional first extra argument --- @param arg2 optional second extra argument -function seq.mapmethod (iter,name,arg1,arg2) - iter = default_iter(iter) - return function() - local val = iter() - if not val then return end - local fn = val[name] - if not fn then error(type(val).." does not have method "..name) end - return fn(val,arg1,arg2) - end -end - ---- a sequence of (last,current) values from another sequence. --- This will return S(i-1),S(i) if given S(i) --- @param iter a sequence -function seq.last (iter) - iter = default_iter(iter) - local val, l = iter(), nil - if val == nil then return list{} end - return function () - val,l = iter(),val - if val == nil then return nil end - return val,l - end -end - ---- call the function on each element of the sequence. --- @param iter a sequence with up to 3 values --- @param fn a function -function seq.foreach(iter,fn) - fn = function_arg(2,fn) - for i1,i2,i3 in default_iter(iter) do fn(i1,i2,i3) end -end - ----------------------- Sequence Adapters --------------------- - -local SMT - -local function SW (iter,...) - if callable(iter) then - return setmetatable({iter=iter},SMT) - else - return iter,... - end -end - - --- can't directly look these up in seq because of the wrong argument order... -local map,reduce,mapmethod = seq.map, seq.reduce, seq.mapmethod -local overrides = { - map = function(self,fun,arg) - return map(fun,self,arg) - end, - reduce = function(self,fun,initval) - return reduce(fun,self,initval) - end -} - -SMT = { - __index = function (tbl,key) - local fn = overrides[key] or seq[key] - if fn then - return function(sw,...) return SW(fn(sw.iter,...)) end - else - return function(sw,...) return SW(mapmethod(sw.iter,key,...)) end - end - end, - __call = function (sw) - return sw.iter() - end, -} - -setmetatable(seq,{ - __call = function(tbl,iter,extra) - if not callable(iter) then - if type(iter) == 'table' then iter = seq.list(iter) - else return iter - end - end - if extra then - return setmetatable({iter=function() - return iter(extra) - end},SMT) - else - return setmetatable({iter=iter},SMT) - end - end -}) - ---- create a wrapped iterator over all lines in the file. --- @param f either a filename, file-like object, or 'STDIN' (for standard input) --- @param ... for Lua 5.2 only, optional format specifiers, as in `io.read`. --- @return a sequence wrapper -function seq.lines (f,...) - local iter,obj - if f == 'STDIN' then - f = io.stdin - elseif type(f) == 'string' then - iter,obj = io.lines(f,...) - elseif not f.read then - error("Pass either a string or a file-like object",2) - end - if not iter then - iter,obj = f:lines(...) - end - if obj then -- LuaJIT version returns a function operating on a file - local lines,file = iter,obj - iter = function() return lines(file) end - end - return SW(iter) -end - -function seq.import () - debug.setmetatable(function() end,{ - __index = function(tbl,key) - local s = overrides[key] or seq[key] - if s then return s - else - return function(s,...) return seq.mapmethod(s,key,...) end - end - end - }) -end - -return seq diff --git a/game/scripts/vscripts/pl/sip.lua b/game/scripts/vscripts/pl/sip.lua deleted file mode 100644 index 5d1f2aa..0000000 --- a/game/scripts/vscripts/pl/sip.lua +++ /dev/null @@ -1,337 +0,0 @@ ---- Simple Input Patterns (SIP). --- SIP patterns start with '$', then a --- one-letter type, and then an optional variable in curly braces. --- --- sip.match('$v=$q','name="dolly"',res) --- ==> res=={'name','dolly'} --- sip.match('($q{first},$q{second})','("john","smith")',res) --- ==> res=={second='smith',first='john'} --- --- Type names: --- --- v identifier --- i integer --- f floating-point --- q quoted string --- ([{< match up to closing bracket --- --- See @{08-additional.md.Simple_Input_Patterns|the Guide} --- --- @module pl.sip - -local loadstring = rawget(_G,'loadstring') or load -local unpack = rawget(_G,'unpack') or rawget(table,'unpack') - -local append,concat = table.insert,table.concat -local ipairs,type = ipairs,type -local io,_G = io,_G -local print,rawget = print,rawget - -local patterns = { - FLOAT = '[%+%-%d]%d*%.?%d*[eE]?[%+%-]?%d*', - INTEGER = '[+%-%d]%d*', - IDEN = '[%a_][%w_]*', - OPTION = '[%a_][%w_%-]*', -} - -local function assert_arg(idx,val,tp) - if type(val) ~= tp then - error("argument "..idx.." must be "..tp, 2) - end -end - -local sip = {} - -local brackets = {['<'] = '>', ['('] = ')', ['{'] = '}', ['['] = ']' } -local stdclasses = {a=1,c=0,d=1,l=1,p=0,u=1,w=1,x=1,s=0} - -local function group(s) - return '('..s..')' -end - --- escape all magic characters except $, which has special meaning --- Also, un-escape any characters after $, so $( and $[ passes through as is. -local function escape (spec) - return (spec:gsub('[%-%.%+%[%]%(%)%^%%%?%*]','%%%0'):gsub('%$%%(%S)','$%1')) -end - --- Most spaces within patterns can match zero or more spaces. --- Spaces between alphanumeric characters or underscores or between --- patterns that can match these characters, however, must match at least --- one space. Otherwise '$v $v' would match 'abcd' as {'abc', 'd'}. --- This function replaces continuous spaces within a pattern with either --- '%s*' or '%s+' according to this rule. The pattern has already --- been stripped of pattern names by now. -local function compress_spaces(patt) - return (patt:gsub("()%s+()", function(i1, i2) - local before = patt:sub(i1 - 2, i1 - 1) - if before:match('%$[vifadxlu]') or before:match('^[^%$]?[%w_]$') then - local after = patt:sub(i2, i2 + 1) - if after:match('%$[vifadxlu]') or after:match('^[%w_]') then - return '%s+' - end - end - return '%s*' - end)) -end - -local pattern_map = { - v = group(patterns.IDEN), - i = group(patterns.INTEGER), - f = group(patterns.FLOAT), - o = group(patterns.OPTION), - r = '(%S.*)', - p = '([%a]?[:]?[\\/%.%w_]+)' -} - -function sip.custom_pattern(flag,patt) - pattern_map[flag] = patt -end - ---- convert a SIP pattern into the equivalent Lua string pattern. --- @param spec a SIP pattern --- @param options a table; only the at_start field is --- currently meaningful and ensures that the pattern is anchored --- at the start of the string. --- @return a Lua string pattern. -function sip.create_pattern (spec,options) - assert_arg(1,spec,'string') - local fieldnames,fieldtypes = {},{} - - if type(spec) == 'string' then - spec = escape(spec) - else - local res = {} - for i,s in ipairs(spec) do - res[i] = escape(s) - end - spec = concat(res,'.-') - end - - local kount = 1 - - local function addfield (name,type) - name = name or kount - append(fieldnames,name) - fieldtypes[name] = type - kount = kount + 1 - end - - local named_vars = spec:find('{%a+}') - - if options and options.at_start then - spec = '^'..spec - end - if spec:sub(-1,-1) == '$' then - spec = spec:sub(1,-2)..'$r' - if named_vars then spec = spec..'{rest}' end - end - - local names - - if named_vars then - names = {} - spec = spec:gsub('{(%a+)}',function(name) - append(names,name) - return '' - end) - end - spec = compress_spaces(spec) - - local k = 1 - local err - local r = (spec:gsub('%$%S',function(s) - local type,name - type = s:sub(2,2) - if names then name = names[k]; k=k+1 end - -- this kludge is necessary because %q generates two matches, and - -- we want to ignore the first. Not a problem for named captures. - if not names and type == 'q' then - addfield(nil,'Q') - else - addfield(name,type) - end - local res - if pattern_map[type] then - res = pattern_map[type] - elseif type == 'q' then - -- some Lua pattern matching voodoo; we want to match '...' as - -- well as "...", and can use the fact that %n will match a - -- previous capture. Adding the extra field above comes from needing - -- to accommodate the extra spurious match (which is either ' or ") - addfield(name,type) - res = '(["\'])(.-)%'..(kount-2) - else - local endbracket = brackets[type] - if endbracket then - res = '(%b'..type..endbracket..')' - elseif stdclasses[type] or stdclasses[type:lower()] then - res = '(%'..type..'+)' - else - err = "unknown format type or character class" - end - end - return res - end)) - - if err then - return nil,err - else - return r,fieldnames,fieldtypes - end -end - - -local function tnumber (s) - return s == 'd' or s == 'i' or s == 'f' -end - -function sip.create_spec_fun(spec,options) - local fieldtypes,fieldnames - local ls = {} - spec,fieldnames,fieldtypes = sip.create_pattern(spec,options) - if not spec then return spec,fieldnames end - local named_vars = type(fieldnames[1]) == 'string' - for i = 1,#fieldnames do - append(ls,'mm'..i) - end - ls[1] = ls[1] or "mm1" -- behave correctly if there are no patterns - local fun = ('return (function(s,res)\n\tlocal %s = s:match(%q)\n'):format(concat(ls,','),spec) - fun = fun..'\tif not mm1 then return false end\n' - local k=1 - for i,f in ipairs(fieldnames) do - if f ~= '_' then - local var = 'mm'..i - if tnumber(fieldtypes[f]) then - var = 'tonumber('..var..')' - elseif brackets[fieldtypes[f]] then - var = var..':sub(2,-2)' - end - if named_vars then - fun = ('%s\tres.%s = %s\n'):format(fun,f,var) - else - if fieldtypes[f] ~= 'Q' then -- we skip the string-delim capture - fun = ('%s\tres[%d] = %s\n'):format(fun,k,var) - k = k + 1 - end - end - end - end - return fun..'\treturn true\nend)\n', named_vars -end - ---- convert a SIP pattern into a matching function. --- The returned function takes two arguments, the line and an empty table. --- If the line matched the pattern, then this function returns true --- and the table is filled with field-value pairs. --- @param spec a SIP pattern --- @param options optional table; {at_start=true} ensures that the pattern --- is anchored at the start of the string. --- @return a function if successful, or nil,error -function sip.compile(spec,options) - assert_arg(1,spec,'string') - local fun,names = sip.create_spec_fun(spec,options) - if not fun then return nil,names end - if rawget(_G,'_DEBUG') then print(fun) end - local chunk,err = loadstring(fun,'tmp') - if err then return nil,err end - return chunk(),names -end - -local cache = {} - ---- match a SIP pattern against a string. --- @param spec a SIP pattern --- @param line a string --- @param res a table to receive values --- @param options (optional) option table --- @return true or false -function sip.match (spec,line,res,options) - assert_arg(1,spec,'string') - assert_arg(2,line,'string') - assert_arg(3,res,'table') - if not cache[spec] then - cache[spec] = sip.compile(spec,options) - end - return cache[spec](line,res) -end - ---- match a SIP pattern against the start of a string. --- @param spec a SIP pattern --- @param line a string --- @param res a table to receive values --- @return true or false -function sip.match_at_start (spec,line,res) - return sip.match(spec,line,res,{at_start=true}) -end - ---- given a pattern and a file object, return an iterator over the results --- @param spec a SIP pattern --- @param f a file-like object. -function sip.fields (spec,f) - assert_arg(1,spec,'string') - if not f then return nil,"no file object" end - local fun,err = sip.compile(spec) - if not fun then return nil,err end - local res = {} - return function() - while true do - local line = f:read() - if not line then return end - if fun(line,res) then - local values = res - res = {} - return unpack(values) - end - end - end -end - -local read_patterns = {} - ---- register a match which will be used in the read function. --- @string spec a SIP pattern --- @func fun a function to be called with the results of the match --- @see read -function sip.pattern (spec,fun) - assert_arg(1,spec,'string') - local pat,named = sip.compile(spec) - append(read_patterns,{pat=pat,named=named,callback=fun}) -end - ---- enter a loop which applies all registered matches to the input file. --- @param f a file-like object --- @array matches optional list of `{spec,fun}` pairs, as for `pattern` above. -function sip.read (f,matches) - local owned,err - if not f then return nil,"no file object" end - if type(f) == 'string' then - f,err = io.open(f) - if not f then return nil,err end - owned = true - end - if matches then - for _,p in ipairs(matches) do - sip.pattern(p[1],p[2]) - end - end - local res = {} - for line in f:lines() do - for _,item in ipairs(read_patterns) do - if item.pat(line,res) then - if item.callback then - if item.named then - item.callback(res) - else - item.callback(unpack(res)) - end - end - res = {} - break - end - end - end - if owned then f:close() end -end - -return sip diff --git a/game/scripts/vscripts/pl/strict.lua b/game/scripts/vscripts/pl/strict.lua deleted file mode 100644 index 67cbf5b..0000000 --- a/game/scripts/vscripts/pl/strict.lua +++ /dev/null @@ -1,138 +0,0 @@ ---- Checks uses of undeclared global variables. --- All global variables must be 'declared' through a regular assignment --- (even assigning `nil` will do) in a main chunk before being used --- anywhere or assigned to inside a function. Existing metatables `__newindex` and `__index` --- metamethods are respected. --- --- You can set any table to have strict behaviour using `strict.module`. Creating a new --- module with `strict.closed_module` makes the module immune to monkey-patching, if --- you don't wish to encourage monkey business. --- --- If the global `PENLIGHT_NO_GLOBAL_STRICT` is defined, then this module won't make the --- global environment strict - if you just want to explicitly set table strictness. --- --- @module pl.strict - -require 'debug' -- for Lua 5.2 -local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget -local strict = {} - -local function what () - local d = getinfo(3, "S") - return d and d.what or "C" -end - ---- make an existing table strict. --- @string[opt] name name of table --- @tab[opt] mod the table to protect - if `nil` then we'll return a new table --- @tab[opt] predeclared - table of variables that are to be considered predeclared. --- @return the given table, or a new table --- @usage --- local M = { hello = "world" } --- strict.module ("Awesome_Module", M, { --- Lua = true, -- defines allowed keys --- }) --- --- assert(M.hello == "world") --- assert(M.Lua == nil) -- access allowed, but has no value yet --- M.Lua = "Rocks" --- assert(M.Lua == "Rocks") --- M.not_allowed = "bad boy" -- throws an error -function strict.module (name,mod,predeclared) - local mt, old_newindex, old_index, old_index_type, global - if predeclared then - global = predeclared.__global - end - if type(mod) == 'table' then - mt = getmetatable(mod) - if mt and rawget(mt,'__declared') then return end -- already patched... - else - mod = {} - end - if mt == nil then - mt = {} - setmetatable(mod, mt) - else - old_newindex = mt.__newindex - old_index = mt.__index - old_index_type = type(old_index) - end - mt.__declared = predeclared or {} - mt.__newindex = function(t, n, v) - if old_newindex then - old_newindex(t, n, v) - if rawget(t,n)~=nil then return end - end - if not mt.__declared[n] then - if global then - local w = what() - if w ~= "main" and w ~= "C" then - error("assign to undeclared global '"..n.."'", 2) - end - end - mt.__declared[n] = true - end - rawset(t, n, v) - end - mt.__index = function(t,n) - if not mt.__declared[n] and what() ~= "C" then - if old_index then - if old_index_type == "table" then - local fallback = old_index[n] - if fallback ~= nil then - return fallback - end - else - local res = old_index(t, n) - if res ~= nil then - return res - end - end - end - local msg = "variable '"..n.."' is not declared" - if name then - msg = msg .. " in '"..tostring(name).."'" - end - error(msg, 2) - end - return rawget(t, n) - end - return mod -end - ---- make all tables in a table strict. --- So `strict.make_all_strict(_G)` prevents monkey-patching --- of any global table --- @tab T the table containing the tables to protect. Table `T` itself will NOT be protected. -function strict.make_all_strict (T) - for k,v in pairs(T) do - if type(v) == 'table' and v ~= T then - strict.module(k,v) - end - end -end - ---- make a new module table which is closed to further changes. --- @tab mod module table --- @string name module name -function strict.closed_module (mod,name) - -- No clue to what this is useful for? see tests - -- Deprecate this and remove??? - local M = {} - mod = mod or {} - local mt = getmetatable(mod) - if not mt then - mt = {} - setmetatable(mod,mt) - end - mt.__newindex = function(t,k,v) - M[k] = v - end - return strict.module(name,M) -end - -if not rawget(_G,'PENLIGHT_NO_GLOBAL_STRICT') then - strict.module(nil,_G,{_PROMPT=true,_PROMPT2=true,__global=true}) -end - -return strict diff --git a/game/scripts/vscripts/pl/stringio.lua b/game/scripts/vscripts/pl/stringio.lua deleted file mode 100644 index 666f415..0000000 --- a/game/scripts/vscripts/pl/stringio.lua +++ /dev/null @@ -1,158 +0,0 @@ ---- Reading and writing strings using file-like objects.
--- --- f = stringio.open(text) --- l1 = f:read() -- read first line --- n,m = f:read ('*n','*n') -- read two numbers --- for line in f:lines() do print(line) end -- iterate over all lines --- f = stringio.create() --- f:write('hello') --- f:write('dolly') --- assert(f:value(),'hellodolly') --- --- See @{03-strings.md.File_style_I_O_on_Strings|the Guide}. --- @module pl.stringio - -local unpack = rawget(_G,'unpack') or rawget(table,'unpack') -local tonumber = tonumber -local concat,append = table.concat,table.insert - -local stringio = {} - --- Writer class -local SW = {} -SW.__index = SW - -local function xwrite(self,...) - local args = {...} --arguments may not be nil! - for i = 1, #args do - append(self.tbl,args[i]) - end -end - -function SW:write(arg1,arg2,...) - if arg2 then - xwrite(self,arg1,arg2,...) - else - append(self.tbl,arg1) - end -end - -function SW:writef(fmt,...) - self:write(fmt:format(...)) -end - -function SW:value() - return concat(self.tbl) -end - -function SW:__tostring() - return self:value() -end - -function SW:close() -- for compatibility only -end - -function SW:seek() -end - --- Reader class -local SR = {} -SR.__index = SR - -function SR:_read(fmt) - local i,str = self.i,self.str - local sz = #str - if i > sz then return nil end - local res - if fmt == '*l' or fmt == '*L' then - local idx = str:find('\n',i) or (sz+1) - res = str:sub(i,fmt == '*l' and idx-1 or idx) - self.i = idx+1 - elseif fmt == '*a' then - res = str:sub(i) - self.i = sz - elseif fmt == '*n' then - local _,i2,idx - _,idx = str:find ('%s*%d+',i) - _,i2 = str:find ('^%.%d+',idx+1) - if i2 then idx = i2 end - _,i2 = str:find ('^[eE][%+%-]*%d+',idx+1) - if i2 then idx = i2 end - local val = str:sub(i,idx) - res = tonumber(val) - self.i = idx+1 - elseif type(fmt) == 'number' then - res = str:sub(i,i+fmt-1) - self.i = i + fmt - else - error("bad read format",2) - end - return res -end - -function SR:read(...) - if select('#',...) == 0 then - return self:_read('*l') - else - local res, fmts = {},{...} - for i = 1, #fmts do - res[i] = self:_read(fmts[i]) - end - return unpack(res) - end -end - -function SR:seek(whence,offset) - local base - whence = whence or 'cur' - offset = offset or 0 - if whence == 'set' then - base = 1 - elseif whence == 'cur' then - base = self.i - elseif whence == 'end' then - base = #self.str - end - self.i = base + offset - return self.i -end - -function SR:lines(...) - local n, args = select('#',...) - if n > 0 then - args = {...} - end - return function() - if n == 0 then - return self:_read '*l' - else - return self:read(unpack(args)) - end - end -end - -function SR:close() -- for compatibility only -end - ---- create a file-like object which can be used to construct a string. --- The resulting object has an extra `value()` method for --- retrieving the string value. Implements `file:write`, `file:seek`, `file:lines`, --- plus an extra `writef` method which works like `utils.printf`. --- @usage f = create(); f:write('hello, dolly\n'); print(f:value()) -function stringio.create() - return setmetatable({tbl={}},SW) -end - ---- create a file-like object for reading from a given string. --- Implements `file:read`. --- @string s The input string. --- @usage fs = open '20 10'; x,y = f:read ('*n','*n'); assert(x == 20 and y == 10) -function stringio.open(s) - return setmetatable({str=s,i=1},SR) -end - -function stringio.lines(s,...) - return stringio.open(s):lines(...) -end - -return stringio diff --git a/game/scripts/vscripts/pl/stringx.lua b/game/scripts/vscripts/pl/stringx.lua deleted file mode 100644 index 75c61c7..0000000 --- a/game/scripts/vscripts/pl/stringx.lua +++ /dev/null @@ -1,917 +0,0 @@ ---- Python-style extended string library. --- --- see 3.6.1 of the Python reference. --- If you want to make these available as string methods, then say --- `stringx.import()` to bring them into the standard `string` table. --- --- See @{03-strings.md|the Guide} --- --- Dependencies: `pl.utils`, `pl.types` --- @module pl.stringx -local utils = require 'pl.utils' -local is_callable = require 'pl.types'.is_callable -local string = string -local find = string.find -local type,setmetatable,ipairs = type,setmetatable,ipairs -local error = error -local gsub = string.gsub -local rep = string.rep -local sub = string.sub -local reverse = string.reverse -local concat = table.concat -local append = table.insert -local remove = table.remove -local escape = utils.escape -local ceil, max = math.ceil, math.max -local assert_arg,usplit = utils.assert_arg,utils.split -local lstrip -local unpack = utils.unpack -local pack = utils.pack - -local function assert_string (n,s) - assert_arg(n,s,'string') -end - -local function non_empty(s) - return #s > 0 -end - -local function assert_nonempty_string(n,s) - assert_arg(n,s,'string',non_empty,'must be a non-empty string') -end - -local function makelist(l) - return setmetatable(l, require('pl.List')) -end - -local stringx = {} - ------------------- --- String Predicates --- @section predicates - ---- does s only contain alphabetic characters? --- @string s a string -function stringx.isalpha(s) - assert_string(1,s) - return find(s,'^%a+$') == 1 -end - ---- does s only contain digits? --- @string s a string -function stringx.isdigit(s) - assert_string(1,s) - return find(s,'^%d+$') == 1 -end - ---- does s only contain alphanumeric characters? --- @string s a string -function stringx.isalnum(s) - assert_string(1,s) - return find(s,'^%w+$') == 1 -end - ---- does s only contain whitespace? --- Matches on pattern '%s' so matches space, newline, tabs, etc. --- @string s a string -function stringx.isspace(s) - assert_string(1,s) - return find(s,'^%s+$') == 1 -end - ---- does s only contain lower case characters? --- @string s a string -function stringx.islower(s) - assert_string(1,s) - return find(s,'^[%l%s]+$') == 1 -end - ---- does s only contain upper case characters? --- @string s a string -function stringx.isupper(s) - assert_string(1,s) - return find(s,'^[%u%s]+$') == 1 -end - -local function raw_startswith(s, prefix) - return find(s,prefix,1,true) == 1 -end - -local function raw_endswith(s, suffix) - return #s >= #suffix and find(s, suffix, #s-#suffix+1, true) and true or false -end - -local function test_affixes(s, affixes, fn) - if type(affixes) == 'string' then - return fn(s,affixes) - elseif type(affixes) == 'table' then - for _,affix in ipairs(affixes) do - if fn(s,affix) then return true end - end - return false - else - error(("argument #2 expected a 'string' or a 'table', got a '%s'"):format(type(affixes))) - end -end - ---- does s start with prefix or one of prefixes? --- @string s a string --- @param prefix a string or an array of strings -function stringx.startswith(s,prefix) - assert_string(1,s) - return test_affixes(s,prefix,raw_startswith) -end - ---- does s end with suffix or one of suffixes? --- @string s a string --- @param suffix a string or an array of strings -function stringx.endswith(s,suffix) - assert_string(1,s) - return test_affixes(s,suffix,raw_endswith) -end - ---- Strings and Lists --- @section lists - ---- concatenate the strings using this string as a delimiter. --- Note that the arguments are reversed from `string.concat`. --- @string s the string --- @param seq a table of strings or numbers --- @usage stringx.join(' ', {1,2,3}) == '1 2 3' -function stringx.join(s,seq) - assert_string(1,s) - return concat(seq,s) -end - ---- Split a string into a list of lines. --- `"\r"`, `"\n"`, and `"\r\n"` are considered line ends. --- They are not included in the lines unless `keepends` is passed. --- Terminal line end does not produce an extra line. --- Splitting an empty string results in an empty list. --- @string s the string. --- @bool[opt] keep_ends include line ends. --- @return List of lines -function stringx.splitlines(s, keep_ends) - assert_string(1, s) - local res = {} - local pos = 1 - while true do - local line_end_pos = find(s, '[\r\n]', pos) - if not line_end_pos then - break - end - - local line_end = sub(s, line_end_pos, line_end_pos) - if line_end == '\r' and sub(s, line_end_pos + 1, line_end_pos + 1) == '\n' then - line_end = '\r\n' - end - - local line = sub(s, pos, line_end_pos - 1) - if keep_ends then - line = line .. line_end - end - append(res, line) - - pos = line_end_pos + #line_end - end - - if pos <= #s then - append(res, sub(s, pos)) - end - return makelist(res) -end - ---- split a string into a list of strings using a delimiter. --- @function split --- @string s the string --- @string[opt] re a delimiter (defaults to whitespace) --- @int[opt] n maximum number of results --- @return List --- @usage #(stringx.split('one two')) == 2 --- @usage stringx.split('one,two,three', ',') == List{'one','two','three'} --- @usage stringx.split('one,two,three', ',', 2) == List{'one','two,three'} -function stringx.split(s,re,n) - assert_string(1,s) - local plain = true - if not re then -- default spaces - s = lstrip(s) - plain = false - end - local res = usplit(s,re,plain,n) - if re and re ~= '' and - find(s,re,-#re,true) and - (n or math.huge) > #res then - res[#res+1] = "" - end - return makelist(res) -end - ---- replace all tabs in s with tabsize spaces. If not specified, tabsize defaults to 8. --- Tab stops will be honored. --- @string s the string --- @int tabsize[opt=8] number of spaces to expand each tab --- @return expanded string --- @usage stringx.expandtabs('\tone,two,three', 4) == ' one,two,three' --- @usage stringx.expandtabs(' \tone,two,three', 4) == ' one,two,three' -function stringx.expandtabs(s,tabsize) - assert_string(1,s) - tabsize = tabsize or 8 - return (s:gsub("([^\t\r\n]*)\t", function(before_tab) - if tabsize == 0 then - return before_tab - else - return before_tab .. (" "):rep(tabsize - #before_tab % tabsize) - end - end)) -end - ---- Finding and Replacing --- @section find - -local function _find_all(s,sub,first,last,allow_overlap) - first = first or 1 - last = last or #s - if sub == '' then return last+1,last-first+1 end - local i1,i2 = find(s,sub,first,true) - local res - local k = 0 - while i1 do - if last and i2 > last then break end - res = i1 - k = k + 1 - if allow_overlap then - i1,i2 = find(s,sub,i1+1,true) - else - i1,i2 = find(s,sub,i2+1,true) - end - end - return res,k -end - ---- find index of first instance of sub in s from the left. --- @string s the string --- @string sub substring --- @int[opt] first first index --- @int[opt] last last index --- @return start index, or nil if not found -function stringx.lfind(s,sub,first,last) - assert_string(1,s) - assert_string(2,sub) - local i1, i2 = find(s,sub,first,true) - - if i1 and (not last or i2 <= last) then - return i1 - else - return nil - end -end - ---- find index of first instance of sub in s from the right. --- @string s the string --- @string sub substring --- @int[opt] first first index --- @int[opt] last last index --- @return start index, or nil if not found -function stringx.rfind(s,sub,first,last) - assert_string(1,s) - assert_string(2,sub) - return (_find_all(s,sub,first,last,true)) -end - ---- replace up to n instances of old by new in the string s. --- If n is not present, replace all instances. --- @string s the string --- @string old the target substring --- @string new the substitution --- @int[opt] n optional maximum number of substitutions --- @return result string -function stringx.replace(s,old,new,n) - assert_string(1,s) - assert_string(2,old) - assert_string(3,new) - return (gsub(s,escape(old),new:gsub('%%','%%%%'),n)) -end - ---- count all instances of substring in string. --- @string s the string --- @string sub substring --- @bool[opt] allow_overlap allow matches to overlap --- @usage --- assert(stringx.count('banana', 'ana') == 1) --- assert(stringx.count('banana', 'ana', true) == 2) -function stringx.count(s,sub,allow_overlap) - assert_string(1,s) - local _,k = _find_all(s,sub,1,false,allow_overlap) - return k -end - ---- Stripping and Justifying --- @section strip - -local function _just(s,w,ch,left,right) - local n = #s - if w > n then - if not ch then ch = ' ' end - local f1,f2 - if left and right then - local rn = ceil((w-n)/2) - local ln = w - n - rn - f1 = rep(ch,ln) - f2 = rep(ch,rn) - elseif right then - f1 = rep(ch,w-n) - f2 = '' - else - f2 = rep(ch,w-n) - f1 = '' - end - return f1..s..f2 - else - return s - end -end - ---- left-justify s with width w. --- @string s the string --- @int w width of justification --- @string[opt=' '] ch padding character --- @usage stringx.ljust('hello', 10, '*') == '*****hello' -function stringx.ljust(s,w,ch) - assert_string(1,s) - assert_arg(2,w,'number') - return _just(s,w,ch,true,false) -end - ---- right-justify s with width w. --- @string s the string --- @int w width of justification --- @string[opt=' '] ch padding character --- @usage stringx.rjust('hello', 10, '*') == 'hello*****' -function stringx.rjust(s,w,ch) - assert_string(1,s) - assert_arg(2,w,'number') - return _just(s,w,ch,false,true) -end - ---- center-justify s with width w. --- @string s the string --- @int w width of justification --- @string[opt=' '] ch padding character --- @usage stringx.center('hello', 10, '*') == '**hello***' -function stringx.center(s,w,ch) - assert_string(1,s) - assert_arg(2,w,'number') - return _just(s,w,ch,true,true) -end - -local function _strip(s,left,right,chrs) - if not chrs then - chrs = '%s' - else - chrs = '['..escape(chrs)..']' - end - local f = 1 - local t - if left then - local i1,i2 = find(s,'^'..chrs..'*') - if i2 >= i1 then - f = i2+1 - end - end - if right then - if #s < 200 then - local i1,i2 = find(s,chrs..'*$',f) - if i2 >= i1 then - t = i1-1 - end - else - local rs = reverse(s) - local i1,i2 = find(rs, '^'..chrs..'*') - if i2 >= i1 then - t = -i2-1 - end - end - end - return sub(s,f,t) -end - ---- trim any characters on the left of s. --- @string s the string --- @string[opt='%s'] chrs default any whitespace character, --- but can be a string of characters to be trimmed -function stringx.lstrip(s,chrs) - assert_string(1,s) - return _strip(s,true,false,chrs) -end -lstrip = stringx.lstrip - ---- trim any characters on the right of s. --- @string s the string --- @string[opt='%s'] chrs default any whitespace character, --- but can be a string of characters to be trimmed -function stringx.rstrip(s,chrs) - assert_string(1,s) - return _strip(s,false,true,chrs) -end - ---- trim any characters on both left and right of s. --- @string s the string --- @string[opt='%s'] chrs default any whitespace character, --- but can be a string of characters to be trimmed --- @usage stringx.strip(' --== Hello ==-- ', "- =") --> 'Hello' -function stringx.strip(s,chrs) - assert_string(1,s) - return _strip(s,true,true,chrs) -end - ---- Partitioning Strings --- @section partitioning - ---- split a string using a pattern. Note that at least one value will be returned! --- @string s the string --- @string[opt='%s'] re a Lua string pattern (defaults to whitespace) --- @return the parts of the string --- @usage a,b = line:splitv('=') --- @see utils.splitv -function stringx.splitv(s,re) - assert_string(1,s) - return utils.splitv(s,re) -end - --- The partition functions split a string using a delimiter into three parts: --- the part before, the delimiter itself, and the part afterwards -local function _partition(p,delim,fn) - local i1,i2 = fn(p,delim) - if not i1 or i1 == -1 then - return p,'','' - else - if not i2 then i2 = i1 end - return sub(p,1,i1-1),sub(p,i1,i2),sub(p,i2+1) - end -end - ---- partition the string using first occurance of a delimiter --- @string s the string --- @string ch delimiter (match as plain string, no patterns) --- @return part before ch --- @return ch --- @return part after ch --- @usage {stringx.partition('a,b,c', ','))} == {'a', ',', 'b,c'} --- @usage {stringx.partition('abc', 'x'))} == {'abc', '', ''} -function stringx.partition(s,ch) - assert_string(1,s) - assert_nonempty_string(2,ch) - return _partition(s,ch,stringx.lfind) -end - ---- partition the string p using last occurance of a delimiter --- @string s the string --- @string ch delimiter (match as plain string, no patterns) --- @return part before ch --- @return ch --- @return part after ch --- @usage {stringx.rpartition('a,b,c', ','))} == {'a,b', ',', 'c'} --- @usage {stringx.rpartition('abc', 'x'))} == {'', '', 'abc'} -function stringx.rpartition(s,ch) - assert_string(1,s) - assert_nonempty_string(2,ch) - local a,b,c = _partition(s,ch,stringx.rfind) - if a == s then -- no match found - return c,b,a - end - return a,b,c -end - ---- return the 'character' at the index. --- @string s the string --- @int idx an index (can be negative) --- @return a substring of length 1 if successful, empty string otherwise. -function stringx.at(s,idx) - assert_string(1,s) - assert_arg(2,idx,'number') - return sub(s,idx,idx) -end - - ---- Text handling --- @section text - - ---- indent a multiline string. --- @tparam string s the (multiline) string --- @tparam integer n the size of the indent --- @tparam[opt=' '] string ch the character to use when indenting --- @return indented string -function stringx.indent (s,n,ch) - assert_arg(1,s,'string') - assert_arg(2,n,'number') - local lines = usplit(s ,'\n') - local prefix = string.rep(ch or ' ',n) - for i, line in ipairs(lines) do - lines[i] = prefix..line - end - return concat(lines,'\n')..'\n' -end - - ---- dedent a multiline string by removing any initial indent. --- useful when working with [[..]] strings. --- Empty lines are ignored. --- @tparam string s the (multiline) string --- @return a string with initial indent zero. --- @usage --- local s = dedent [[ --- One --- --- Two --- --- Three --- ]] --- assert(s == [[ --- One --- --- Two --- --- Three --- ]]) -function stringx.dedent (s) - assert_arg(1,s,'string') - local lst = usplit(s,'\n') - if #lst>0 then - local ind_size = math.huge - for i, line in ipairs(lst) do - local i1, i2 = lst[i]:find('^%s*[^%s]') - if i1 and i2 < ind_size then - ind_size = i2 - end - end - for i, line in ipairs(lst) do - lst[i] = lst[i]:sub(ind_size, -1) - end - end - return concat(lst,'\n')..'\n' -end - - - -do - local buildline = function(words, size, breaklong) - -- if overflow is set, a word longer than size, will overflow the size - -- otherwise it will be chopped in line-length pieces - local line = {} - if #words[1] > size then - -- word longer than line - if not breaklong then - line[1] = words[1] - remove(words, 1) - else - line[1] = words[1]:sub(1, size) - words[1] = words[1]:sub(size + 1, -1) - end - else - local len = 0 - while words[1] and (len + #words[1] <= size) or - (len == 0 and #words[1] == size) do - if words[1] ~= "" then - line[#line+1] = words[1] - len = len + #words[1] + 1 - end - remove(words, 1) - end - end - return stringx.strip(concat(line, " ")), words - end - - --- format a paragraph into lines so that they fit into a line width. - -- It will not break long words by default, so lines can be over the length - -- to that extent. - -- @tparam string s the string to format - -- @tparam[opt=70] integer width the margin width - -- @tparam[opt=false] boolean breaklong if truthy, words longer than the width given will be forced split. - -- @return a list of lines (List object), use `fill` to return a string instead of a `List`. - -- @see pl.List - -- @see fill - stringx.wrap = function(s, width, breaklong) - s = s:gsub('\n',' ') -- remove line breaks - s = stringx.strip(s) -- remove leading/trailing whitespace - if s == "" then - return { "" } - end - width = width or 70 - local out = {} - local words = usplit(s, "%s") - while words[1] do - out[#out+1], words = buildline(words, width, breaklong) - end - return makelist(out) - end -end - ---- format a paragraph so that it fits into a line width. --- @tparam string s the string to format --- @tparam[opt=70] integer width the margin width --- @tparam[opt=false] boolean breaklong if truthy, words longer than the width given will be forced split. --- @return a string, use `wrap` to return a list of lines instead of a string. --- @see wrap -function stringx.fill (s,width,breaklong) - return concat(stringx.wrap(s,width,breaklong),'\n') .. '\n' -end - ---- Template --- @section Template - - -local function _substitute(s,tbl,safe) - local subst - if is_callable(tbl) then - subst = tbl - else - function subst(f) - local s = tbl[f] - if not s then - if safe then - return f - else - error("not present in table "..f) - end - else - return s - end - end - end - local res = gsub(s,'%${([%w_]+)}',subst) - return (gsub(res,'%$([%w_]+)',subst)) -end - - - -local Template = {} -stringx.Template = Template -Template.__index = Template -setmetatable(Template, { - __call = function(obj,tmpl) - return Template.new(tmpl) - end -}) - ---- Creates a new Template class. --- This is a shortcut to `Template.new(tmpl)`. --- @tparam string tmpl the template string --- @function Template --- @treturn Template -function Template.new(tmpl) - assert_arg(1,tmpl,'string') - local res = {} - res.tmpl = tmpl - setmetatable(res,Template) - return res -end - ---- substitute values into a template, throwing an error. --- This will throw an error if no name is found. --- @tparam table tbl a table of name-value pairs. --- @return string with place holders substituted -function Template:substitute(tbl) - assert_arg(1,tbl,'table') - return _substitute(self.tmpl,tbl,false) -end - ---- substitute values into a template. --- This version just passes unknown names through. --- @tparam table tbl a table of name-value pairs. --- @return string with place holders substituted -function Template:safe_substitute(tbl) - assert_arg(1,tbl,'table') - return _substitute(self.tmpl,tbl,true) -end - ---- substitute values into a template, preserving indentation.
--- If the value is a multiline string _or_ a template, it will insert --- the lines at the correct indentation.
--- Furthermore, if a template, then that template will be substituted --- using the same table. --- @tparam table tbl a table of name-value pairs. --- @return string with place holders substituted -function Template:indent_substitute(tbl) - assert_arg(1,tbl,'table') - if not self.strings then - self.strings = usplit(self.tmpl,'\n') - end - - -- the idea is to substitute line by line, grabbing any spaces as - -- well as the $var. If the value to be substituted contains newlines, - -- then we split that into lines and adjust the indent before inserting. - local function subst(line) - return line:gsub('(%s*)%$([%w_]+)',function(sp,f) - local subtmpl - local s = tbl[f] - if not s then error("not present in table "..f) end - if getmetatable(s) == Template then - subtmpl = s - s = s.tmpl - else - s = tostring(s) - end - if s:find '\n' then - local lines = usplit(s, '\n') - for i, line in ipairs(lines) do - lines[i] = sp..line - end - s = concat(lines, '\n') .. '\n' - end - if subtmpl then - return _substitute(s, tbl) - else - return s - end - end) - end - - local lines = {} - for i, line in ipairs(self.strings) do - lines[i] = subst(line) - end - return concat(lines,'\n')..'\n' -end - - - ---- Miscelaneous --- @section misc - ---- return an iterator over all lines in a string --- @string s the string --- @return an iterator --- @usage --- local line_no = 1 --- for line in stringx.lines(some_text) do --- print(line_no, line) --- line_no = line_no + 1 --- end -function stringx.lines(s) - assert_string(1,s) - if not s:find '\n$' then s = s..'\n' end - return s:gmatch('([^\n]*)\n') -end - ---- inital word letters uppercase ('title case'). --- Here 'words' mean chunks of non-space characters. --- @string s the string --- @return a string with each word's first letter uppercase --- @usage stringx.title("hello world") == "Hello World") -function stringx.title(s) - assert_string(1,s) - return (s:gsub('(%S)(%S*)',function(f,r) - return f:upper()..r:lower() - end)) -end - -stringx.capitalize = stringx.title - -do - local ellipsis = '...' - local n_ellipsis = #ellipsis - - --- Return a shortened version of a string. - -- Fits string within w characters. Removed characters are marked with ellipsis. - -- @string s the string - -- @int w the maxinum size allowed - -- @bool tail true if we want to show the end of the string (head otherwise) - -- @usage ('1234567890'):shorten(8) == '12345...' - -- @usage ('1234567890'):shorten(8, true) == '...67890' - -- @usage ('1234567890'):shorten(20) == '1234567890' - function stringx.shorten(s,w,tail) - assert_string(1,s) - if #s > w then - if w < n_ellipsis then return ellipsis:sub(1,w) end - if tail then - local i = #s - w + 1 + n_ellipsis - return ellipsis .. s:sub(i) - else - return s:sub(1,w-n_ellipsis) .. ellipsis - end - end - return s - end -end - - -do - -- Utility function that finds any patterns that match a long string's an open or close. - -- Note that having this function use the least number of equal signs that is possible is a harder algorithm to come up with. - -- Right now, it simply returns the greatest number of them found. - -- @param s The string - -- @return 'nil' if not found. If found, the maximum number of equal signs found within all matches. - local function has_lquote(s) - local lstring_pat = '([%[%]])(=*)%1' - local equals, new_equals, _ - local finish = 1 - repeat - _, finish, _, new_equals = s:find(lstring_pat, finish) - if new_equals then - equals = max(equals or 0, #new_equals) - end - until not new_equals - - return equals - end - - --- Quote the given string and preserve any control or escape characters, such that reloading the string in Lua returns the same result. - -- @param s The string to be quoted. - -- @return The quoted string. - function stringx.quote_string(s) - assert_string(1,s) - -- Find out if there are any embedded long-quote sequences that may cause issues. - -- This is important when strings are embedded within strings, like when serializing. - -- Append a closing bracket to catch unfinished long-quote sequences at the end of the string. - local equal_signs = has_lquote(s .. "]") - - -- Note that strings containing "\r" can't be quoted using long brackets - -- as Lua lexer converts all newlines to "\n" within long strings. - if (s:find("\n") or equal_signs) and not s:find("\r") then - -- If there is an embedded sequence that matches a long quote, then - -- find the one with the maximum number of = signs and add one to that number. - equal_signs = ("="):rep((equal_signs or -1) + 1) - -- Long strings strip out leading newline. We want to retain that, when quoting. - if s:find("^\n") then s = "\n" .. s end - local lbracket, rbracket = - "[" .. equal_signs .. "[", - "]" .. equal_signs .. "]" - s = lbracket .. s .. rbracket - else - -- Escape funny stuff. Lua 5.1 does not handle "\r" correctly. - s = ("%q"):format(s):gsub("\r", "\\r") - end - return s - end -end - - ---- Python-style formatting operator. --- Calling `text.format_operator()` overloads the % operator for strings to give --- Python/Ruby style formated output. --- This is extended to also do template-like substitution for map-like data. --- --- Note this goes further than the original, and will allow these cases: --- --- 1. a single value --- 2. a list of values --- 3. a map of var=value pairs --- 4. a function, as in gsub --- --- For the second two cases, it uses $-variable substituion. --- --- When called, this function will monkey-patch the global `string` metatable by --- adding a `__mod` method. --- --- See the lua-users wiki --- --- @usage --- require 'pl.text'.format_operator() --- local out1 = '%s = %5.3f' % {'PI',math.pi} --> 'PI = 3.142' --- local out2 = '$name = $value' % {name='dog',value='Pluto'} --> 'dog = Pluto' -function stringx.format_operator() - - local format = string.format - - -- a more forgiving version of string.format, which applies - -- tostring() to any value with a %s format. - local function formatx (fmt,...) - local args = pack(...) - local i = 1 - for p in fmt:gmatch('%%.') do - if p == '%s' and type(args[i]) ~= 'string' then - args[i] = tostring(args[i]) - end - i = i + 1 - end - return format(fmt,unpack(args)) - end - - local function basic_subst(s,t) - return (s:gsub('%$([%w_]+)',t)) - end - - getmetatable("").__mod = function(a, b) - if b == nil then - return a - elseif type(b) == "table" and getmetatable(b) == nil then - if #b == 0 then -- assume a map-like table - return _substitute(a,b,true) - else - return formatx(a,unpack(b)) - end - elseif type(b) == 'function' then - return basic_subst(a,b) - else - return formatx(a,b) - end - end -end - ---- import the stringx functions into the global string (meta)table -function stringx.import() - utils.import(stringx,string) -end - -return stringx diff --git a/game/scripts/vscripts/pl/tablex.lua b/game/scripts/vscripts/pl/tablex.lua deleted file mode 100644 index 3606912..0000000 --- a/game/scripts/vscripts/pl/tablex.lua +++ /dev/null @@ -1,999 +0,0 @@ ---- Extended operations on Lua tables. --- --- See @{02-arrays.md.Useful_Operations_on_Tables|the Guide} --- --- Dependencies: `pl.utils`, `pl.types` --- @module pl.tablex -local utils = require ('pl.utils') -local types = require ('pl.types') -local getmetatable,setmetatable,require = getmetatable,setmetatable,require -local tsort,append,remove = table.sort,table.insert,table.remove -local min = math.min -local pairs,type,unpack,select,tostring = pairs,type,utils.unpack,select,tostring -local function_arg = utils.function_arg -local assert_arg = utils.assert_arg - -local tablex = {} - --- generally, functions that make copies of tables try to preserve the metatable. --- However, when the source has no obvious type, then we attach appropriate metatables --- like List, Map, etc to the result. -local function setmeta (res,tbl,pl_class) - local mt = getmetatable(tbl) or pl_class and require('pl.' .. pl_class) - return mt and setmetatable(res, mt) or res -end - -local function makelist(l) - return setmetatable(l, require('pl.List')) -end - -local function makemap(m) - return setmetatable(m, require('pl.Map')) -end - -local function complain (idx,msg) - error(('argument %d is not %s'):format(idx,msg),3) -end - -local function assert_arg_indexable (idx,val) - if not types.is_indexable(val) then - complain(idx,"indexable") - end -end - -local function assert_arg_iterable (idx,val) - if not types.is_iterable(val) then - complain(idx,"iterable") - end -end - -local function assert_arg_writeable (idx,val) - if not types.is_writeable(val) then - complain(idx,"writeable") - end -end - ---- copy a table into another, in-place. --- @within Copying --- @tab t1 destination table --- @tab t2 source (actually any iterable object) --- @return first table -function tablex.update (t1,t2) - assert_arg_writeable(1,t1) - assert_arg_iterable(2,t2) - for k,v in pairs(t2) do - t1[k] = v - end - return t1 -end - ---- total number of elements in this table. --- Note that this is distinct from `#t`, which is the number --- of values in the array part; this value will always --- be greater or equal. The difference gives the size of --- the hash part, for practical purposes. Works for any --- object with a __pairs metamethod. --- @tab t a table --- @return the size -function tablex.size (t) - assert_arg_iterable(1,t) - local i = 0 - for k in pairs(t) do i = i + 1 end - return i -end - ---- make a shallow copy of a table --- @within Copying --- @tab t an iterable source --- @return new table -function tablex.copy (t) - assert_arg_iterable(1,t) - local res = {} - for k,v in pairs(t) do - res[k] = v - end - return res -end - -local function cycle_aware_copy(t, cache) - if type(t) ~= 'table' then return t end - if cache[t] then return cache[t] end - assert_arg_iterable(1,t) - local res = {} - cache[t] = res - local mt = getmetatable(t) - for k,v in pairs(t) do - k = cycle_aware_copy(k, cache) - v = cycle_aware_copy(v, cache) - res[k] = v - end - setmetatable(res,mt) - return res -end - ---- make a deep copy of a table, recursively copying all the keys and fields. --- This supports cycles in tables; cycles will be reproduced in the copy. --- This will also set the copied table's metatable to that of the original. --- @within Copying --- @tab t A table --- @return new table -function tablex.deepcopy(t) - return cycle_aware_copy(t,{}) -end - -local abs = math.abs - -local function cycle_aware_compare(t1,t2,ignore_mt,eps,cache) - if cache[t1] and cache[t1][t2] then return true end - local ty1 = type(t1) - local ty2 = type(t2) - if ty1 ~= ty2 then return false end - -- non-table types can be directly compared - if ty1 ~= 'table' then - if ty1 == 'number' and eps then return abs(t1-t2) < eps end - return t1 == t2 - end - -- as well as tables which have the metamethod __eq - local mt = getmetatable(t1) - if not ignore_mt and mt and mt.__eq then return t1 == t2 end - for k1 in pairs(t1) do - if t2[k1]==nil then return false end - end - for k2 in pairs(t2) do - if t1[k2]==nil then return false end - end - cache[t1] = cache[t1] or {} - cache[t1][t2] = true - for k1,v1 in pairs(t1) do - local v2 = t2[k1] - if not cycle_aware_compare(v1,v2,ignore_mt,eps,cache) then return false end - end - return true -end - ---- compare two values. --- if they are tables, then compare their keys and fields recursively. --- @within Comparing --- @param t1 A value --- @param t2 A value --- @bool[opt] ignore_mt if true, ignore __eq metamethod (default false) --- @number[opt] eps if defined, then used for any number comparisons --- @return true or false -function tablex.deepcompare(t1,t2,ignore_mt,eps) - return cycle_aware_compare(t1,t2,ignore_mt,eps,{}) -end - ---- compare two arrays using a predicate. --- @within Comparing --- @array t1 an array --- @array t2 an array --- @func cmp A comparison function; `bool = cmp(t1_value, t2_value)` --- @return true or false --- @usage --- assert(tablex.compare({ 1, 2, 3 }, { 1, 2, 3 }, "==")) --- --- assert(tablex.compare( --- {1,2,3, hello = "world"}, -- fields are not compared! --- {1,2,3}, function(v1, v2) return v1 == v2 end) -function tablex.compare (t1,t2,cmp) - assert_arg_indexable(1,t1) - assert_arg_indexable(2,t2) - if #t1 ~= #t2 then return false end - cmp = function_arg(3,cmp) - for k = 1,#t1 do - if not cmp(t1[k],t2[k]) then return false end - end - return true -end - ---- compare two list-like tables using an optional predicate, without regard for element order. --- @within Comparing --- @array t1 a list-like table --- @array t2 a list-like table --- @param cmp A comparison function (may be nil) -function tablex.compare_no_order (t1,t2,cmp) - assert_arg_indexable(1,t1) - assert_arg_indexable(2,t2) - if cmp then cmp = function_arg(3,cmp) end - if #t1 ~= #t2 then return false end - local visited = {} - for i = 1,#t1 do - local val = t1[i] - local gotcha - for j = 1,#t2 do - if not visited[j] then - local match - if cmp then match = cmp(val,t2[j]) else match = val == t2[j] end - if match then - gotcha = j - break - end - end - end - if not gotcha then return false end - visited[gotcha] = true - end - return true -end - - ---- return the index of a value in a list. --- Like string.find, there is an optional index to start searching, --- which can be negative. --- @within Finding --- @array t A list-like table --- @param val A value --- @int idx index to start; -1 means last element,etc (default 1) --- @return index of value or nil if not found --- @usage find({10,20,30},20) == 2 --- @usage find({'a','b','a','c'},'a',2) == 3 -function tablex.find(t,val,idx) - assert_arg_indexable(1,t) - idx = idx or 1 - if idx < 0 then idx = #t + idx + 1 end - for i = idx,#t do - if t[i] == val then return i end - end - return nil -end - ---- return the index of a value in a list, searching from the end. --- Like string.find, there is an optional index to start searching, --- which can be negative. --- @within Finding --- @array t A list-like table --- @param val A value --- @param idx index to start; -1 means last element,etc (default `#t`) --- @return index of value or nil if not found --- @usage rfind({10,10,10},10) == 3 -function tablex.rfind(t,val,idx) - assert_arg_indexable(1,t) - idx = idx or #t - if idx < 0 then idx = #t + idx + 1 end - for i = idx,1,-1 do - if t[i] == val then return i end - end - return nil -end - - ---- return the index (or key) of a value in a table using a comparison function. --- --- *NOTE*: the 2nd return value of this function, the value returned --- by the comparison function, has a limitation that it cannot be `false`. --- Because if it is, then it indicates the comparison failed, and the --- function will continue the search. See examples. --- @within Finding --- @tab t A table --- @func cmp A comparison function --- @param arg an optional second argument to the function --- @return index of value, or nil if not found --- @return value returned by comparison function (cannot be `false`!) --- @usage --- -- using an operator --- local lst = { "Rudolph", true, false, 15 } --- local idx, cmp_result = tablex.rfind(lst, "==", "Rudolph") --- assert(idx == 1) --- assert(cmp_result == true) --- --- local idx, cmp_result = tablex.rfind(lst, "==", false) --- assert(idx == 3) --- assert(cmp_result == true) -- looking up 'false' works! --- --- -- using a function returning the value looked up --- local cmp = function(v1, v2) return v1 == v2 and v2 end --- local idx, cmp_result = tablex.rfind(lst, cmp, "Rudolph") --- assert(idx == 1) --- assert(cmp_result == "Rudolph") -- the value is returned --- --- -- NOTE: this fails, since 'false' cannot be returned! --- local idx, cmp_result = tablex.rfind(lst, cmp, false) --- assert(idx == nil) -- looking up 'false' failed! --- assert(cmp_result == nil) -function tablex.find_if(t,cmp,arg) - assert_arg_iterable(1,t) - cmp = function_arg(2,cmp) - for k,v in pairs(t) do - local c = cmp(v,arg) - if c then return k,c end - end - return nil -end - ---- return a list of all values in a table indexed by another list. --- @tab tbl a table --- @array idx an index table (a list of keys) --- @return a list-like table --- @usage index_by({10,20,30,40},{2,4}) == {20,40} --- @usage index_by({one=1,two=2,three=3},{'one','three'}) == {1,3} -function tablex.index_by(tbl,idx) - assert_arg_indexable(1,tbl) - assert_arg_indexable(2,idx) - local res = {} - for i = 1,#idx do - res[i] = tbl[idx[i]] - end - return setmeta(res,tbl,'List') -end - ---- apply a function to all values of a table. --- This returns a table of the results. --- Any extra arguments are passed to the function. --- @within MappingAndFiltering --- @func fun A function that takes at least one argument --- @tab t A table --- @param ... optional arguments --- @usage map(function(v) return v*v end, {10,20,30,fred=2}) is {100,400,900,fred=4} -function tablex.map(fun,t,...) - assert_arg_iterable(1,t) - fun = function_arg(1,fun) - local res = {} - for k,v in pairs(t) do - res[k] = fun(v,...) - end - return setmeta(res,t) -end - ---- apply a function to all values of a list. --- This returns a table of the results. --- Any extra arguments are passed to the function. --- @within MappingAndFiltering --- @func fun A function that takes at least one argument --- @array t a table (applies to array part) --- @param ... optional arguments --- @return a list-like table --- @usage imap(function(v) return v*v end, {10,20,30,fred=2}) is {100,400,900} -function tablex.imap(fun,t,...) - assert_arg_indexable(1,t) - fun = function_arg(1,fun) - local res = {} - for i = 1,#t do - res[i] = fun(t[i],...) or false - end - return setmeta(res,t,'List') -end - ---- apply a named method to values from a table. --- @within MappingAndFiltering --- @string name the method name --- @array t a list-like table --- @param ... any extra arguments to the method --- @return a `List` with the results of the method (1st result only) --- @usage --- local Car = {} --- Car.__index = Car --- function Car.new(car) --- return setmetatable(car or {}, Car) --- end --- Car.speed = 0 --- function Car:faster(increase) --- self.speed = self.speed + increase --- return self.speed --- end --- --- local ferrari = Car.new{ name = "Ferrari" } --- local lamborghini = Car.new{ name = "Lamborghini", speed = 50 } --- local cars = { ferrari, lamborghini } --- --- assert(ferrari.speed == 0) --- assert(lamborghini.speed == 50) --- tablex.map_named_method("faster", cars, 10) --- assert(ferrari.speed == 10) --- assert(lamborghini.speed == 60) -function tablex.map_named_method (name,t,...) - utils.assert_string(1,name) - assert_arg_indexable(2,t) - local res = {} - for i = 1,#t do - local val = t[i] - local fun = val[name] - res[i] = fun(val,...) - end - return setmeta(res,t,'List') -end - ---- apply a function to all values of a table, in-place. --- Any extra arguments are passed to the function. --- @func fun A function that takes at least one argument --- @tab t a table --- @param ... extra arguments passed to `fun` --- @see tablex.foreach -function tablex.transform (fun,t,...) - assert_arg_iterable(1,t) - fun = function_arg(1,fun) - for k,v in pairs(t) do - t[k] = fun(v,...) - end -end - ---- generate a table of all numbers in a range. --- This is consistent with a numerical for loop. --- @int start number --- @int finish number --- @int[opt=1] step make this negative for start < finish -function tablex.range (start,finish,step) - local res - step = step or 1 - if start == finish then - res = {start} - elseif (start > finish and step > 0) or (finish > start and step < 0) then - res = {} - else - local k = 1 - res = {} - for i=start,finish,step do res[k]=i; k=k+1 end - end - return makelist(res) -end - ---- apply a function to values from two tables. --- @within MappingAndFiltering --- @func fun a function of at least two arguments --- @tab t1 a table --- @tab t2 a table --- @param ... extra arguments --- @return a table --- @usage map2('+',{1,2,3,m=4},{10,20,30,m=40}) is {11,22,23,m=44} -function tablex.map2 (fun,t1,t2,...) - assert_arg_iterable(1,t1) - assert_arg_iterable(2,t2) - fun = function_arg(1,fun) - local res = {} - for k,v in pairs(t1) do - res[k] = fun(v,t2[k],...) - end - return setmeta(res,t1,'List') -end - ---- apply a function to values from two arrays. --- The result will be the length of the shortest array. --- @within MappingAndFiltering --- @func fun a function of at least two arguments --- @array t1 a list-like table --- @array t2 a list-like table --- @param ... extra arguments --- @usage imap2('+',{1,2,3,m=4},{10,20,30,m=40}) is {11,22,23} -function tablex.imap2 (fun,t1,t2,...) - assert_arg_indexable(2,t1) - assert_arg_indexable(3,t2) - fun = function_arg(1,fun) - local res,n = {},math.min(#t1,#t2) - for i = 1,n do - res[i] = fun(t1[i],t2[i],...) - end - return res -end - ---- 'reduce' a list using a binary function. --- @func fun a function of two arguments --- @array t a list-like table --- @array memo optional initial memo value. Defaults to first value in table. --- @return the result of the function --- @usage reduce('+',{1,2,3,4}) == 10 -function tablex.reduce (fun,t,memo) - assert_arg_indexable(2,t) - fun = function_arg(1,fun) - local n = #t - if n == 0 then - return memo - end - local res = memo and fun(memo, t[1]) or t[1] - for i = 2,n do - res = fun(res,t[i]) - end - return res -end - ---- apply a function to all elements of a table. --- The arguments to the function will be the value, --- the key and _finally_ any extra arguments passed to this function. --- Note that the Lua 5.0 function table.foreach passed the _key_ first. --- @within Iterating --- @tab t a table --- @func fun a function on the elements; `function(value, key, ...)` --- @param ... extra arguments passed to `fun` --- @see tablex.transform -function tablex.foreach(t,fun,...) - assert_arg_iterable(1,t) - fun = function_arg(2,fun) - for k,v in pairs(t) do - fun(v,k,...) - end -end - ---- apply a function to all elements of a list-like table in order. --- The arguments to the function will be the value, --- the index and _finally_ any extra arguments passed to this function --- @within Iterating --- @array t a table --- @func fun a function with at least one argument --- @param ... optional arguments -function tablex.foreachi(t,fun,...) - assert_arg_indexable(1,t) - fun = function_arg(2,fun) - for i = 1,#t do - fun(t[i],i,...) - end -end - ---- Apply a function to a number of tables. --- A more general version of map --- The result is a table containing the result of applying that function to the --- ith value of each table. Length of output list is the minimum length of all the lists --- @within MappingAndFiltering --- @func fun a function of n arguments --- @tab ... n tables --- @usage mapn(function(x,y,z) return x+y+z end, {1,2,3},{10,20,30},{100,200,300}) is {111,222,333} --- @usage mapn(math.max, {1,20,300},{10,2,3},{100,200,100}) is {100,200,300} --- @param fun A function that takes as many arguments as there are tables -function tablex.mapn(fun,...) - fun = function_arg(1,fun) - local res = {} - local lists = {...} - local minn = 1e40 - for i = 1,#lists do - minn = min(minn,#(lists[i])) - end - for i = 1,minn do - local args,k = {},1 - for j = 1,#lists do - args[k] = lists[j][i] - k = k + 1 - end - res[#res+1] = fun(unpack(args)) - end - return res -end - ---- call the function with the key and value pairs from a table. --- The function can return a value and a key (note the order!). If both --- are not nil, then this pair is inserted into the result: if the key already exists, we convert the value for that --- key into a table and append into it. If only value is not nil, then it is appended to the result. --- @within MappingAndFiltering --- @func fun A function which will be passed each key and value as arguments, plus any extra arguments to pairmap. --- @tab t A table --- @param ... optional arguments --- @usage pairmap(function(k,v) return v end,{fred=10,bonzo=20}) is {10,20} _or_ {20,10} --- @usage pairmap(function(k,v) return {k,v},k end,{one=1,two=2}) is {one={'one',1},two={'two',2}} -function tablex.pairmap(fun,t,...) - assert_arg_iterable(1,t) - fun = function_arg(1,fun) - local res = {} - for k,v in pairs(t) do - local rv,rk = fun(k,v,...) - if rk then - if res[rk] then - if type(res[rk]) == 'table' then - table.insert(res[rk],rv) - else - res[rk] = {res[rk], rv} - end - else - res[rk] = rv - end - else - res[#res+1] = rv - end - end - return res -end - -local function keys_op(i,v) return i end - ---- return all the keys of a table in arbitrary order. --- @within Extraction --- @tab t A list-like table where the values are the keys of the input table -function tablex.keys(t) - assert_arg_iterable(1,t) - return makelist(tablex.pairmap(keys_op,t)) -end - -local function values_op(i,v) return v end - ---- return all the values of the table in arbitrary order --- @within Extraction --- @tab t A list-like table where the values are the values of the input table -function tablex.values(t) - assert_arg_iterable(1,t) - return makelist(tablex.pairmap(values_op,t)) -end - -local function index_map_op (i,v) return i,v end - ---- create an index map from a list-like table. The original values become keys, --- and the associated values are the indices into the original list. --- @array t a list-like table --- @return a map-like table -function tablex.index_map (t) - assert_arg_indexable(1,t) - return makemap(tablex.pairmap(index_map_op,t)) -end - -local function set_op(i,v) return true,v end - ---- create a set from a list-like table. A set is a table where the original values --- become keys, and the associated values are all true. --- @array t a list-like table --- @return a set (a map-like table) -function tablex.makeset (t) - assert_arg_indexable(1,t) - return setmetatable(tablex.pairmap(set_op,t),require('pl.Set')) -end - ---- combine two tables, either as union or intersection. Corresponds to --- set operations for sets () but more general. Not particularly --- useful for list-like tables. --- @within Merging --- @tab t1 a table --- @tab t2 a table --- @bool dup true for a union, false for an intersection. --- @usage merge({alice=23,fred=34},{bob=25,fred=34}) is {fred=34} --- @usage merge({alice=23,fred=34},{bob=25,fred=34},true) is {bob=25,fred=34,alice=23} --- @see tablex.index_map -function tablex.merge (t1,t2,dup) - assert_arg_iterable(1,t1) - assert_arg_iterable(2,t2) - local res = {} - for k,v in pairs(t1) do - if dup or t2[k] then res[k] = v end - end - if dup then - for k,v in pairs(t2) do - res[k] = v - end - end - return setmeta(res,t1,'Map') -end - ---- the union of two map-like tables. --- If there are duplicate keys, the second table wins. --- @tab t1 a table --- @tab t2 a table --- @treturn tab --- @see tablex.merge -function tablex.union(t1, t2) - return tablex.merge(t1, t2, true) -end - ---- the intersection of two map-like tables. --- @tab t1 a table --- @tab t2 a table --- @treturn tab --- @see tablex.merge -function tablex.intersection(t1, t2) - return tablex.merge(t1, t2, false) -end - ---- a new table which is the difference of two tables. --- With sets (where the values are all true) this is set difference and --- symmetric difference depending on the third parameter. --- @within Merging --- @tab s1 a map-like table or set --- @tab s2 a map-like table or set --- @bool symm symmetric difference (default false) --- @return a map-like table or set -function tablex.difference (s1,s2,symm) - assert_arg_iterable(1,s1) - assert_arg_iterable(2,s2) - local res = {} - for k,v in pairs(s1) do - if s2[k] == nil then res[k] = v end - end - if symm then - for k,v in pairs(s2) do - if s1[k] == nil then res[k] = v end - end - end - return setmeta(res,s1,'Map') -end - ---- A table where the key/values are the values and value counts of the table. --- @array t a list-like table --- @func cmp a function that defines equality (otherwise uses ==) --- @return a map-like table --- @see seq.count_map -function tablex.count_map (t,cmp) - assert_arg_indexable(1,t) - local res,mask = {},{} - cmp = function_arg(2,cmp or '==') - local n = #t - for i = 1,#t do - local v = t[i] - if not mask[v] then - mask[v] = true - -- check this value against all other values - res[v] = 1 -- there's at least one instance - for j = i+1,n do - local w = t[j] - local ok = cmp(v,w) - if ok then - res[v] = res[v] + 1 - mask[w] = true - end - end - end - end - return makemap(res) -end - ---- filter an array's values using a predicate function --- @within MappingAndFiltering --- @array t a list-like table --- @func pred a boolean function --- @param arg optional argument to be passed as second argument of the predicate -function tablex.filter (t,pred,arg) - assert_arg_indexable(1,t) - pred = function_arg(2,pred) - local res,k = {},1 - for i = 1,#t do - local v = t[i] - if pred(v,arg) then - res[k] = v - k = k + 1 - end - end - return setmeta(res,t,'List') -end - ---- return a table where each element is a table of the ith values of an arbitrary --- number of tables. It is equivalent to a matrix transpose. --- @within Merging --- @usage zip({10,20,30},{100,200,300}) is {{10,100},{20,200},{30,300}} --- @array ... arrays to be zipped -function tablex.zip(...) - return tablex.mapn(function(...) return {...} end,...) -end - -local _copy -function _copy (dest,src,idest,isrc,nsrc,clean_tail) - idest = idest or 1 - isrc = isrc or 1 - local iend - if not nsrc then - nsrc = #src - iend = #src - else - iend = isrc + min(nsrc-1,#src-isrc) - end - if dest == src then -- special case - if idest > isrc and iend >= idest then -- overlapping ranges - src = tablex.sub(src,isrc,nsrc) - isrc = 1; iend = #src - end - end - for i = isrc,iend do - dest[idest] = src[i] - idest = idest + 1 - end - if clean_tail then - tablex.clear(dest,idest) - end - return dest -end - ---- copy an array into another one, clearing `dest` after `idest+nsrc`, if necessary. --- @within Copying --- @array dest a list-like table --- @array src a list-like table --- @int[opt=1] idest where to start copying values into destination --- @int[opt=1] isrc where to start copying values from source --- @int[opt=#src] nsrc number of elements to copy from source -function tablex.icopy (dest,src,idest,isrc,nsrc) - assert_arg_indexable(1,dest) - assert_arg_indexable(2,src) - return _copy(dest,src,idest,isrc,nsrc,true) -end - ---- copy an array into another one. --- @within Copying --- @array dest a list-like table --- @array src a list-like table --- @int[opt=1] idest where to start copying values into destination --- @int[opt=1] isrc where to start copying values from source --- @int[opt=#src] nsrc number of elements to copy from source -function tablex.move (dest,src,idest,isrc,nsrc) - assert_arg_indexable(1,dest) - assert_arg_indexable(2,src) - return _copy(dest,src,idest,isrc,nsrc,false) -end - -function tablex._normalize_slice(self,first,last) - local sz = #self - if not first then first=1 end - if first<0 then first=sz+first+1 end - -- make the range _inclusive_! - if not last then last=sz end - if last < 0 then last=sz+1+last end - return first,last -end - ---- Extract a range from a table, like 'string.sub'. --- If first or last are negative then they are relative to the end of the list --- eg. sub(t,-2) gives last 2 entries in a list, and --- sub(t,-4,-2) gives from -4th to -2nd --- @within Extraction --- @array t a list-like table --- @int first An index --- @int last An index --- @return a new List -function tablex.sub(t,first,last) - assert_arg_indexable(1,t) - first,last = tablex._normalize_slice(t,first,last) - local res={} - for i=first,last do append(res,t[i]) end - return setmeta(res,t,'List') -end - ---- set an array range to a value. If it's a function we use the result --- of applying it to the indices. --- @array t a list-like table --- @param val a value --- @int[opt=1] i1 start range --- @int[opt=#t] i2 end range -function tablex.set (t,val,i1,i2) - assert_arg_indexable(1,t) - i1,i2 = i1 or 1,i2 or #t - if types.is_callable(val) then - for i = i1,i2 do - t[i] = val(i) - end - else - for i = i1,i2 do - t[i] = val - end - end -end - ---- create a new array of specified size with initial value. --- @int n size --- @param val initial value (can be `nil`, but don't expect `#` to work!) --- @return the table -function tablex.new (n,val) - local res = {} - tablex.set(res,val,1,n) - return res -end - ---- clear out the contents of a table. --- @array t a list --- @param istart optional start position -function tablex.clear(t,istart) - istart = istart or 1 - for i = istart,#t do remove(t) end -end - ---- insert values into a table. --- similar to `table.insert` but inserts values from given table `values`, --- not the object itself, into table `t` at position `pos`. --- @within Copying --- @array t the list --- @int[opt] position (default is at end) --- @array values -function tablex.insertvalues(t, ...) - assert_arg(1,t,'table') - local pos, values - if select('#', ...) == 1 then - pos,values = #t+1, ... - else - pos,values = ... - end - if #values > 0 then - for i=#t,pos,-1 do - t[i+#values] = t[i] - end - local offset = 1 - pos - for i=pos,pos+#values-1 do - t[i] = values[i + offset] - end - end - return t -end - ---- remove a range of values from a table. --- End of range may be negative. --- @array t a list-like table --- @int i1 start index --- @int i2 end index --- @return the table -function tablex.removevalues (t,i1,i2) - assert_arg(1,t,'table') - i1,i2 = tablex._normalize_slice(t,i1,i2) - for i = i1,i2 do - remove(t,i1) - end - return t -end - -local _find -_find = function (t,value,tables) - for k,v in pairs(t) do - if v == value then return k end - end - for k,v in pairs(t) do - if not tables[v] and type(v) == 'table' then - tables[v] = true - local res = _find(v,value,tables) - if res then - res = tostring(res) - if type(k) ~= 'string' then - return '['..k..']'..res - else - return k..'.'..res - end - end - end - end -end - ---- find a value in a table by recursive search. --- @within Finding --- @tab t the table --- @param value the value --- @array[opt] exclude any tables to avoid searching --- @return a fieldspec, e.g. 'a.b' or 'math.sin' --- @usage search(_G,math.sin,{package.path}) == 'math.sin' -function tablex.search (t,value,exclude) - assert_arg_iterable(1,t) - local tables = {[t]=true} - if exclude then - for _,v in pairs(exclude) do tables[v] = true end - end - return _find(t,value,tables) -end - ---- return an iterator to a table sorted by its keys --- @within Iterating --- @tab t the table --- @func f an optional comparison function (f(x,y) is true if x < y) --- @usage for k,v in tablex.sort(t) do print(k,v) end --- @return an iterator to traverse elements sorted by the keys -function tablex.sort(t,f) - local keys = {} - for k in pairs(t) do keys[#keys + 1] = k end - tsort(keys,f) - local i = 0 - return function() - i = i + 1 - return keys[i], t[keys[i]] - end -end - ---- return an iterator to a table sorted by its values --- @within Iterating --- @tab t the table --- @func f an optional comparison function (f(x,y) is true if x < y) --- @usage for k,v in tablex.sortv(t) do print(k,v) end --- @return an iterator to traverse elements sorted by the values -function tablex.sortv(t,f) - f = function_arg(2, f or '<') - local keys = {} - for k in pairs(t) do keys[#keys + 1] = k end - tsort(keys,function(x, y) return f(t[x], t[y]) end) - local i = 0 - return function() - i = i + 1 - return keys[i], t[keys[i]] - end -end - ---- modifies a table to be read only. --- This only offers weak protection. Tables can still be modified with --- `table.insert` and `rawset`. --- --- *NOTE*: for Lua 5.1 length, pairs and ipairs will not work, since the --- equivalent metamethods are only available in Lua 5.2 and newer. --- @tab t the table --- @return the table read only (a proxy). -function tablex.readonly(t) - local mt = { - __index=t, - __newindex=function(t, k, v) error("Attempt to modify read-only table", 2) end, - __pairs=function() return pairs(t) end, - __ipairs=function() return ipairs(t) end, - __len=function() return #t end, - __metatable=false - } - return setmetatable({}, mt) -end - -return tablex diff --git a/game/scripts/vscripts/pl/template.lua b/game/scripts/vscripts/pl/template.lua deleted file mode 100644 index 9961a1b..0000000 --- a/game/scripts/vscripts/pl/template.lua +++ /dev/null @@ -1,202 +0,0 @@ ---- A template preprocessor. --- Originally by [Ricki Lake](http://lua-users.org/wiki/SlightlyLessSimpleLuaPreprocessor) --- --- There are two rules: --- --- * lines starting with # are Lua --- * otherwise, `$(expr)` is the result of evaluating `expr` --- --- Example: --- --- # for i = 1,3 do --- $(i) Hello, Word! --- # end --- ===> --- 1 Hello, Word! --- 2 Hello, Word! --- 3 Hello, Word! --- --- Other escape characters can be used, when the defaults conflict --- with the output language. --- --- > for _,n in pairs{'one','two','three'} do --- static int l_${n} (luaState *state); --- > end --- --- See @{03-strings.md.Another_Style_of_Template|the Guide}. --- --- Dependencies: `pl.utils` --- @module pl.template - -local utils = require 'pl.utils' - -local append,format,strsub,strfind,strgsub = table.insert,string.format,string.sub,string.find,string.gsub - -local APPENDER = "\n__R_size = __R_size + 1; __R_table[__R_size] = " - -local function parseDollarParen(pieces, chunk, exec_pat, newline) - local s = 1 - for term, executed, e in chunk:gmatch(exec_pat) do - executed = '('..strsub(executed,2,-2)..')' - append(pieces, APPENDER..format("%q", strsub(chunk,s, term - 1))) - append(pieces, APPENDER..format("__tostring(%s or '')", executed)) - s = e - end - local r - if newline then - r = format("%q", strgsub(strsub(chunk,s),"\n","")) - else - r = format("%q", strsub(chunk,s)) - end - if r ~= '""' then - append(pieces, APPENDER..r) - end -end - -local function parseHashLines(chunk,inline_escape,brackets,esc,newline) - local exec_pat = "()"..inline_escape.."(%b"..brackets..")()" - - local esc_pat = esc.."+([^\n]*\n?)" - local esc_pat1, esc_pat2 = "^"..esc_pat, "\n"..esc_pat - local pieces, s = {"return function()\nlocal __R_size, __R_table, __tostring = 0, {}, __tostring", n = 1}, 1 - while true do - local _, e, lua = strfind(chunk,esc_pat1, s) - if not e then - local ss - ss, e, lua = strfind(chunk,esc_pat2, s) - parseDollarParen(pieces, strsub(chunk,s, ss), exec_pat, newline) - if not e then break end - end - if strsub(lua, -1, -1) == "\n" then lua = strsub(lua, 1, -2) end - append(pieces, "\n"..lua) - s = e + 1 - end - append(pieces, "\nreturn __R_table\nend") - - -- let's check for a special case where there is nothing to template, but it's - -- just a single static string - local short = false - if (#pieces == 3) and (pieces[2]:find(APPENDER, 1, true) == 1) then - pieces = { "return " .. pieces[2]:sub(#APPENDER+1,-1) } - short = true - end - -- if short == true, the generated function will not return a table of strings, - -- but a single string - return table.concat(pieces), short -end - -local template = {} - ---- expand the template using the specified environment. --- This function will compile and render the template. For more performant --- recurring usage use the two step approach by using `compile` and `ct:render`. --- There are six special fields in the environment table `env` --- --- * `_parent`: continue looking up in this table (e.g. `_parent=_G`). --- * `_brackets`: bracket pair that wraps inline Lua expressions, default is '()'. --- * `_escape`: character marking Lua lines, default is '#' --- * `_inline_escape`: character marking inline Lua expression, default is '$'. --- * `_chunk_name`: chunk name for loaded templates, used if there --- is an error in Lua code. Default is 'TMP'. --- * `_debug`: if truthy, the generated code will be printed upon a render error --- --- @string str the template string --- @tab[opt] env the environment --- @return `rendered template + nil + source_code`, or `nil + error + source_code`. The last --- return value (`source_code`) is only returned if the debug option is used. -function template.substitute(str,env) - env = env or {} - local t, err = template.compile(str, { - chunk_name = rawget(env,"_chunk_name"), - escape = rawget(env,"_escape"), - inline_escape = rawget(env,"_inline_escape"), - inline_brackets = rawget(env,"_brackets"), - newline = nil, - debug = rawget(env,"_debug") - }) - if not t then return t, err end - - return t:render(env, rawget(env,"_parent"), rawget(env,"_debug")) -end - ---- executes the previously compiled template and renders it. --- @function ct:render --- @tab[opt] env the environment. --- @tab[opt] parent continue looking up in this table (e.g. `parent=_G`). --- @bool[opt] db if thruthy, it will print the code upon a render error --- (provided the template was compiled with the debug option). --- @return `rendered template + nil + source_code`, or `nil + error + source_code`. The last return value --- (`source_code`) is only returned if the template was compiled with the debug option. --- @usage --- local ct, err = template.compile(my_template) --- local rendered , err = ct:render(my_env, parent) -local render = function(self, env, parent, db) - env = env or {} - if parent then -- parent is a bit silly, but for backward compatibility retained - setmetatable(env, {__index = parent}) - end - setmetatable(self.env, {__index = env}) - - local res, out = xpcall(self.fn, debug.traceback) - if not res then - if self.code and db then print(self.code) end - return nil, out, self.code - end - return table.concat(out), nil, self.code -end - ---- compiles the template. --- Returns an object that can repeatedly be rendered without parsing/compiling --- the template again. --- The options passed in the `opts` table support the following options: --- --- * `chunk_name`: chunk name for loaded templates, used if there --- is an error in Lua code. Default is 'TMP'. --- * `escape`: character marking Lua lines, default is '#' --- * `inline_escape`: character marking inline Lua expression, default is '$'. --- * `inline_brackets`: bracket pair that wraps inline Lua expressions, default is '()'. --- * `newline`: string to replace newline characters, default is `nil` (not replacing newlines). --- * `debug`: if truthy, the generated source code will be retained within the compiled template object, default is `nil`. --- --- @string str the template string --- @tab[opt] opts the compilation options to use --- @return template object, or `nil + error + source_code` --- @usage --- local ct, err = template.compile(my_template) --- local rendered , err = ct:render(my_env, parent) -function template.compile(str, opts) - opts = opts or {} - local chunk_name = opts.chunk_name or 'TMP' - local escape = opts.escape or '#' - local inline_escape = opts.inline_escape or '$' - local inline_brackets = opts.inline_brackets or '()' - - local code, short = parseHashLines(str,inline_escape,inline_brackets,escape,opts.newline) - local env = { __tostring = tostring } - local fn, err = utils.load(code, chunk_name,'t',env) - if not fn then return nil, err, code end - - if short then - -- the template returns a single constant string, let's optimize for that - local constant_string = fn() - return { - fn = fn(), - env = env, - render = function(self) -- additional params can be ignored - -- skip the metatable magic and error handling in the render - -- function above for this special case - return constant_string, nil, self.code - end, - code = opts.debug and code or nil, - } - end - - return { - fn = fn(), - env = env, - render = render, - code = opts.debug and code or nil, - } -end - -return template diff --git a/game/scripts/vscripts/pl/test.lua b/game/scripts/vscripts/pl/test.lua deleted file mode 100644 index 694bbc5..0000000 --- a/game/scripts/vscripts/pl/test.lua +++ /dev/null @@ -1,164 +0,0 @@ ---- Useful test utilities. --- --- test.asserteq({1,2},{1,2}) -- can compare tables --- test.asserteq(1.2,1.19,0.02) -- compare FP numbers within precision --- T = test.tuple -- used for comparing multiple results --- test.asserteq(T(string.find(" me","me")),T(2,3)) --- --- Dependencies: `pl.utils`, `pl.tablex`, `pl.pretty`, `pl.path`, `debug` --- @module pl.test - -local tablex = require 'pl.tablex' -local utils = require 'pl.utils' -local pretty = require 'pl.pretty' -local path = require 'pl.path' -local type,unpack,pack = type,utils.unpack,utils.pack -local clock = os.clock -local debug = require 'debug' -local io = io - -local function dump(x) - if type(x) == 'table' and not (getmetatable(x) and getmetatable(x).__tostring) then - return pretty.write(x,' ',true) - elseif type(x) == 'string' then - return '"'..x..'"' - else - return tostring(x) - end -end - -local test = {} - ----- error handling for test results. --- By default, this writes to stderr and exits the program. --- Re-define this function to raise an error and/or redirect output -function test.error_handler(file,line,got_text, needed_text,msg) - local err = io.stderr - err:write(path.basename(file)..':'..line..': assertion failed\n') - err:write("got:\t",got_text,'\n') - err:write("needed:\t",needed_text,'\n') - utils.quit(1,msg or "these values were not equal") -end - -local function complain (x,y,msg,where) - local i = debug.getinfo(3 + (where or 0)) - test.error_handler(i.short_src,i.currentline,dump(x),dump(y),msg) -end - ---- general test complain message. --- Useful for composing new test functions (see tests/tablex.lua for an example) --- @param x a value --- @param y value to compare first value against --- @param msg message --- @param where extra level offset for errors --- @function complain -test.complain = complain - ---- like assert, except takes two arguments that must be equal and can be tables. --- If they are plain tables, it will use tablex.deepcompare. --- @param x any value --- @param y a value equal to x --- @param eps an optional tolerance for numerical comparisons --- @param where extra level offset -function test.asserteq (x,y,eps,where) - local res = x == y - if not res then - res = tablex.deepcompare(x,y,true,eps) - end - if not res then - complain(x,y,nil,where) - end -end - ---- assert that the first string matches the second. --- @param s1 a string --- @param s2 a string --- @param where extra level offset -function test.assertmatch (s1,s2,where) - if not s1:match(s2) then - complain (s1,s2,"these strings did not match",where) - end -end - ---- assert that the function raises a particular error. --- @param fn a function or a table of the form {function,arg1,...} --- @param e a string to match the error against --- @param where extra level offset -function test.assertraise(fn,e,where) - local ok, err - if type(fn) == 'table' then - ok, err = pcall(unpack(fn)) - else - ok, err = pcall(fn) - end - if ok or err:match(e)==nil then - complain (err,e,"these errors did not match",where) - end -end - ---- a version of asserteq that takes two pairs of values. --- x1==y1 and x2==y2 must be true. Useful for functions that naturally --- return two values. --- @param x1 any value --- @param x2 any value --- @param y1 any value --- @param y2 any value --- @param where extra level offset -function test.asserteq2 (x1,x2,y1,y2,where) - if x1 ~= y1 then complain(x1,y1,nil,where) end - if x2 ~= y2 then complain(x2,y2,nil,where) end -end - --- tuple type -- - -local tuple_mt = { - unpack = unpack -} -tuple_mt.__index = tuple_mt - -function tuple_mt.__tostring(self) - local ts = {} - for i=1, self.n do - local s = self[i] - ts[i] = type(s) == 'string' and ('%q'):format(s) or tostring(s) - end - return 'tuple(' .. table.concat(ts, ', ') .. ')' -end - -function tuple_mt.__eq(a, b) - if a.n ~= b.n then return false end - for i=1, a.n do - if a[i] ~= b[i] then return false end - end - return true -end - -function tuple_mt.__len(self) - return self.n -end - ---- encode an arbitrary argument list as a tuple. --- This can be used to compare to other argument lists, which is --- very useful for testing functions which return a number of values. --- Unlike regular array-like tables ('sequences') they may contain nils. --- Tuples understand equality and know how to print themselves out. --- The # operator is defined to be the size, irrespecive of any nils, --- and there is an `unpack` method. --- @usage asserteq(tuple( ('ab'):find 'a'), tuple(1,1)) -function test.tuple(...) - return setmetatable(pack(...), tuple_mt) -end - ---- Time a function. Call the function a given number of times, and report the number of seconds taken, --- together with a message. Any extra arguments will be passed to the function. --- @string msg a descriptive message --- @int n number of times to call the function --- @func fun the function --- @param ... optional arguments to fun -function test.timer(msg,n,fun,...) - local start = clock() - for i = 1,n do fun(...) end - utils.printf("%s: took %7.2f sec\n",msg,clock()-start) -end - -return test diff --git a/game/scripts/vscripts/pl/text.lua b/game/scripts/vscripts/pl/text.lua deleted file mode 100644 index 8b6a53f..0000000 --- a/game/scripts/vscripts/pl/text.lua +++ /dev/null @@ -1,26 +0,0 @@ ---- Text processing utilities. --- --- This provides a Template class (modeled after the same from the Python --- libraries, see string.Template). It also provides similar functions to those --- found in the textwrap module. --- --- IMPORTANT: this module has been deprecated and will be removed in a future --- version (2.0). The contents of this module have moved to the `pl.stringx` --- module. --- --- See @{03-strings.md.String_Templates|the Guide}. --- --- Dependencies: `pl.stringx`, `pl.utils` --- @module pl.text - -local utils = require("pl.utils") - -utils.raise_deprecation { - source = "Penlight " .. utils._VERSION, - message = "the contents of module 'pl.text' has moved into 'pl.stringx'", - version_removed = "2.0.0", - deprecated_after = "1.11.0", - no_trace = true, -} - -return require "pl.stringx" diff --git a/game/scripts/vscripts/pl/types.lua b/game/scripts/vscripts/pl/types.lua deleted file mode 100644 index 35b0ccb..0000000 --- a/game/scripts/vscripts/pl/types.lua +++ /dev/null @@ -1,183 +0,0 @@ ----- Dealing with Detailed Type Information - --- Dependencies `pl.utils` --- @module pl.types - -local utils = require 'pl.utils' -local math_ceil = math.ceil -local assert_arg = utils.assert_arg -local types = {} - ---- is the object either a function or a callable object?. --- @param obj Object to check. -function types.is_callable (obj) - return type(obj) == 'function' or getmetatable(obj) and getmetatable(obj).__call and true -end - ---- is the object of the specified type?. --- If the type is a string, then use type, otherwise compare with metatable. --- --- NOTE: this function is imported from `utils.is_type`. --- @param obj An object to check --- @param tp The expected type --- @function is_type --- @see utils.is_type -types.is_type = utils.is_type - -local fileMT = getmetatable(io.stdout) - ---- a string representation of a type. --- For tables and userdata with metatables, we assume that the metatable has a `_name` --- field. If the field is not present it will return 'unknown table' or --- 'unknown userdata'. --- Lua file objects return the type 'file'. --- @param obj an object --- @return a string like 'number', 'table', 'file' or 'List' -function types.type (obj) - local t = type(obj) - if t == 'table' or t == 'userdata' then - local mt = getmetatable(obj) - if mt == fileMT then - return 'file' - elseif mt == nil then - return t - else - -- TODO: the "unknown" is weird, it should just return the type - return mt._name or "unknown "..t - end - else - return t - end -end - ---- is this number an integer? --- @param x a number --- @raise error if x is not a number --- @return boolean -function types.is_integer (x) - return math_ceil(x)==x -end - ---- Check if the object is "empty". --- An object is considered empty if it is: --- --- - `nil` --- - a table without any items (key-value pairs or indexes) --- - a string with no content ("") --- - not a nil/table/string --- @param o The object to check if it is empty. --- @param ignore_spaces If the object is a string and this is true the string is --- considered empty if it only contains spaces. --- @return `true` if the object is empty, otherwise a falsy value. -function types.is_empty(o, ignore_spaces) - if o == nil then - return true - elseif type(o) == "table" then - return next(o) == nil - elseif type(o) == "string" then - return o == "" or (not not ignore_spaces and (not not o:find("^%s+$"))) - else - return true - end -end - -local function check_meta (val) - if type(val) == 'table' then return true end - return getmetatable(val) -end - ---- is an object 'array-like'? --- An object is array like if: --- --- - it is a table, or --- - it has a metatable with `__len` and `__index` methods --- --- NOTE: since `__len` is 5.2+, on 5.1 is usually returns `false` for userdata --- @param val any value. --- @return `true` if the object is array-like, otherwise a falsy value. -function types.is_indexable (val) - local mt = check_meta(val) - if mt == true then return true end - return mt and mt.__len and mt.__index and true -end - ---- can an object be iterated over with `pairs`? --- An object is iterable if: --- --- - it is a table, or --- - it has a metatable with a `__pairs` meta method --- --- NOTE: since `__pairs` is 5.2+, on 5.1 is usually returns `false` for userdata --- @param val any value. --- @return `true` if the object is iterable, otherwise a falsy value. -function types.is_iterable (val) - local mt = check_meta(val) - if mt == true then return true end - return mt and mt.__pairs and true -end - ---- can an object accept new key/pair values? --- An object is iterable if: --- --- - it is a table, or --- - it has a metatable with a `__newindex` meta method --- --- @param val any value. --- @return `true` if the object is writeable, otherwise a falsy value. -function types.is_writeable (val) - local mt = check_meta(val) - if mt == true then return true end - return mt and mt.__newindex and true -end - --- Strings that should evaluate to true. -- TODO: add on/off ??? -local trues = { yes=true, y=true, ["true"]=true, t=true, ["1"]=true } --- Conditions types should evaluate to true. -local true_types = { - boolean=function(o, true_strs, check_objs) return o end, - string=function(o, true_strs, check_objs) - o = o:lower() - if trues[o] then - return true - end - -- Check alternative user provided strings. - for _,v in ipairs(true_strs or {}) do - if type(v) == "string" and o == v:lower() then - return true - end - end - return false - end, - number=function(o, true_strs, check_objs) return o ~= 0 end, - table=function(o, true_strs, check_objs) if check_objs and next(o) ~= nil then return true end return false end -} ---- Convert to a boolean value. --- True values are: --- --- * boolean: true. --- * string: 'yes', 'y', 'true', 't', '1' or additional strings specified by `true_strs`. --- * number: Any non-zero value. --- * table: Is not empty and `check_objs` is true. --- * everything else: Is not `nil` and `check_objs` is true. --- --- @param o The object to evaluate. --- @param[opt] true_strs optional Additional strings that when matched should evaluate to true. Comparison is case insensitive. --- This should be a List of strings. E.g. "ja" to support German. --- @param[opt] check_objs True if objects should be evaluated. --- @return true if the input evaluates to true, otherwise false. -function types.to_bool(o, true_strs, check_objs) - local true_func - if true_strs then - assert_arg(2, true_strs, "table") - end - true_func = true_types[type(o)] - if true_func then - return true_func(o, true_strs, check_objs) - elseif check_objs and o ~= nil then - return true - end - return false -end - - -return types diff --git a/game/scripts/vscripts/pl/url.lua b/game/scripts/vscripts/pl/url.lua deleted file mode 100644 index 8c7cfeb..0000000 --- a/game/scripts/vscripts/pl/url.lua +++ /dev/null @@ -1,51 +0,0 @@ ---- Python-style URL quoting library. --- --- @module pl.url - -local url = {} - -local function quote_char(c) - return string.format("%%%02X", string.byte(c)) -end - ---- Quote the url, replacing special characters using the '%xx' escape. --- @string s the string --- @bool quote_plus Also escape slashes and replace spaces by plus signs. --- @return The quoted string, or if `s` wasn't a string, just plain unaltered `s`. -function url.quote(s, quote_plus) - if type(s) ~= "string" then - return s - end - - s = s:gsub("\n", "\r\n") - s = s:gsub("([^A-Za-z0-9 %-_%./])", quote_char) - if quote_plus then - s = s:gsub(" ", "+") - s = s:gsub("/", quote_char) - else - s = s:gsub(" ", "%%20") - end - - return s -end - -local function unquote_char(h) - return string.char(tonumber(h, 16)) -end - ---- Unquote the url, replacing '%xx' escapes and plus signs. --- @string s the string --- @return The unquoted string, or if `s` wasn't a string, just plain unaltered `s`. -function url.unquote(s) - if type(s) ~= "string" then - return s - end - - s = s:gsub("+", " ") - s = s:gsub("%%(%x%x)", unquote_char) - s = s:gsub("\r\n", "\n") - - return s -end - -return url diff --git a/game/scripts/vscripts/pl/utils.lua b/game/scripts/vscripts/pl/utils.lua deleted file mode 100644 index 8db138e..0000000 --- a/game/scripts/vscripts/pl/utils.lua +++ /dev/null @@ -1,947 +0,0 @@ ---- Generally useful routines. --- See @{01-introduction.md.Generally_useful_functions|the Guide}. --- --- Dependencies: `pl.compat`, all exported fields and functions from --- `pl.compat` are also available in this module. --- --- @module pl.utils -local format = string.format -local compat = require 'pl.compat' -local stdout = io.stdout -local append = table.insert -local concat = table.concat -local _unpack = table.unpack -- always injected by 'compat' -local find = string.find -local sub = string.sub -local next = next -local floor = math.floor - -local is_windows = compat.is_windows -local err_mode = 'default' -local raise -local operators -local _function_factories = {} - - -local utils = { _VERSION = "1.13.1" } -for k, v in pairs(compat) do utils[k] = v end - ---- Some standard patterns --- @table patterns -utils.patterns = { - FLOAT = '[%+%-%d]%d*%.?%d*[eE]?[%+%-]?%d*', -- floating point number - INTEGER = '[+%-%d]%d*', -- integer number - IDEN = '[%a_][%w_]*', -- identifier - FILE = '[%a%.\\][:%][%w%._%-\\]*', -- file -} - - ---- Standard meta-tables as used by other Penlight modules --- @table stdmt --- @field List the List metatable --- @field Map the Map metatable --- @field Set the Set metatable --- @field MultiMap the MultiMap metatable -utils.stdmt = { - List = {_name='List'}, - Map = {_name='Map'}, - Set = {_name='Set'}, - MultiMap = {_name='MultiMap'}, -} - - ---- pack an argument list into a table. --- @param ... any arguments --- @return a table with field `n` set to the length --- @function utils.pack --- @see compat.pack --- @see utils.npairs --- @see utils.unpack -utils.pack = table.pack -- added here to be symmetrical with unpack - ---- unpack a table and return its contents. --- --- NOTE: this implementation differs from the Lua implementation in the way --- that this one DOES honor the `n` field in the table `t`, such that it is 'nil-safe'. --- @param t table to unpack --- @param[opt] i index from which to start unpacking, defaults to 1 --- @param[opt] j index of the last element to unpack, defaults to `t.n` or else `#t` --- @return multiple return values from the table --- @function utils.unpack --- @see compat.unpack --- @see utils.pack --- @see utils.npairs --- @usage --- local t = table.pack(nil, nil, nil, 4) --- local a, b, c, d = table.unpack(t) -- this `unpack` is NOT nil-safe, so d == nil --- --- local a, b, c, d = utils.unpack(t) -- this is nil-safe, so d == 4 -function utils.unpack(t, i, j) - return _unpack(t, i or 1, j or t.n or #t) -end - ---- print an arbitrary number of arguments using a format. --- Output will be sent to `stdout`. --- @param fmt The format (see `string.format`) --- @param ... Extra arguments for format -function utils.printf(fmt, ...) - utils.assert_string(1, fmt) - utils.fprintf(stdout, fmt, ...) -end - ---- write an arbitrary number of arguments to a file using a format. --- @param f File handle to write to. --- @param fmt The format (see `string.format`). --- @param ... Extra arguments for format -function utils.fprintf(f,fmt,...) - utils.assert_string(2,fmt) - f:write(format(fmt,...)) -end - -do - local function import_symbol(T,k,v,libname) - local key = rawget(T,k) - -- warn about collisions! - if key and k ~= '_M' and k ~= '_NAME' and k ~= '_PACKAGE' and k ~= '_VERSION' then - utils.fprintf(io.stderr,"warning: '%s.%s' will not override existing symbol\n",libname,k) - return - end - rawset(T,k,v) - end - - local function lookup_lib(T,t) - for k,v in pairs(T) do - if v == t then return k end - end - return '?' - end - - local already_imported = {} - - --- take a table and 'inject' it into the local namespace. - -- @param t The table (table), or module name (string), defaults to this `utils` module table - -- @param T An optional destination table (defaults to callers environment) - function utils.import(t,T) - T = T or _G - t = t or utils - if type(t) == 'string' then - t = require (t) - end - local libname = lookup_lib(T,t) - if already_imported[t] then return end - already_imported[t] = libname - for k,v in pairs(t) do - import_symbol(T,k,v,libname) - end - end -end - ---- return either of two values, depending on a condition. --- @param cond A condition --- @param value1 Value returned if cond is truthy --- @param value2 Value returned if cond is falsy -function utils.choose(cond, value1, value2) - return cond and value1 or value2 -end - ---- convert an array of values to strings. --- @param t a list-like table --- @param[opt] temp (table) buffer to use, otherwise allocate --- @param[opt] tostr custom tostring function, called with (value,index). Defaults to `tostring`. --- @return the converted buffer -function utils.array_tostring (t,temp,tostr) - temp, tostr = temp or {}, tostr or tostring - for i = 1,#t do - temp[i] = tostr(t[i],i) - end - return temp -end - - - ---- is the object of the specified type? --- If the type is a string, then use type, otherwise compare with metatable --- @param obj An object to check --- @param tp String of what type it should be --- @return boolean --- @usage utils.is_type("hello world", "string") --> true --- -- or check metatable --- local my_mt = {} --- local my_obj = setmetatable(my_obj, my_mt) --- utils.is_type(my_obj, my_mt) --> true -function utils.is_type (obj,tp) - if type(tp) == 'string' then return type(obj) == tp end - local mt = getmetatable(obj) - return tp == mt -end - - - ---- an iterator with indices, similar to `ipairs`, but with a range. --- This is a nil-safe index based iterator that will return `nil` when there --- is a hole in a list. To be safe ensure that table `t.n` contains the length. --- @tparam table t the table to iterate over --- @tparam[opt=1] integer i_start start index --- @tparam[opt=t.n or #t] integer i_end end index --- @tparam[opt=1] integer step step size --- @treturn integer index --- @treturn any value at index (which can be `nil`!) --- @see utils.pack --- @see utils.unpack --- @usage --- local t = utils.pack(nil, 123, nil) -- adds an `n` field when packing --- --- for i, v in utils.npairs(t, 2) do -- start at index 2 --- t[i] = tostring(t[i]) --- end --- --- -- t = { n = 3, [2] = "123", [3] = "nil" } -function utils.npairs(t, i_start, i_end, step) - step = step or 1 - if step == 0 then - error("iterator step-size cannot be 0", 2) - end - local i = (i_start or 1) - step - i_end = i_end or t.n or #t - if step < 0 then - return function() - i = i + step - if i < i_end then - return nil - end - return i, t[i] - end - - else - return function() - i = i + step - if i > i_end then - return nil - end - return i, t[i] - end - end -end - - - ---- an iterator over all non-integer keys (inverse of `ipairs`). --- It will skip any key that is an integer number, so negative indices or an --- array with holes will not return those either (so it returns slightly less than --- 'the inverse of `ipairs`'). --- --- This uses `pairs` under the hood, so any value that is iterable using `pairs` --- will work with this function. --- @tparam table t the table to iterate over --- @treturn key --- @treturn value --- @usage --- local t = { --- "hello", --- "world", --- hello = "hallo", --- world = "Welt", --- } --- --- for k, v in utils.kpairs(t) do --- print("German: ", v) --- end --- --- -- output; --- -- German: hallo --- -- German: Welt -function utils.kpairs(t) - local index - return function() - local value - while true do - index, value = next(t, index) - if type(index) ~= "number" or floor(index) ~= index then - break - end - end - return index, value - end -end - - - ---- Error handling --- @section Error-handling - ---- assert that the given argument is in fact of the correct type. --- @param n argument index --- @param val the value --- @param tp the type --- @param verify an optional verification function --- @param msg an optional custom message --- @param lev optional stack position for trace, default 2 --- @return the validated value --- @raise if `val` is not the correct type --- @usage --- local param1 = assert_arg(1,"hello",'table') --> error: argument 1 expected a 'table', got a 'string' --- local param4 = assert_arg(4,'!@#$%^&*','string',path.isdir,'not a directory') --- --> error: argument 4: '!@#$%^&*' not a directory -function utils.assert_arg (n,val,tp,verify,msg,lev) - if type(val) ~= tp then - error(("argument %d expected a '%s', got a '%s'"):format(n,tp,type(val)),lev or 2) - end - if verify and not verify(val) then - error(("argument %d: '%s' %s"):format(n,val,msg),lev or 2) - end - return val -end - ---- creates an Enum or constants lookup table for improved error handling. --- This helps prevent magic strings in code by throwing errors for accessing --- non-existing values, and/or converting strings/identifiers to other values. --- --- Calling on the object does the same, but returns a soft error; `nil + err`, if --- the call is succesful (the key exists), it will return the value. --- --- When calling with varargs or an array the values will be equal to the keys. --- The enum object is read-only. --- @tparam table|vararg ... the input for the Enum. If varargs or an array then the --- values in the Enum will be equal to the names (must be strings), if a hash-table --- then values remain (any type), and the keys must be strings. --- @return Enum object (read-only table/object) --- @usage -- Enum access at runtime --- local obj = {} --- obj.MOVEMENT = utils.enum("FORWARD", "REVERSE", "LEFT", "RIGHT") --- --- if current_movement == obj.MOVEMENT.FORWARD then --- -- do something --- --- elseif current_movement == obj.MOVEMENT.REVERES then --- -- throws error due to typo 'REVERES', so a silent mistake becomes a hard error --- -- "'REVERES' is not a valid value (expected one of: 'FORWARD', 'REVERSE', 'LEFT', 'RIGHT')" --- --- end --- @usage -- standardized error codes --- local obj = { --- ERR = utils.enum { --- NOT_FOUND = "the item was not found", --- OUT_OF_BOUNDS = "the index is outside the allowed range" --- }, --- --- some_method = function(self) --- return self.ERR.OUT_OF_BOUNDS --- end, --- } --- --- local result, err = obj:some_method() --- if not result then --- if err == obj.ERR.NOT_FOUND then --- -- check on error code, not magic strings --- --- else --- -- return the error description, contained in the constant --- return nil, "error: "..err -- "error: the index is outside the allowed range" --- end --- end --- @usage -- validating/converting user-input --- local color = "purple" --- local ansi_colors = utils.enum { --- black = 30, --- red = 31, --- green = 32, --- } --- local color_code, err = ansi_colors(color) -- calling on the object, returns the value from the enum --- if not color_code then --- print("bad 'color', " .. err) --- -- "bad 'color', 'purple' is not a valid value (expected one of: 'black', 'red', 'green')" --- os.exit(1) --- end -function utils.enum(...) - local first = select(1, ...) - local enum = {} - local lst - - if type(first) ~= "table" then - -- vararg with strings - lst = utils.pack(...) - for i, value in utils.npairs(lst) do - utils.assert_arg(i, value, "string") - enum[value] = value - end - - else - -- table/array with values - utils.assert_arg(1, first, "table") - lst = {} - -- first add array part - for i, value in ipairs(first) do - if type(value) ~= "string" then - error(("expected 'string' but got '%s' at index %d"):format(type(value), i), 2) - end - lst[i] = value - enum[value] = value - end - -- add key-ed part - for key, value in utils.kpairs(first) do - if type(key) ~= "string" then - error(("expected key to be 'string' but got '%s'"):format(type(key)), 2) - end - if enum[key] then - error(("duplicate entry in array and hash part: '%s'"):format(key), 2) - end - enum[key] = value - lst[#lst+1] = key - end - end - - if not lst[1] then - error("expected at least 1 entry", 2) - end - - local valid = "(expected one of: '" .. concat(lst, "', '") .. "')" - setmetatable(enum, { - __index = function(self, key) - error(("'%s' is not a valid value %s"):format(tostring(key), valid), 2) - end, - __newindex = function(self, key, value) - error("the Enum object is read-only", 2) - end, - __call = function(self, key) - if type(key) == "string" then - local v = rawget(self, key) - if v ~= nil then - return v - end - end - return nil, ("'%s' is not a valid value %s"):format(tostring(key), valid) - end - }) - - return enum -end - - ---- process a function argument. --- This is used throughout Penlight and defines what is meant by a function: --- Something that is callable, or an operator string as defined by pl.operator, --- such as '>' or '#'. If a function factory has been registered for the type, it will --- be called to get the function. --- @param idx argument index --- @param f a function, operator string, or callable object --- @param msg optional error message --- @return a callable --- @raise if idx is not a number or if f is not callable -function utils.function_arg (idx,f,msg) - utils.assert_arg(1,idx,'number') - local tp = type(f) - if tp == 'function' then return f end -- no worries! - -- ok, a string can correspond to an operator (like '==') - if tp == 'string' then - if not operators then operators = require 'pl.operator'.optable end - local fn = operators[f] - if fn then return fn end - local fn, err = utils.string_lambda(f) - if not fn then error(err..': '..f) end - return fn - elseif tp == 'table' or tp == 'userdata' then - local mt = getmetatable(f) - if not mt then error('not a callable object',2) end - local ff = _function_factories[mt] - if not ff then - if not mt.__call then error('not a callable object',2) end - return f - else - return ff(f) -- we have a function factory for this type! - end - end - if not msg then msg = " must be callable" end - if idx > 0 then - error("argument "..idx..": "..msg,2) - else - error(msg,2) - end -end - - ---- assert the common case that the argument is a string. --- @param n argument index --- @param val a value that must be a string --- @return the validated value --- @raise val must be a string --- @usage --- local val = 42 --- local param2 = utils.assert_string(2, val) --> error: argument 2 expected a 'string', got a 'number' -function utils.assert_string (n, val) - return utils.assert_arg(n,val,'string',nil,nil,3) -end - ---- control the error strategy used by Penlight. --- This is a global setting that controls how `utils.raise` behaves: --- --- - 'default': return `nil + error` (this is the default) --- - 'error': throw a Lua error --- - 'quit': exit the program --- --- @param mode either 'default', 'quit' or 'error' --- @see utils.raise -function utils.on_error (mode) - mode = tostring(mode) - if ({['default'] = 1, ['quit'] = 2, ['error'] = 3})[mode] then - err_mode = mode - else - -- fail loudly - local err = "Bad argument expected string; 'default', 'quit', or 'error'. Got '"..tostring(mode).."'" - if err_mode == 'default' then - error(err, 2) -- even in 'default' mode fail loud in this case - end - raise(err) - end -end - ---- used by Penlight functions to return errors. Its global behaviour is controlled --- by `utils.on_error`. --- To use this function you MUST use it in conjunction with `return`, since it might --- return `nil + error`. --- @param err the error string. --- @see utils.on_error --- @usage --- if some_condition then --- return utils.raise("some condition was not met") -- MUST use 'return'! --- end -function utils.raise (err) - if err_mode == 'default' then - return nil, err - elseif err_mode == 'quit' then - return utils.quit(err) - else - error(err, 2) - end -end -raise = utils.raise - - - ---- File handling --- @section files - ---- return the contents of a file as a string --- @param filename The file path --- @param is_bin open in binary mode --- @return file contents -function utils.readfile(filename,is_bin) - local mode = is_bin and 'b' or '' - utils.assert_string(1,filename) - local f,open_err = io.open(filename,'r'..mode) - if not f then return raise (open_err) end - local res,read_err = f:read('*a') - f:close() - if not res then - -- Errors in io.open have "filename: " prefix, - -- error in file:read don't, add it. - return raise (filename..": "..read_err) - end - return res -end - ---- write a string to a file --- @param filename The file path --- @param str The string --- @param is_bin open in binary mode --- @return true or nil --- @return error message --- @raise error if filename or str aren't strings -function utils.writefile(filename,str,is_bin) - local mode = is_bin and 'b' or '' - utils.assert_string(1,filename) - utils.assert_string(2,str) - local f,err = io.open(filename,'w'..mode) - if not f then return raise(err) end - local ok, write_err = f:write(str) - f:close() - if not ok then - -- Errors in io.open have "filename: " prefix, - -- error in file:write don't, add it. - return raise (filename..": "..write_err) - end - return true -end - ---- return the contents of a file as a list of lines --- @param filename The file path --- @return file contents as a table --- @raise error if filename is not a string -function utils.readlines(filename) - utils.assert_string(1,filename) - local f,err = io.open(filename,'r') - if not f then return raise(err) end - local res = {} - for line in f:lines() do - append(res,line) - end - f:close() - return res -end - ---- OS functions --- @section OS-functions - ---- execute a shell command and return the output. --- This function redirects the output to tempfiles and returns the content of those files. --- @param cmd a shell command --- @param bin boolean, if true, read output as binary file --- @return true if successful --- @return actual return code --- @return stdout output (string) --- @return errout output (string) -function utils.executeex(cmd, bin) - local outfile = os.tmpname() - local errfile = os.tmpname() - - if is_windows and not outfile:find(':') then - outfile = os.getenv('TEMP')..outfile - errfile = os.getenv('TEMP')..errfile - end - cmd = cmd .. " > " .. utils.quote_arg(outfile) .. " 2> " .. utils.quote_arg(errfile) - - local success, retcode = utils.execute(cmd) - local outcontent = utils.readfile(outfile, bin) - local errcontent = utils.readfile(errfile, bin) - os.remove(outfile) - os.remove(errfile) - return success, retcode, (outcontent or ""), (errcontent or "") -end - ---- Quote and escape an argument of a command. --- Quotes a single (or list of) argument(s) of a command to be passed --- to `os.execute`, `pl.utils.execute` or `pl.utils.executeex`. --- @param argument (string or table/list) the argument to quote. If a list then --- all arguments in the list will be returned as a single string quoted. --- @return quoted and escaped argument. --- @usage --- local options = utils.quote_arg { --- "-lluacov", --- "-e", --- "utils = print(require('pl.utils')._VERSION", --- } --- -- returns: -lluacov -e 'utils = print(require('\''pl.utils'\'')._VERSION' -function utils.quote_arg(argument) - if type(argument) == "table" then - -- encode an entire table - local r = {} - for i, arg in ipairs(argument) do - r[i] = utils.quote_arg(arg) - end - - return concat(r, " ") - end - -- only a single argument - if is_windows then - if argument == "" or argument:find('[ \f\t\v]') then - -- Need to quote the argument. - -- Quotes need to be escaped with backslashes; - -- additionally, backslashes before a quote, escaped or not, - -- need to be doubled. - -- See documentation for CommandLineToArgvW Windows function. - argument = '"' .. argument:gsub([[(\*)"]], [[%1%1\"]]):gsub([[\+$]], "%0%0") .. '"' - end - - -- os.execute() uses system() C function, which on Windows passes command - -- to cmd.exe. Escape its special characters. - return (argument:gsub('["^<>!|&%%]', "^%0")) - else - if argument == "" or argument:find('[^a-zA-Z0-9_@%+=:,./-]') then - -- To quote arguments on posix-like systems use single quotes. - -- To represent an embedded single quote close quoted string ('), - -- add escaped quote (\'), open quoted string again ('). - argument = "'" .. argument:gsub("'", [['\'']]) .. "'" - end - - return argument - end -end - ---- error out of this program gracefully. --- @param[opt] code The exit code, defaults to -`1` if omitted --- @param msg The exit message will be sent to `stderr` (will be formatted with the extra parameters) --- @param ... extra arguments for message's format' --- @see utils.fprintf --- @usage utils.quit(-1, "Error '%s' happened", "42") --- -- is equivalent to --- utils.quit("Error '%s' happened", "42") --> Error '42' happened -function utils.quit(code, msg, ...) - if type(code) == 'string' then - utils.fprintf(io.stderr, code, msg, ...) - io.stderr:write('\n') - code = -1 -- TODO: this is odd, see the test. Which returns 255 as exit code - elseif msg then - utils.fprintf(io.stderr, msg, ...) - io.stderr:write('\n') - end - os.exit(code, true) -end - - ---- String functions --- @section string-functions - ---- escape any Lua 'magic' characters in a string --- @param s The input string -function utils.escape(s) - utils.assert_string(1,s) - return (s:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1')) -end - ---- split a string into a list of strings separated by a delimiter. --- @param s The input string --- @param re optional A Lua string pattern; defaults to '%s+' --- @param plain optional If truthy don't use Lua patterns --- @param n optional maximum number of elements (if there are more, the last will remian un-split) --- @return a list-like table --- @raise error if s is not a string --- @see splitv -function utils.split(s,re,plain,n) - utils.assert_string(1,s) - local i1,ls = 1,{} - if not re then re = '%s+' end - if re == '' then return {s} end - while true do - local i2,i3 = find(s,re,i1,plain) - if not i2 then - local last = sub(s,i1) - if last ~= '' then append(ls,last) end - if #ls == 1 and ls[1] == '' then - return {} - else - return ls - end - end - append(ls,sub(s,i1,i2-1)) - if n and #ls == n then - ls[#ls] = sub(s,i1) - return ls - end - i1 = i3+1 - end -end - ---- split a string into a number of return values. --- Identical to `split` but returns multiple sub-strings instead of --- a single list of sub-strings. --- @param s the string --- @param re A Lua string pattern; defaults to '%s+' --- @param plain don't use Lua patterns --- @param n optional maximum number of splits --- @return n values --- @usage first,next = splitv('user=jane=doe','=', false, 2) --- assert(first == "user") --- assert(next == "jane=doe") --- @see split -function utils.splitv (s,re, plain, n) - return _unpack(utils.split(s,re, plain, n)) -end - - ---- Functional --- @section functional - - ---- 'memoize' a function (cache returned value for next call). --- This is useful if you have a function which is relatively expensive, --- but you don't know in advance what values will be required, so --- building a table upfront is wasteful/impossible. --- @param func a function of at least one argument --- @return a function with at least one argument, which is used as the key. -function utils.memoize(func) - local cache = {} - return function(k) - local res = cache[k] - if res == nil then - res = func(k) - cache[k] = res - end - return res - end -end - - ---- associate a function factory with a type. --- A function factory takes an object of the given type and --- returns a function for evaluating it --- @tab mt metatable --- @func fun a callable that returns a function -function utils.add_function_factory (mt,fun) - _function_factories[mt] = fun -end - -local function _string_lambda(f) - if f:find '^|' or f:find '_' then - local args,body = f:match '|([^|]*)|(.+)' - if f:find '_' then - args = '_' - body = f - else - if not args then return raise 'bad string lambda' end - end - local fstr = 'return function('..args..') return '..body..' end' - local fn,err = utils.load(fstr) - if not fn then return raise(err) end - fn = fn() - return fn - else - return raise 'not a string lambda' - end -end - - ---- an anonymous function as a string. This string is either of the form --- '|args| expression' or is a function of one argument, '_' --- @param lf function as a string --- @return a function --- @function utils.string_lambda --- @usage --- string_lambda '|x|x+1' (2) == 3 --- string_lambda '_+1' (2) == 3 -utils.string_lambda = utils.memoize(_string_lambda) - - ---- bind the first argument of the function to a value. --- @param fn a function of at least two values (may be an operator string) --- @param p a value --- @return a function such that f(x) is fn(p,x) --- @raise same as @{function_arg} --- @see func.bind1 --- @usage local function f(msg, name) --- print(msg .. " " .. name) --- end --- --- local hello = utils.bind1(f, "Hello") --- --- print(hello("world")) --> "Hello world" --- print(hello("sunshine")) --> "Hello sunshine" -function utils.bind1 (fn,p) - fn = utils.function_arg(1,fn) - return function(...) return fn(p,...) end -end - - ---- bind the second argument of the function to a value. --- @param fn a function of at least two values (may be an operator string) --- @param p a value --- @return a function such that f(x) is fn(x,p) --- @raise same as @{function_arg} --- @usage local function f(a, b, c) --- print(a .. " " .. b .. " " .. c) --- end --- --- local hello = utils.bind1(f, "world") --- --- print(hello("Hello", "!")) --> "Hello world !" --- print(hello("Bye", "?")) --> "Bye world ?" -function utils.bind2 (fn,p) - fn = utils.function_arg(1,fn) - return function(x,...) return fn(x,p,...) end -end - - - - ---- Deprecation --- @section deprecation - -do - -- the default implementation - local deprecation_func = function(msg, trace) - if trace then - warn(msg, "\n", trace) -- luacheck: ignore - else - warn(msg) -- luacheck: ignore - end - end - - --- Sets a deprecation warning function. - -- An application can override this function to support proper output of - -- deprecation warnings. The warnings can be generated from libraries or - -- functions by calling `utils.raise_deprecation`. The default function - -- will write to the 'warn' system (introduced in Lua 5.4, or the compatibility - -- function from the `compat` module for earlier versions). - -- - -- Note: only applications should set/change this function, libraries should not. - -- @param func a callback with signature: `function(msg, trace)` both arguments are strings, the latter being optional. - -- @see utils.raise_deprecation - -- @usage - -- -- write to the Nginx logs with OpenResty - -- utils.set_deprecation_func(function(msg, trace) - -- ngx.log(ngx.WARN, msg, (trace and (" " .. trace) or nil)) - -- end) - -- - -- -- disable deprecation warnings - -- utils.set_deprecation_func() - function utils.set_deprecation_func(func) - if func == nil then - deprecation_func = function() end - else - utils.assert_arg(1, func, "function") - deprecation_func = func - end - end - - --- raises a deprecation warning. - -- For options see the usage example below. - -- - -- Note: the `opts.deprecated_after` field is the last version in which - -- a feature or option was NOT YET deprecated! Because when writing the code it - -- is quite often not known in what version the code will land. But the last - -- released version is usually known. - -- @param opts options table - -- @see utils.set_deprecation_func - -- @usage - -- warn("@on") -- enable Lua warnings, they are usually off by default - -- - -- function stringx.islower(str) - -- raise_deprecation { - -- source = "Penlight " .. utils._VERSION, -- optional - -- message = "function 'islower' was renamed to 'is_lower'", -- required - -- version_removed = "2.0.0", -- optional - -- deprecated_after = "1.2.3", -- optional - -- no_trace = true, -- optional - -- } - -- return stringx.is_lower(str) - -- end - -- -- output: "[Penlight 1.9.2] function 'islower' was renamed to 'is_lower' (deprecated after 1.2.3, scheduled for removal in 2.0.0)" - function utils.raise_deprecation(opts) - utils.assert_arg(1, opts, "table") - if type(opts.message) ~= "string" then - error("field 'message' of the options table must be a string", 2) - end - local trace - if not opts.no_trace then - trace = debug.traceback("", 2):match("[\n%s]*(.-)$") - end - local msg - if opts.deprecated_after and opts.version_removed then - msg = (" (deprecated after %s, scheduled for removal in %s)"):format( - tostring(opts.deprecated_after), tostring(opts.version_removed)) - elseif opts.deprecated_after then - msg = (" (deprecated after %s)"):format(tostring(opts.deprecated_after)) - elseif opts.version_removed then - msg = (" (scheduled for removal in %s)"):format(tostring(opts.version_removed)) - else - msg = "" - end - - msg = opts.message .. msg - - if opts.source then - msg = "[" .. opts.source .."] " .. msg - else - if msg:sub(1,1) == "@" then - -- in Lua 5.4 "@" prefixed messages are control messages to the warn system - error("message cannot start with '@'", 2) - end - end - - deprecation_func(msg, trace) - end - -end - - -return utils - - diff --git a/game/scripts/vscripts/pl/xml.lua b/game/scripts/vscripts/pl/xml.lua deleted file mode 100644 index 9489530..0000000 --- a/game/scripts/vscripts/pl/xml.lua +++ /dev/null @@ -1,1165 +0,0 @@ ---- XML LOM Utilities. --- --- This implements some useful things on [LOM](http://matthewwild.co.uk/projects/luaexpat/lom.html) documents, such as returned by `lxp.lom.parse`. --- In particular, it can convert LOM back into XML text, with optional pretty-printing control. --- It is based on stanza.lua from [Prosody](http://hg.prosody.im/trunk/file/4621c92d2368/util/stanza.lua) --- --- > d = xml.parse "alice" --- > = d --- alice --- > = xml.tostring(d,'',' ') --- --- alice --- --- --- Can be used as a lightweight one-stop-shop for simple XML processing; a simple XML parser is included --- but the default is to use `lxp.lom` if it can be found. ---
--- Prosody IM
--- Copyright (C) 2008-2010 Matthew Wild
--- Copyright (C) 2008-2010 Waqas Hussain--
--- classic Lua XML parser by Roberto Ierusalimschy.
--- modified to output LOM format.
--- http://lua-users.org/wiki/LuaXml
--- 
--- See @{06-data.md.XML|the Guide} --- --- Dependencies: `pl.utils` --- --- Soft Dependencies: `lxp.lom` (fallback is to use basic Lua parser) --- @module pl.xml - -local utils = require 'pl.utils' -local split = utils.split -local t_insert = table.insert -local t_concat = table.concat -local t_remove = table.remove -local s_match = string.match -local tostring = tostring -local setmetatable = setmetatable -local getmetatable = getmetatable -local pairs = pairs -local ipairs = ipairs -local type = type -local next = next -local print = print -local unpack = utils.unpack -local s_gsub = string.gsub -local s_sub = string.sub -local s_find = string.find -local pcall = pcall -local require = require - - -utils.raise_deprecation { - source = "Penlight " .. utils._VERSION, - message = "the contents of module 'pl.xml' has been deprecated, please use a more specialized library instead", - version_removed = "2.0.0", - deprecated_after = "1.11.0", - no_trace = true, -} - - - -local _M = {} -local Doc = { __type = "doc" }; -Doc.__index = Doc; - - -local function is_text(s) return type(s) == 'string' end -local function is_tag(d) return type(d) == 'table' and is_text(d.tag) end - - - ---- create a new document node. --- @tparam string tag the tag name --- @tparam[opt={}] table attr attributes (table of name-value pairs) --- @return the Node object --- @see xml.elem --- @usage --- local doc = xml.new("main", { hello = "world", answer = "42" }) --- print(doc) -->
-function _M.new(tag, attr) - if type(tag) ~= "string" then - error("expected 'tag' to be a string value, got: " .. type(tag), 2) - end - attr = attr or {} - if type(attr) ~= "table" then - error("expected 'attr' to be a table value, got: " .. type(attr), 2) - end - - local doc = { tag = tag, attr = attr, last_add = {}}; - return setmetatable(doc, Doc); -end - - ---- parse an XML document. By default, this uses lxp.lom.parse, but --- falls back to basic_parse, or if `use_basic` is truthy --- @param text_or_filename file or string representation --- @param is_file whether text_or_file is a file name or not --- @param use_basic do a basic parse --- @return a parsed LOM document with the document metatatables set --- @return nil, error the error can either be a file error or a parse error -function _M.parse(text_or_filename, is_file, use_basic) - local parser,status,lom - if use_basic then - parser = _M.basic_parse - else - status,lom = pcall(require,'lxp.lom') - if not status then - parser = _M.basic_parse - else - parser = lom.parse - end - end - - if is_file then - local text, err = utils.readfile(text_or_filename) - if not text then - return nil, err - end - text_or_filename = text - end - - local doc, err = parser(text_or_filename) - if not doc then - return nil, err - end - - if lom then - _M.walk(doc, false, function(_, d) - setmetatable(d, Doc) - end) - end - return doc -end - - ---- Create a Node with a set of children (text or Nodes) and attributes. --- @tparam string tag a tag name --- @tparam table|string items either a single child (text or Node), or a table where the hash --- part is the attributes and the list part is the children (text or Nodes). --- @return the new Node --- @see xml.new --- @see xml.tags --- @usage --- local doc = xml.elem("top", "hello world") -- hello world --- local doc = xml.elem("main", xml.new("child")) --
--- local doc = xml.elem("main", { "this ", "is ", "nice" }) --
this is nice
--- local doc = xml.elem("main", { xml.new "this", --- xml.new "is", --- xml.new "nice" }) --
--- local doc = xml.elem("main", { hello = "world" }) --
--- local doc = xml.elem("main", { --- "prefix", --- xml.elem("child", { "this ", "is ", "nice"}), --- "postfix", --- attrib = "value" --- }) --
prefixthis is nicepostfix
" -function _M.elem(tag, items) - local s = _M.new(tag) - if is_text(items) then items = {items} end - if is_tag(items) then - t_insert(s,items) - elseif type(items) == 'table' then - for k,v in pairs(items) do - if is_text(k) then - s.attr[k] = v - t_insert(s.attr,k) - else - s[k] = v - end - end - end - return s -end - - ---- given a list of names, return a number of element constructors. --- If passing a comma-separated string, then whitespace surrounding the values --- will be stripped. --- --- The returned constructor functions are a shortcut to `xml.elem` where you --- no longer provide the tag-name, but only the `items` table. --- @tparam string|table list a list of names, or a comma-separated string. --- @return (multiple) constructor functions; `function(items)`. For the `items` --- parameter see `xml.elem`. --- @see xml.elem --- @usage --- local new_parent, new_child = xml.tags 'mom, kid' --- doc = new_parent {new_child 'Bob', new_child 'Annie'} --- -- BobAnnie -function _M.tags(list) - local ctors = {} - if is_text(list) then - list = split(list:match("^%s*(.-)%s*$"),'%s*,%s*') - end - for i,tag in ipairs(list) do - local function ctor(items) - return _M.elem(tag,items) - end - ctors[i] = ctor - end - return unpack(ctors) -end - - ---- Adds a document Node, at current position. --- This updates the last inserted position to the new Node. --- @tparam string tag the tag name --- @tparam[opt={}] table attrs attributes (table of name-value pairs) --- @return the current node (`self`) --- @usage --- local doc = xml.new("main") --- doc:addtag("penlight", { hello = "world"}) --- doc:addtag("expat") -- added to 'penlight' since position moved --- print(doc) -->
-function Doc:addtag(tag, attrs) - local s = _M.new(tag, attrs) - self:add_child(s) - t_insert(self.last_add, s) - return self -end - - ---- Adds a text node, at current position. --- @tparam string text a string --- @return the current node (`self`) --- @usage --- local doc = xml.new("main") --- doc:text("penlight") --- doc:text("expat") --- print(doc) -->
-function Doc:text(text) - self:add_child(text) - return self -end - - ---- Moves current position up one level. --- @return the current node (`self`) -function Doc:up() - t_remove(self.last_add) - return self -end - - ---- Resets current position to top level. --- Resets to the `self` node. --- @return the current node (`self`) -function Doc:reset() - local last_add = self.last_add - for i = 1,#last_add do - last_add[i] = nil - end - return self -end - - ---- Append a child to the currrent Node (ignoring current position). --- @param child a child node (either text or a document) --- @return the current node (`self`) --- @usage --- local doc = xml.new("main") --- doc:add_direct_child("dog") --- doc:add_direct_child(xml.new("child")) --- doc:add_direct_child("cat") --- print(doc) -->
dogcat
-function Doc:add_direct_child(child) - t_insert(self, child) - return self -end - - ---- Append a child at the current position (without changing position). --- @param child a child node (either text or a document) --- @return the current node (`self`) --- @usage --- local doc = xml.new("main") --- doc:addtag("one") --- doc:add_child(xml.new("item1")) --- doc:add_child(xml.new("item2")) --- doc:add_child(xml.new("item3")) --- print(doc) -->
-function Doc:add_child(child) - (self.last_add[#self.last_add] or self):add_direct_child(child) - return self -end - - ---accessing attributes: useful not to have to expose implementation (attr) ---but also can allow attr to be nil in any future optimizations - - ---- Set attributes of a document node. --- Will add/overwite values, but will not remove existing ones. --- Operates on the Node itself, will not take position into account. --- @tparam table t a table containing attribute/value pairs --- @return the current node (`self`) -function Doc:set_attribs(t) - -- TODO: keep array part in sync - for k,v in pairs(t) do - self.attr[k] = v - end - return self -end - - ---- Set a single attribute of a document node. --- Operates on the Node itself, will not take position into account. --- @param a attribute --- @param v its value, pass in `nil` to delete the attribute --- @return the current node (`self`) -function Doc:set_attrib(a,v) - -- TODO: keep array part in sync - self.attr[a] = v - return self -end - - ---- Gets the attributes of a document node. --- Operates on the Node itself, will not take position into account. --- @return table with attributes (attribute/value pairs) -function Doc:get_attribs() - return self.attr -end - - - -local template_cache do - local templ_cache = {} - - -- @param templ a template, a string being valid xml to be parsed, or a Node object - function template_cache(templ) - if is_text(templ) then - if templ_cache[templ] then - -- cache hit - return templ_cache[templ] - - else - -- parse and cache - local ptempl, err = _M.parse(templ,false,true) - if not ptempl then - return nil, err - end - templ_cache[templ] = ptempl - return ptempl - end - end - - if is_tag(templ) then - return templ - end - - return nil, "template is not a document" - end -end - - -do - local function is_data(data) - return #data == 0 or type(data[1]) ~= 'table' - end - - - local function prepare_data(data) - -- a hack for ensuring that $1 maps to first element of data, etc. - -- Either this or could change the gsub call just below. - for i,v in ipairs(data) do - data[tostring(i)] = v - end - end - - --- create a substituted copy of a document, - -- @param template may be a document or a string representation which will be parsed and cached - -- @param data a table of name-value pairs or a list of such tables - -- @return an XML document - function Doc.subst(template, data) - if type(data) ~= 'table' or not next(data) then - return nil, "data must be a non-empty table" - end - - if is_data(data) then - prepare_data(data) - end - - local templ, err = template_cache(template) - if err then - return nil, err - end - - local function _subst(item) - return _M.clone(templ, function(s) - return s:gsub('%$(%w+)', item) - end) - end - - if is_data(data) then - return _subst(data) - end - - local list = {} - for _, item in ipairs(data) do - prepare_data(item) - t_insert(list, _subst(item)) - end - - if data.tag then - list = _M.elem(data.tag,list) - end - return list - end -end - - ---- Return the first child with a given tag name (non-recursive). --- @param tag the tag name --- @return the child Node found or `nil` if not found -function Doc:child_with_name(tag) - for _, child in ipairs(self) do - if child.tag == tag then - return child - end - end -end - - -do - -- @param self document node to traverse - -- @param tag tag-name to look for - -- @param list array table to add the matching ones to - -- @param recurse if truthy, recursivly search the node - local function _children_with_name(self, tag, list, recurse) - -- TODO: protect against recursion - for _, child in ipairs(self) do - if type(child) == 'table' then - if child.tag == tag then - t_insert(list, child) - end - if recurse then - _children_with_name(child, tag, list, recurse) - end - end - end - end - - --- Returns all elements in a document that have a given tag. - -- @tparam string tag a tag name - -- @tparam[opt=false] boolean dont_recurse optionally only return the immediate children with this tag name - -- @return a list of elements found, list will be empty if none was found. - function Doc:get_elements_with_name(tag, dont_recurse) - local res = {} - _children_with_name(self, tag, res, not dont_recurse) - return res - end -end - - - ---- Iterator over all children of a document node, including text nodes. --- This function is not recursive, so returns only direct child nodes. --- @return iterator that returns a single Node per iteration. -function Doc:children() - local i = 0; - return function (a) - i = i + 1 - return a[i]; - end, self, i; -end - - ---- Return the first child element of a node, if it exists. --- This will skip text nodes. --- @return first child Node or `nil` if there is none. -function Doc:first_childtag() - if #self == 0 then - return - end - for _, t in ipairs(self) do - if is_tag(t) then - return t - end - end -end - - ---- Iterator that matches tag names, and a namespace (non-recursive). --- @tparam[opt=nil] string tag tag names to return. Returns all tags if not provided. --- @tparam[opt=nil] string xmlns the namespace value ('xmlns' attribute) to return. If not --- provided will match all namespaces. --- @return iterator that returns a single Node per iteration. -function Doc:matching_tags(tag, xmlns) - -- TODO: this doesn't make sense??? namespaces are not "xmnls", as matched below - -- but "xmlns:name"... so should be a string-prefix match if anything... - xmlns = xmlns or self.attr.xmlns; - local tags = self - local next_i = 1 - local max_i = #tags - local node - return function () - for i = next_i, max_i do - node = tags[i]; - if (not tag or node.tag == tag) and - (not xmlns or xmlns == node.attr.xmlns) then - next_i = i + 1 - return node - end - end - end, tags, next_i -end - - ---- Iterator over all child tags of a document node. This will skip over --- text nodes. --- @return iterator that returns a single Node per iteration. -function Doc:childtags() - local i = 0; - return function (a) - local v - repeat - i = i + 1 - v = self[i] - if v and type(v) == 'table' then - return v - end - until not v - end, self[1], i; -end - - ---- Visit child Nodes of a node and call a function, possibly modifying the document. --- Text elements will be skipped. --- This is not recursive, so only direct children will be passed. --- @tparam function callback a function with signature `function(node)`, passed the node. --- The element will be updated with the returned value, or deleted if it returns `nil`. -function Doc:maptags(callback) - local i = 1; - - while i <= #self do - if is_tag(self[i]) then - local ret = callback(self[i]); - if ret == nil then - -- remove it - t_remove(self, i); - - else - -- update it - self[i] = ret; - i = i + 1; - end - else - i = i + 1 - end - end - - return self; -end - - -do - local escape_table = { - ["'"] = "'", - ['"'] = """, - ["<"] = "<", - [">"] = ">", - ["&"] = "&", - } - - --- Escapes a string for safe use in xml. - -- Handles quotes(single+double), less-than, greater-than, and ampersand. - -- @tparam string str string value to escape - -- @return escaped string - -- @usage - -- local esc = xml.xml_escape([["'<>&]]) --> ""'<>&" - function _M.xml_escape(str) - return (s_gsub(str, "['&<>\"]", escape_table)) - end -end -local xml_escape = _M.xml_escape - -do - local escape_table = { - quot = '"', - apos = "'", - lt = "<", - gt = ">", - amp = "&", - } - - --- Unescapes a string from xml. - -- Handles quotes(single+double), less-than, greater-than, and ampersand. - -- @tparam string str string value to unescape - -- @return unescaped string - -- @usage - -- local unesc = xml.xml_escape(""'<>&") --> [["'<>&]] - function _M.xml_unescape(str) - return (str:gsub( "&(%a+);", escape_table)) - end -end -local xml_unescape = _M.xml_unescape - --- pretty printing --- if indent, then put each new tag on its own line --- if attr_indent, put each new attribute on its own line -local function _dostring(t, buf, parentns, block_indent, tag_indent, attr_indent) - local nsid = 0 - local tag = t.tag - - local lf = "" - if tag_indent then - lf = '\n'..block_indent - end - - local alf = " " - if attr_indent then - alf = '\n'..block_indent..attr_indent - end - - t_insert(buf, lf.."<"..tag) - - local function write_attr(k,v) - if s_find(k, "\1", 1, true) then - nsid = nsid + 1 - local ns, attrk = s_match(k, "^([^\1]*)\1?(.*)$") - t_insert(buf, " xmlns:ns"..nsid.."='"..xml_escape(ns).."' ".."ns"..nsid..":"..attrk.."='"..xml_escape(v).."'") - - elseif not (k == "xmlns" and v == parentns) then - t_insert(buf, alf..k.."='"..xml_escape(v).."'"); - end - end - - -- it's useful for testing to have predictable attribute ordering, if available - if #t.attr > 0 then - -- TODO: the key-value list is leading, what if they are not in-sync - for _,k in ipairs(t.attr) do - write_attr(k,t.attr[k]) - end - else - for k, v in pairs(t.attr) do - write_attr(k,v) - end - end - - local len = #t - local has_children - - if len == 0 then - t_insert(buf, attr_indent and '\n'..block_indent.."/>" or "/>") - - else - t_insert(buf, ">"); - - for n = 1, len do - local child = t[n] - - if child.tag then - has_children = true - _dostring(child, buf, t.attr.xmlns, block_indent and block_indent..tag_indent, tag_indent, attr_indent) - - else - -- text element - t_insert(buf, xml_escape(child)) - end - end - - t_insert(buf, (has_children and lf or '')..""); - end -end - ---- Function to pretty-print an XML document. --- @param doc an XML document --- @tparam[opt] string|int b_ind an initial block-indent (required when `t_ind` is set) --- @tparam[opt] string|int t_ind an tag-indent for each level (required when `a_ind` is set) --- @tparam[opt] string|int a_ind if given, indent each attribute pair and put on a separate line --- @tparam[opt] string|bool xml_preface force prefacing with default or custom , if truthy then `<?xml version='1.0'?>` will be used as default. --- @return a string representation --- @see Doc:tostring -function _M.tostring(doc, b_ind, t_ind, a_ind, xml_preface) - local buf = {} - - if type(b_ind) == "number" then b_ind = (" "):rep(b_ind) end - if type(t_ind) == "number" then t_ind = (" "):rep(t_ind) end - if type(a_ind) == "number" then a_ind = (" "):rep(a_ind) end - - if xml_preface then - if type(xml_preface) == "string" then - buf[1] = xml_preface - else - buf[1] = "" - end - end - - _dostring(doc, buf, nil, b_ind, t_ind, a_ind, xml_preface) - - return t_concat(buf) -end - - -Doc.__tostring = _M.tostring - - ---- Method to pretty-print an XML document. --- Invokes `xml.tostring`. --- @tparam[opt] string|int b_ind an initial indent (required when `t_ind` is set) --- @tparam[opt] string|int t_ind an indent for each level (required when `a_ind` is set) --- @tparam[opt] string|int a_ind if given, indent each attribute pair and put on a separate line --- @tparam[opt="<?xml version='1.0'?>"] string xml_preface force prefacing with default or custom --- @return a string representation --- @see xml.tostring -function Doc:tostring(b_ind, t_ind, a_ind, xml_preface) - return _M.tostring(self, b_ind, t_ind, a_ind, xml_preface) -end - - ---- get the full text value of an element. --- @return a single string with all text elements concatenated --- @usage --- local doc = xml.new("main") --- doc:text("one") --- doc:add_child(xml.elem "two") --- doc:text("three") --- --- local t = doc:get_text() --> "onethree" -function Doc:get_text() - local res = {} - for i,el in ipairs(self) do - if is_text(el) then t_insert(res,el) end - end - return t_concat(res); -end - - -do - local function _copy(object, kind, parent, strsubst, lookup_table) - if type(object) ~= "table" then - if strsubst and is_text(object) then - return strsubst(object, kind, parent) - else - return object - end - end - - if lookup_table[object] then - error("recursion detected") - end - lookup_table[object] = true - - local new_table = {} - lookup_table[object] = new_table - - local tag = object.tag - new_table.tag = _copy(tag, '*TAG', parent, strsubst, lookup_table) - - if object.attr then - local res = {} - for attr, value in pairs(object.attr) do - if type(attr) == "string" then - res[attr] = _copy(value, attr, object, strsubst, lookup_table) - end - end - new_table.attr = res - end - - for index = 1, #object do - local v = _copy(object[index], '*TEXT', object, strsubst, lookup_table) - t_insert(new_table,v) - end - - return setmetatable(new_table, getmetatable(object)) - end - - --- Returns a copy of a document. - -- The `strsubst` parameter is a callback with signature `function(object, kind, parent)`. - -- - -- Param `kind` has the following values, and parameters: - -- - -- - `"*TAG"`: `object` is the tag-name, `parent` is the Node object. Returns the new tag name. - -- - -- - `"*TEXT"`: `object` is the text-element, `parent` is the Node object. Returns the new text value. - -- - -- - other strings not prefixed with `*`: `kind` is the attribute name, `object` is the - -- attribute value, `parent` is the Node object. Returns the new attribute value. - -- - -- @tparam Node|string doc a Node object or string (text node) - -- @tparam[opt] function strsubst an optional function for handling string copying - -- which could do substitution, etc. - -- @return copy of the document - -- @see Doc:filter - function _M.clone(doc, strsubst) - return _copy(doc, nil, nil, strsubst, {}) - end -end - - ---- Returns a copy of a document. --- This is the method version of `xml.clone`. --- @see xml.clone --- @name Doc:filter --- @tparam[opt] function strsubst an optional function for handling string copying -Doc.filter = _M.clone -- also available as method - -do - local function _compare(t1, t2, recurse_check) - - local ty1 = type(t1) - local ty2 = type(t2) - - if ty1 ~= ty2 then - return false, 'type mismatch' - end - - if ty1 == 'string' then - if t1 == t2 then - return true - else - return false, 'text '..t1..' ~= text '..t2 - end - end - - if ty1 ~= 'table' or ty2 ~= 'table' then - return false, 'not a document' - end - - if recurse_check[t1] then - return false, "recursive document" - end - recurse_check[t1] = true - - if t1.tag ~= t2.tag then - return false, 'tag '..t1.tag..' ~= tag '..t2.tag - end - - if #t1 ~= #t2 then - return false, 'size '..#t1..' ~= size '..#t2..' for tag '..t1.tag - end - - -- compare attributes - for k,v in pairs(t1.attr) do - local t2_value = t2.attr[k] - if type(k) == "string" then - if t2_value ~= v then return false, 'mismatch attrib' end - else - if t2_value ~= nil and t2_value ~= v then return false, "mismatch attrib order" end - end - end - for k,v in pairs(t2.attr) do - local t1_value = t1.attr[k] - if type(k) == "string" then - if t1_value ~= v then return false, 'mismatch attrib' end - else - if t1_value ~= nil and t1_value ~= v then return false, "mismatch attrib order" end - end - end - - -- compare children - for i = 1, #t1 do - local ok, err = _compare(t1[i], t2[i], recurse_check) - if not ok then - return ok, err - end - end - return true - end - - --- Compare two documents or elements. - -- Equality is based on tag, child nodes (text and tags), attributes and order - -- of those (order only fails if both are given, and not equal). - -- @tparam Node|string t1 a Node object or string (text node) - -- @tparam Node|string t2 a Node object or string (text node) - -- @treturn boolean `true` when the Nodes are equal. - function _M.compare(t1,t2) - return _compare(t1, t2, {}) - end -end - - ---- is this value a document element? --- @param d any value --- @treturn boolean `true` if it is a `table` with property `tag` being a string value. --- @name is_tag -_M.is_tag = is_tag - - -do - local function _walk(doc, depth_first, operation, recurse_check) - if not depth_first then operation(doc.tag, doc) end - for _,d in ipairs(doc) do - if is_tag(d) then - assert(not recurse_check[d], "recursion detected") - recurse_check[d] = true - _walk(d, depth_first, operation, recurse_check) - end - end - if depth_first then operation(doc.tag, doc) end - end - - --- Calls a function recursively over Nodes in the document. - -- Will only call on tags, it will skip text nodes. - -- The function signature for `operation` is `function(tag_name, Node)`. - -- @tparam Node|string doc a Node object or string (text node) - -- @tparam boolean depth_first visit child nodes first, then the current node - -- @tparam function operation a function which will receive the current tag name and current node. - function _M.walk(doc, depth_first, operation) - return _walk(doc, depth_first, operation, {}) - end -end - - -local html_empty_elements = { --lists all HTML empty (void) elements - br = true, - img = true, - meta = true, - frame = true, - area = true, - hr = true, - base = true, - col = true, - link = true, - input = true, - option = true, - param = true, - isindex = true, - embed = true, -} - ---- Parse a well-formed HTML file as a string. --- Tags are case-insenstive, DOCTYPE is ignored, and empty elements can be .. empty. --- @param s the HTML -function _M.parsehtml(s) - return _M.basic_parse(s,false,true) -end - ---- Parse a simple XML document using a pure Lua parser based on Robero Ierusalimschy's original version. --- @param s the XML document to be parsed. --- @param all_text if true, preserves all whitespace. Otherwise only text containing non-whitespace is included. --- @param html if true, uses relaxed HTML rules for parsing -function _M.basic_parse(s, all_text, html) - local stack = {} - local top = {} - - local function parseargs(s) - local arg = {} - s:gsub("([%w:%-_]+)%s*=%s*([\"'])(.-)%2", function (w, _, a) - if html then w = w:lower() end - arg[w] = xml_unescape(a) - end) - if html then - s:gsub("([%w:%-_]+)%s*=%s*([^\"']+)%s*", function (w, a) - w = w:lower() - arg[w] = xml_unescape(a) - end) - end - return arg - end - - t_insert(stack, top) - local ni,c,label,xarg, empty, _, istart - local i = 1 - local j - -- we're not interested in - _,istart = s_find(s,'^%s*<%?[^%?]+%?>%s*') - if not istart then -- or - _,istart = s_find(s,'^%s*%s*') - end - if istart then i = istart+1 end - while true do - ni,j,c,label,xarg, empty = s_find(s, "<([%/!]?)([%w:%-_]+)(.-)(%/?)>", i) - if not ni then break end - if c == "!" then -- comment - -- case where there's no space inside comment - if not (label:match '%-%-$' and xarg == '') then - if xarg:match '%-%-$' then -- we've grabbed it all - j = j - 2 - end - -- match end of comment - _,j = s_find(s, "-->", j, true) - end - else - local text = s_sub(s, i, ni-1) - if html then - label = label:lower() - if html_empty_elements[label] then empty = "/" end - end - if all_text or not s_find(text, "^%s*$") then - t_insert(top, xml_unescape(text)) - end - if empty == "/" then -- empty element tag - t_insert(top, setmetatable({tag=label, attr=parseargs(xarg), empty=1},Doc)) - elseif c == "" then -- start tag - top = setmetatable({tag=label, attr=parseargs(xarg)},Doc) - t_insert(stack, top) -- new level - else -- end tag - local toclose = t_remove(stack) -- remove top - top = stack[#stack] - if #stack < 1 then - error("nothing to close with "..label..':'..text) - end - if toclose.tag ~= label then - error("trying to close "..toclose.tag.." with "..label.." "..text) - end - t_insert(top, toclose) - end - end - i = j+1 - end - local text = s_sub(s, i) - if all_text or not s_find(text, "^%s*$") then - t_insert(stack[#stack], xml_unescape(text)) - end - if #stack > 1 then - error("unclosed "..stack[#stack].tag) - end - local res = stack[1] - return is_text(res[1]) and res[2] or res[1] -end - -do - local match do - - local function empty(attr) return not attr or not next(attr) end - - local append_capture do - -- returns the key,value pair from a table if it has exactly one entry - local function has_one_element(t) - local key,value = next(t) - if next(t,key) ~= nil then return false end - return key,value - end - - function append_capture(res,tbl) - if not empty(tbl) then -- no point in capturing empty tables... - local key - if tbl._ then -- if $_ was set then it is meant as the top-level key for the captured table - key = tbl._ - tbl._ = nil - if empty(tbl) then return end - end - -- a table with only one pair {[0]=value} shall be reduced to that value - local numkey,val = has_one_element(tbl) - if numkey == 0 then tbl = val end - if key then - res[key] = tbl - else -- otherwise, we append the captured table - t_insert(res,tbl) - end - end - end - end - - local function make_number(pat) - if pat:find '^%d+$' then -- $1 etc means use this as an array location - pat = tonumber(pat) - end - return pat - end - - local function capture_attrib(res,pat,value) - pat = make_number(pat:sub(2)) - res[pat] = value - return true - end - - function match(d,pat,res,keep_going) - local ret = true - if d == nil then d = '' end --return false end - -- attribute string matching is straight equality, except if the pattern is a $ capture, - -- which always succeeds. - if is_text(d) then - if not is_text(pat) then return false end - if _M.debug then print(d,pat) end - if pat:find '^%$' then - return capture_attrib(res,pat,d) - else - return d == pat - end - else - if _M.debug then print(d.tag,pat.tag) end - -- this is an element node. For a match to succeed, the attributes must - -- match as well. - -- a tagname in the pattern ending with '-' is a wildcard and matches like an attribute - local tagpat = pat.tag:match '^(.-)%-$' - if tagpat then - tagpat = make_number(tagpat) - res[tagpat] = d.tag - end - if d.tag == pat.tag or tagpat then - - if not empty(pat.attr) then - if empty(d.attr) then ret = false - else - for prop,pval in pairs(pat.attr) do - local dval = d.attr[prop] - if not match(dval,pval,res) then ret = false; break end - end - end - end - -- the pattern may have child nodes. We match partially, so that {P1,P2} shall match {X,P1,X,X,P2,..} - if ret and #pat > 0 then - local i,j = 1,1 - local function next_elem() - j = j + 1 -- next child element of data - if is_text(d[j]) then j = j + 1 end - return j <= #d - end - repeat - local p = pat[i] - -- repeated {{<...>}} patterns shall match one or more elements - -- so e.g. {P+} will match {X,X,P,P,X,P,X,X,X} - if is_tag(p) and p.repeated then - local found - repeat - local tbl = {} - ret = match(d[j],p,tbl,false) - if ret then - found = false --true - append_capture(res,tbl) - end - until not next_elem() or (found and not ret) - i = i + 1 - else - ret = match(d[j],p,res,false) - if ret then i = i + 1 end - end - until not next_elem() or i > #pat -- run out of elements or patterns to match - -- if every element in our pattern matched ok, then it's been a successful match - if i > #pat then return true end - end - if ret then return true end - else - ret = false - end - -- keep going anyway - look at the children! - if keep_going then - for child in d:childtags() do - ret = match(child,pat,res,keep_going) - if ret then break end - end - end - end - return ret - end - end - - --- does something... - function Doc:match(pat) - local err - pat,err = template_cache(pat) - if not pat then return nil, err end - _M.walk(pat,false,function(_,d) - if is_text(d[1]) and is_tag(d[2]) and is_text(d[3]) and - d[1]:find '%s*{{' and d[3]:find '}}%s*' then - t_remove(d,1) - t_remove(d,2) - d[1].repeated = true - end - end) - - local res = {} - local ret = match(self,pat,res,true) - return res,ret - end -end - - -return _M - diff --git a/spec/combo/base_combo_spec.lua b/spec/combo/base_combo_spec.lua new file mode 100644 index 0000000..a642e3f --- /dev/null +++ b/spec/combo/base_combo_spec.lua @@ -0,0 +1,131 @@ +local assert = require("luassert") + +local F = require("support.factory") + +local BaseCombo = require("invk.combo.base_combo") +local S = require("invk.combo.spec") +local talents = require("invk.dota2.talents") + +--- @type invk.combo.ComboSpec +local SPEC = { + id = 13, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = 5, + difficulty_rating = 5, + hero_level = 25, + orbs = { 7, 7, 7 }, + gold = 1234, + items = { "item_blink" }, + tags = { "late-game" }, + talents = talents.select( + talents.Talents.L10_LEFT, + talents.Talents.L15_RIGHT, + talents.Talents.L20_RIGHT, + talents.Talents.L25_RIGHT + ), + sequence = {}, +} + +describe("invk.combo.BaseCombo", function() + --- @type invk.combo.BaseCombo + local combo + + before_each(function() + combo = BaseCombo:new(SPEC) + end) + + describe("constructor", function() + it("initializes attributes", function() + for key, value in pairs(SPEC) do + assert.same(value, combo[key]) + end + + assert.equal(BaseCombo.State.Initial, combo.state) + assert.equal(0, combo.metrics.count) + assert.equal(0, combo.metrics.damage) + assert.equal(0, combo.metrics.duration) + end) + end) + + describe(":current_step_id", function() + it("raises an error", function() + assert.error(function() + combo:current_step_id() + end, "Not implemented") + end) + end) + + describe(":current_step", function() + it("raises an error", function() + assert.error(function() + combo:current_step() + end, "Not implemented") + end) + end) + + describe(":next_steps_ids", function() + it("raises an error", function() + assert.error(function() + combo:next_steps_ids() + end, "Not implemented") + end) + end) + + describe(":next_steps", function() + it("raises an error", function() + assert.error(function() + combo:next_steps() + end, "Not implemented") + end) + end) + + describe(":progress", function() + it("raises an error", function() + assert.error(function() + local ability = F.ability({ name = "step1" }) + + combo:progress(ability) + end, "Not implemented") + end) + end) + + describe(":fail", function() + it("flags the combo as failed", function() + assert.equal(BaseCombo.State.Initial, combo.state) + + combo:fail() + + assert.equal(BaseCombo.State.Failed, combo.state) + end) + end) + + describe(":pre_finish", function() + it("raises an error", function() + assert.error(function() + combo:pre_finish() + end, "Not implemented") + + assert.equal(BaseCombo.State.Initial, combo.state) + end) + end) + + describe(":finish", function() + it("raises an error", function() + assert.error(function() + combo:finish() + end, "Not implemented") + + assert.equal(BaseCombo.State.Initial, combo.state) + end) + end) + + describe(":increment_damage", function() + it("increments the damage accumulator and returns the accumulated value", function() + assert.equal(13, combo:increment_damage(13)) + assert.equal(13, combo.metrics.damage) + assert.equal(44, combo:increment_damage(31)) + assert.equal(44, combo.metrics.damage) + end) + end) +end) diff --git a/spec/combo/combo_sequence_spec.lua b/spec/combo/combo_sequence_spec.lua new file mode 100644 index 0000000..1158776 --- /dev/null +++ b/spec/combo/combo_sequence_spec.lua @@ -0,0 +1,230 @@ +local assert = require("luassert") +local m = require("moses") + +local MockClock = require("support.dota2.clock") +local combo_h = require("support.combo.helpers") + +local ComboSequence = require("invk.combo.combo_sequence") +local ComboStep = require("invk.combo.combo_step") + +local STATES = ComboSequence.STATES + +describe("invk.combo.ComboSequence", function() + local steps = { + { id = 1, name = "step1", required = true, next = { 2, 3 } }, + { id = 2, name = "step2", next = { 3 } }, + { id = 3, name = "step3", required = true }, + } + + --- @type invk.combo.ComboSequence + local seq + --- @type string + local seq_id + --- @type support.dota2.MockClock + local clock = MockClock() + + before_each(function() + clock:reset() + + seq_id = m.uniqueId() + seq = ComboSequence:new(seq_id, steps, { clock = clock }) + end) + + describe("constructor", function() + it("initializes attributes", function() + assert.equal(seq_id, seq.id) + assert.equal(clock, seq.clock) + assert.is_table(seq.sequence) + + for _, s in ipairs(seq.sequence) do + assert.is_true(s:isInstanceOf(ComboStep)) + end + end) + end) + + describe(":enter_time", function() + it("returns the time when the sequence entered a state", function() + assert.is_true(seq:progress("step1")) + assert.is_true(seq:progress("step2")) + assert.is_true(seq:progress("step3")) + assert.is_true(seq:pre_finish()) + assert.equal(4, seq:enter_time(STATES.PRE_FINISH)) + assert.is_nil(seq:enter_time(STATES.FINISH)) + end) + + it("returns nil for an invalid state", function() + assert.is_true(seq:progress("step1")) + assert.is_true(seq:progress("step2")) + assert.is_true(seq:progress("step3")) + assert.is_true(seq:pre_finish()) + assert.is_true(seq:finish()) + assert.is_nil(seq:enter_time("invalid")) + end) + end) + + describe(":leave_time", function() + it("returns the time when the sequence left a state", function() + assert.is_true(seq:progress("step1")) + assert.is_true(seq:progress("step2")) + assert.is_true(seq:progress("step3")) + assert.is_true(seq:pre_finish()) + assert.is_true(seq:finish()) + assert.equal(5, seq:leave_time(STATES.PRE_FINISH)) + assert.is_nil(seq:leave_time(STATES.FINISH)) + end) + + it("returns nil for an invalid state", function() + assert.is_true(seq:progress("step1")) + assert.is_true(seq:progress("step2")) + assert.is_true(seq:progress("step3")) + assert.is_true(seq:pre_finish()) + assert.is_true(seq:finish()) + assert.is_nil(seq:leave_time("invalid")) + end) + end) + + describe(":progress", function() + describe("with a valid event", function() + it("progresses the sequence", function() + assert.is_nil(seq.current) + assert.is_nil(seq.current_id) + assert.same({ 1 }, seq.next_ids) + assert.same({ 1 }, combo_h.steps_ids(seq.next)) + assert.is_nil(seq:enter_time(STATES.INITIAL)) + assert.is_nil(seq:leave_time(STATES.INITIAL)) + + assert.is_true(seq:progress("step1")) + + assert.is_not_nil(seq.current) --- @cast seq.current invk.combo.ComboStep + assert.same(1, seq.current.id) + assert.equal(1, seq.current_id) + assert.same({ 2, 3 }, seq.next_ids) + assert.same({ 2, 3 }, combo_h.steps_ids(seq.next)) + assert.equal(1, seq:leave_time(STATES.INITIAL)) + + assert.is_true(seq:progress("step2")) + + assert.is_not_nil(seq.current) --- @cast seq.current invk.combo.ComboStep + assert.same(2, seq.current.id) + assert.equal(2, seq.current_id) + assert.same({ 3 }, seq.next_ids) + assert.same({ 3 }, combo_h.steps_ids(seq.next)) + + assert.is_true(seq:progress("step3")) + + assert.is_not_nil(seq.current) --- @cast seq.current invk.combo.ComboStep + assert.same(3, seq.current.id) + assert.equal(3, seq.current_id) + assert.same({}, seq.next_ids) + assert.same({}, combo_h.steps_ids(seq.next)) + + assert.is_true(seq:pre_finish()) + + assert.is_nil(seq.current) + assert.is_nil(seq.current_id) + assert.same({}, seq.next_ids) + assert.same({}, combo_h.steps_ids(seq.next)) + assert.equal(4, seq:enter_time(STATES.PRE_FINISH)) + + assert.is_true(seq:finish()) + + assert.is_nil(seq.current) + assert.is_nil(seq.current_id) + assert.same({}, seq.next_ids) + assert.same({}, combo_h.steps_ids(seq.next)) + assert.equal(5, seq:leave_time(STATES.PRE_FINISH)) + assert.equal(5, seq:enter_time(STATES.FINISH)) + end) + + it("enables skipping optional steps", function() + assert.is_nil(seq.current) + assert.is_nil(seq.current_id) + assert.same({ 1 }, seq.next_ids) + assert.same({ 1 }, combo_h.steps_ids(seq.next)) + assert.is_nil(seq:enter_time(STATES.INITIAL)) + assert.is_nil(seq:leave_time(STATES.INITIAL)) + + assert.is_true(seq:progress("step1")) + + assert.is_not_nil(seq.current) --- @cast seq.current invk.combo.ComboStep + assert.same(1, seq.current.id) + assert.equal(1, seq.current_id) + assert.same({ 2, 3 }, seq.next_ids) + assert.same({ 2, 3 }, combo_h.steps_ids(seq.next)) + assert.equal(1, seq:leave_time(STATES.INITIAL)) + + assert.is_true(seq:progress("step3")) + + assert.is_not_nil(seq.current) --- @cast seq.current invk.combo.ComboStep + assert.same(3, seq.current.id) + assert.equal(3, seq.current_id) + assert.same({}, seq.next_ids) + assert.same({}, combo_h.steps_ids(seq.next)) + + assert.is_true(seq:pre_finish()) + + assert.is_nil(seq.current) + assert.is_nil(seq.current_id) + assert.same({}, seq.next_ids) + assert.same({}, combo_h.steps_ids(seq.next)) + assert.equal(3, seq:enter_time(STATES.PRE_FINISH)) + + assert.is_true(seq:finish()) + + assert.is_nil(seq.current) + assert.is_nil(seq.current_id) + assert.same({}, seq.next_ids) + assert.same({}, combo_h.steps_ids(seq.next)) + assert.equal(4, seq:leave_time(STATES.PRE_FINISH)) + assert.equal(4, seq:enter_time(STATES.FINISH)) + end) + end) + + describe("with an invalid event", function() + it("does NOT progress the sequence", function() + assert.is_false(seq:progress("invalid")) + assert.is_false(seq:progress("step2")) + assert.is_true(seq:progress("step1")) + assert.is_true(seq:progress("step3")) + assert.is_false(seq:progress("step1")) + assert.is_false(seq:progress("step2")) + assert.is_false(seq:progress("invalid")) + end) + end) + end) + + describe(":pre_finish", function() + it("pre-finishes the sequence", function() + assert.is_false(seq:pre_finish()) + assert.is_true(seq:progress("step1")) + assert.is_false(seq:pre_finish()) + assert.is_true(seq:progress("step2")) + assert.is_false(seq:pre_finish()) + assert.is_true(seq:progress("step3")) + assert.is_true(seq:pre_finish()) + end) + end) + + describe(":finish", function() + it("finishes the sequence", function() + assert.is_false(seq:finish()) + assert.is_true(seq:progress("step1")) + assert.is_false(seq:finish()) + assert.is_true(seq:progress("step2")) + assert.is_false(seq:finish()) + assert.is_true(seq:progress("step3")) + assert.is_false(seq:finish()) + assert.is_true(seq:pre_finish()) + assert.is_true(seq:finish()) + end) + + it("sets the duration", function() + assert.is_true(seq:progress("step1")) + assert.is_true(seq:progress("step2")) + assert.is_true(seq:progress("step3")) + assert.is_true(seq:pre_finish()) + assert.is_true(seq:finish()) + assert.equal(4, seq.duration) + end) + end) +end) diff --git a/spec/combo/combo_spec.lua b/spec/combo/combo_spec.lua new file mode 100644 index 0000000..9afb2f4 --- /dev/null +++ b/spec/combo/combo_spec.lua @@ -0,0 +1,369 @@ +local assert = require("luassert") +local m = require("moses") +local spy = require("luassert.spy") + +local F = require("support.factory") +local MockClock = require("support.dota2.clock") + +local BaseCombo = require("invk.combo.base_combo") +local Combo = require("invk.combo.combo") +local ComboSequence = require("invk.combo.combo_sequence") +local S = require("invk.combo.spec") +local talents = require("invk.dota2.talents") + +local State = BaseCombo.State +local Talents = talents.Talents + +--- @type invk.combo.ComboSpec +local SPEC = { + id = 13, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = S.DamageRating.None, + difficulty_rating = S.DifficultyRating.Easy, + gold = 1234, + items = { "item_blink" }, + hero_level = 30, + orbs = { 7, 7, 7 }, + talents = talents.select( + Talents.L10_LEFT, + Talents.L15_RIGHT, + Talents.L20_RIGHT, + Talents.L25_RIGHT + ), + tags = { "late-game" }, + sequence = { + { id = 1, name = "step1", required = true, next = { 2, 3 } }, + { id = 2, name = "step2", next = { 3 } }, + { id = 3, name = "step3", required = true }, + }, +} + +describe("invk.combo.Combo", function() + --- @type invk.combo.Combo + local combo + --- @type support.dota2.MockClock + local clock = MockClock() + + local function steps_ids(arr) + return m.map(arr, function(s) + return s.id + end) + end + + local ability1 = F.ability({ name = "step1", AbilityDuration = 0.5 }) + local ability2 = F.ability({ name = "step2", AbilityDuration = 0.3 }) + local ability3 = F.ability({ name = "step3", AbilityDuration = 0.25 }) + + before_each(function() + clock:reset() + combo = Combo:new(SPEC, { clock = clock }) + end) + + it("inherits from BaseCombo", function() + assert.is_true(Combo:isSubclassOf(BaseCombo)) + assert.is_true(combo:isInstanceOf(BaseCombo)) + end) + + describe("constructor", function() + it("initializes attributes", function() + for key, value in pairs(m.omit(SPEC, { "sequence" })) do + assert.same(SPEC[key], value) + end + + assert.equal(State.Initial, combo.state) + assert.equal(0, combo.metrics.count) + assert.equal(0, combo.metrics.damage) + assert.equal(0, combo.metrics.duration) + assert.equal(clock, combo.clock) + assert.is_true(combo.sequence:isInstanceOf(ComboSequence)) + end) + end) + + describe("#todot", function() + it("delegates to sequence", function() + local spy_todot = spy.on(combo.sequence, "todot") + + combo:todot() + + assert.spy(spy_todot).called(1) + end) + end) + + describe(":current_step_id", function() + it("returns the current step id", function() + assert.is_nil(combo:current_step_id()) + assert.is_true(combo:progress(ability1)) + assert.equal(1, combo:current_step_id()) + assert.is_true(combo:progress(ability2)) + assert.equal(2, combo:current_step_id()) + assert.is_true(combo:progress(ability3)) + assert.equal(3, combo:current_step_id()) + assert.is_true(combo:pre_finish()) + assert.is_nil(combo:current_step_id()) + assert.is_true(combo:finish()) + assert.is_nil(combo:current_step_id()) + end) + end) + + describe(":current_step", function() + it("returns the current step", function() + assert.is_nil(combo:current_step()) + + do + assert.is_true(combo:progress(ability1)) + + local step = combo:current_step() + + assert.is_table(step) + --- @cast step invk.combo.ComboStep + assert.equal(1, step.id) + assert.equal("step1", step.name) + end + + do + assert.is_true(combo:progress(ability2)) + + local step = combo:current_step() + + assert.is_table(step) + --- @cast step invk.combo.ComboStep + assert.equal(2, step.id) + assert.equal("step2", step.name) + end + + do + assert.is_true(combo:progress(ability3)) + + local step = combo:current_step() + + assert.is_table(step) + --- @cast step invk.combo.ComboStep + assert.equal(3, step.id) + assert.equal("step3", step.name) + end + + assert.is_true(combo:pre_finish()) + assert.is_nil(combo:current_step()) + assert.is_true(combo:finish()) + assert.is_nil(combo:current_step()) + end) + end) + + describe(":next_steps_ids", function() + it("returns the next steps ids", function() + assert.same({ 1 }, combo:next_steps_ids()) + assert.is_true(combo:progress(ability1)) + assert.same({ 2, 3 }, combo:next_steps_ids()) + assert.is_true(combo:progress(ability2)) + assert.same({ 3 }, combo:next_steps_ids()) + assert.is_true(combo:progress(ability3)) + assert.same({}, combo:next_steps_ids()) + assert.is_true(combo:pre_finish()) + assert.same({}, combo:next_steps_ids()) + assert.is_true(combo:finish()) + assert.same({}, combo:next_steps_ids()) + end) + end) + + describe(":next_steps", function() + it("returns the next steps", function() + assert.same({ 1 }, steps_ids(combo:next_steps())) + assert.is_true(combo:progress(ability1)) + assert.same({ 2, 3 }, steps_ids(combo:next_steps())) + assert.is_true(combo:progress(ability2)) + assert.same({ 3 }, steps_ids(combo:next_steps())) + assert.is_true(combo:progress(ability3)) + assert.same({}, combo:next_steps()) + assert.is_true(combo:pre_finish()) + assert.same({}, combo:next_steps()) + assert.is_true(combo:finish()) + assert.same({}, combo:next_steps()) + end) + end) + + describe(":progress", function() + describe("with valid abilities", function() + it("progresses the combo", function() + assert.equal(State.Initial, combo.state) + assert.equal(0, combo.metrics.count) + assert.is_nil(combo:current_step()) + assert.is_nil(combo:current_step_id()) + assert.same({ 1 }, combo:next_steps_ids()) + assert.same({ 1 }, steps_ids(combo:next_steps())) + + do + assert.is_true(combo:progress(ability1)) + + local step = combo:current_step() + + assert.equal(State.Started, combo.state) + assert.equal(1, combo.metrics.count) + assert.is_not_nil(step) --- @cast step invk.combo.ComboStep + assert.same(1, step.id) + assert.equal(1, combo:current_step_id()) + assert.same({ 2, 3 }, combo:next_steps_ids()) + assert.same({ 2, 3 }, steps_ids(combo:next_steps())) + end + + do + assert.is_true(combo:progress(ability2)) + + local step = combo:current_step() + + assert.equal(State.Started, combo.state) + assert.equal(2, combo.metrics.count) + assert.is_not_nil(step) --- @cast step invk.combo.ComboStep + assert.same(2, step.id) + assert.equal(2, combo:current_step_id()) + assert.same({ 3 }, combo:next_steps_ids()) + assert.same({ 3 }, steps_ids(combo:next_steps())) + end + + do + assert.is_true(combo:progress(ability3)) + + local step = combo:current_step() + + assert.equal(State.Started, combo.state) + assert.equal(3, combo.metrics.count) + assert.is_not_nil(step) --- @cast step invk.combo.ComboStep + assert.same(3, step.id) + assert.equal(3, combo:current_step_id()) + assert.same({}, combo:next_steps_ids()) + assert.same({}, steps_ids(combo:next_steps())) + end + end) + + it("enables skipping optional steps", function() + assert.is_true(combo:progress(ability1)) + assert.is_true(combo:progress(ability3)) + end) + end) + + describe("with invalid abilities", function() + local invalid_ability = F.ability({ + name = "invalid", + AbilityDuration = 0.5, + }) + + it("does NOT progress the combo", function() + assert.equal(State.Initial, combo.state) + assert.equal(0, combo.metrics.count) + assert.is_nil(combo:current_step()) + assert.is_nil(combo:current_step_id()) + assert.same({ 1 }, combo:next_steps_ids()) + assert.same({ 1 }, steps_ids(combo:next_steps())) + + assert.is_false(combo:progress(invalid_ability)) + + assert.equal(State.Initial, combo.state) + assert.equal(0, combo.metrics.count) + assert.is_nil(combo:current_step()) + assert.is_nil(combo:current_step_id()) + assert.same({ 1 }, combo:next_steps_ids()) + assert.same({ 1 }, steps_ids(combo:next_steps())) + + do + assert.is_true(combo:progress(ability1)) + + local step = combo:current_step() + + assert.equal(State.Started, combo.state) + assert.equal(1, combo.metrics.count) + assert.is_table(step) --- @cast step invk.combo.ComboStep + assert.same(1, step.id) + assert.equal(1, combo:current_step_id()) + assert.same({ 2, 3 }, combo:next_steps_ids()) + assert.same({ 2, 3 }, steps_ids(combo:next_steps())) + end + + do + assert.is_false(combo:progress(invalid_ability)) + + local step = combo:current_step() + + assert.equal(State.Started, combo.state) + assert.equal(1, combo.metrics.count) + assert.is_table(step) --- @cast step invk.combo.ComboStep + assert.same(1, step.id) + assert.equal(1, combo:current_step_id()) + assert.same({ 2, 3 }, combo:next_steps_ids()) + assert.same({ 2, 3 }, steps_ids(combo:next_steps())) + end + end) + end) + end) + + describe(":fail", function() + it("flags the combo as failed", function() + assert.equal(State.Initial, combo.state) + + combo:fail() + + assert.equal(State.Failed, combo.state) + end) + end) + + describe(":pre_finish", function() + it("advances the combo to pre-finished state", function() + assert.is_false(combo:pre_finish()) + assert.are_not_equal(State.PreFinished, combo.state) + + assert.is_true(combo:progress(ability1)) + assert.is_false(combo:pre_finish()) + assert.are_not_equal(State.PreFinished, combo.state) + + assert.is_true(combo:progress(ability2)) + assert.is_false(combo:pre_finish()) + assert.are_not_equal(State.PreFinished, combo.state) + + assert.is_true(combo:progress(ability3)) + assert.is_true(combo:pre_finish()) + assert.equal(State.PreFinished, combo.state) + end) + + it("sets the wait times", function() + local spy_wait_finish = spy.on(combo.wait, "finish") + + assert.is_true(combo:progress(ability1)) + assert.is_true(combo:progress(ability2)) + assert.is_true(combo:progress(ability3)) + assert.is_true(combo:pre_finish()) + + assert.spy(spy_wait_finish).called(1) + end) + end) + + describe(":finish", function() + it("advances the combo to finished state", function() + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + + assert.is_true(combo:progress(ability1)) + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + + assert.is_true(combo:progress(ability2)) + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + + assert.is_true(combo:progress(ability3)) + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + + assert.is_true(combo:pre_finish()) + assert.is_true(combo:finish()) + assert.equal(State.Finished, combo.state) + end) + + it("sets the combo duration", function() + assert.is_true(combo:progress(ability1)) + assert.is_true(combo:progress(ability2)) + assert.is_true(combo:progress(ability3)) + assert.is_true(combo:pre_finish()) + assert.is_true(combo:finish()) + assert.equal(7, combo.metrics.duration) + end) + end) +end) diff --git a/spec/combo/combo_step_spec.lua b/spec/combo/combo_step_spec.lua new file mode 100644 index 0000000..8e923c5 --- /dev/null +++ b/spec/combo/combo_step_spec.lua @@ -0,0 +1,70 @@ +local assert = require("luassert") + +local ComboStep = require("invk.combo.combo_step") + +describe("invk.combo.ComboStep", function() + --- @type invk.combo.ComboStepSpec + local data = { + id = 1, + name = "step_name", + required = true, + next = { 2, 3 }, + } + + --- @type invk.combo.ComboStep + local step + + before_each(function() + step = ComboStep:new(data) + end) + + describe(".gen_state_name", function() + it("generates a state name", function() + assert.equal("1:step_name", ComboStep.gen_state_name(step)) + + step.id = 2 + + assert.equal("2:step_name", ComboStep.gen_state_name(step)) + + step.id = 3 + step.name = "another_step" + + assert.equal("3:another_step", ComboStep.gen_state_name(step)) + end) + end) + + describe(".gen_event_name", function() + it("generates an event name", function() + assert.equal("step_name", ComboStep.gen_event_name(step)) + + step.name = "another_step" + + assert.equal("another_step", ComboStep.gen_event_name(step)) + end) + end) + + describe(".extract_step_id", function() + describe("with valid state name", function() + it("extracts a numeric step id from a state name", function() + assert.equal(13, ComboStep.extract_step_id("13:step_name")) + assert.equal(31, ComboStep.extract_step_id("31:another_step")) + assert.equal(44, ComboStep.extract_step_id("44:yet_another_step")) + end) + end) + + describe("with an invalid state name", function() + it("returns nil", function() + assert.is_nil(ComboStep.extract_step_id("invalid_state_name")) + assert.is_nil(ComboStep.extract_step_id("invalid:state_name")) + assert.is_nil(ComboStep.extract_step_id("0.5:state_name")) + end) + end) + end) + + describe("constructor", function() + it("initializes attributes", function() + assert.equal(ComboStep.gen_state_name(step), step.state) + assert.equal(ComboStep.gen_event_name(step), step.event) + end) + end) +end) diff --git a/spec/combo/combos_spec.lua b/spec/combo/combos_spec.lua new file mode 100644 index 0000000..4dc88c6 --- /dev/null +++ b/spec/combo/combos_spec.lua @@ -0,0 +1,733 @@ +local assert = require("luassert") +local m = require("moses") +local match = require("luassert.match") + +local F = require("support.factory") +local Mock = require("support.mock") + +local BaseCombo = require("invk.combo.base_combo") +local COMBOS = require("invk.const.combos") +local Combo = require("invk.combo.combo") +local Combos = require("invk.combo.combos") +local DamageInstance = require("invk.dota2.damage_instance") +local FreestyleCombo = require("invk.combo.freestyle_combo") +local INVOKER = require("invk.const.invoker") +local NET_TABLE = require("invk.const.net_table") +local S = require("invk.combo.spec") +local UNITS = require("invk.const.units") +local Unit = require("invk.dota2.unit") +local combo_comms = require("invk.combo.communication") +local combo_hero = require("invk.combo.hero") +local combo_sound = require("invk.combo.sound") +local talents = require("invk.dota2.talents") + +local AbilityName = INVOKER.AbilityName +local Talents = talents.Talents +local State = BaseCombo.State + +local NET_TABLE_CFG = NET_TABLE.Tables[NET_TABLE.Name.MAIN] + +describe("invk.combo.Combos", function() + local mocks = Mock() + --- @type invk.combo.Combos + local combos + local net_table = { keys = NET_TABLE_CFG.keys } + local dummy_spawn = F.dota_entity({ name = "dummy_spawn" }) + local hero_ent = F.dota_hero_invoker() + local player_ent = F.dota_player({ hero = hero_ent }) + local player_id = player_ent:GetPlayerID() + --- @type invk.combo.PlayerState + local player_state + + setup(function() + mocks:stub("Entities", Entities, "FindByName", function(_, _, name) + return name == UNITS.DUMMY_TARGET_SPAWN and dummy_spawn or nil + end) + end) + + teardown(function() + mocks:reset() + end) + + before_each(function() + mocks:stub("net_table", net_table, "set") + + combos = Combos:new(net_table) + + combos.state[player_id] = {} + player_state = combos.state[player_id] + end) + + after_each(function() + mocks:reset("net_table", "set") + end) + + describe("constructor", function() + it("loads and transforms specs", function() + assert.equal(m.count(COMBOS), m.count(combos.specs)) + + for _, spec in pairs(combos.specs) do + assert.is_table(spec) + assert.is_not_nil(spec.id) + + for _, step in pairs(spec.sequence) do + assert.is_table(step) + assert.is_not_nil(step.id) + end + end + end) + + it("sets NetTable key with loaded specs", function() + mocks:assert("net_table", "set").self.called_with(NET_TABLE_CFG.keys.COMBOS, combos.specs) + end) + end) + + describe(":create", function() + describe("with an invalid id", function() + it("throws an error", function() + assert.error(function() + combos:create(-1) + end, 'Combo "-1" not found') + end) + end) + + describe("with freestyle id", function() + it("creates a freestyle combo", function() + local combo = combos:create(BaseCombo.FREESTYLE_COMBO_ID) + + assert.is_not_nil(combo) + assert.is_true(combo:isInstanceOf(FreestyleCombo)) + end) + end) + + describe("with a valid id", function() + it("creates a combo", function() + local combo = combos:create(13) + + assert.is_not_nil(combo) + assert.is_true(combo:isInstanceOf(Combo)) + end) + end) + end) + + describe(":on_ability_used", function() + before_each(function() + mocks:stub("combos", combos, "capture_ability") + mocks:stub("combos", combos, "on_progress") + end) + + after_each(function() + mocks:reset("combos", "capture_ability", "on_progress") + end) + + local unit = Unit:new(hero_ent) + + describe("with relevant ability", function() + local ability = F.ability({ name = AbilityName.SUN_STRIKE }) + + it("handles ability capture and combo progress", function() + combos:on_ability_used(player_ent, unit, ability) + + mocks:assert("combos", "capture_ability").self.called_with(player_ent, ability) + mocks:assert("combos", "on_progress").self.called_with(player_ent, ability) + end) + end) + + describe("with ignored ability", function() + local ability = F.ability({ name = "item_phase_boots" }) + + it("is a noop", function() + combos:on_ability_used(player_ent, unit, ability) + + mocks:assert("combos", "capture_ability").called(0) + mocks:assert("combos", "on_progress").called(0) + end) + end) + end) + + describe(":on_entity_hurt", function() + before_each(function() + mocks:stub("combos", combos, "on_progress_damage") + end) + + after_each(function() + mocks:reset("combos", "on_progress_damage") + end) + + local victim = F.unit({ name = UNITS.DUMMY_TARGET }) + + describe("with player-owned attacker", function() + local attacker = F.hero_invoker({ player_owner = player_ent }) + local inflictor = F.ability({ name = AbilityName.SUN_STRIKE }) + + it("handles combo damage progress", function() + local damage = DamageInstance:new(victim, 123.4, attacker, inflictor) + local owner = damage:attacker_player_owner() + + combos:on_entity_hurt(damage) + + mocks:assert("combos", "on_progress_damage").self.called_with(owner, damage) + end) + end) + + describe("with non-player attacker", function() + local attacker = F.unit({ name = "npc_dota_hero_axe" }) + local inflictor = F.ability({ name = "item_dagon_5" }) + + it("is a noop", function() + local damage = DamageInstance:new(victim, 123.4, attacker, inflictor) + + combos:on_entity_hurt(damage) + + mocks:assert("combos", "on_progress_damage").called(0) + end) + end) + end) + + describe(":on_item_purchased", function() + local purchase = { item = "item_blink", cost = 12345 } + + describe("when no combo is active", function() + it("is a noop", function() + hero_ent:SetGold(0, true) + hero_ent:SetGold(0, false) + + assert.equal(0, hero_ent:GetGold()) + + combos:on_item_purchased(player_ent, purchase) + + assert.equal(0, hero_ent:GetGold()) + end) + end) + + describe("when a regular combo is active", function() + it("is a noop", function() + combos:on_start(player_ent, combos:create(1)) + hero_ent:SetGold(0, true) + hero_ent:SetGold(0, false) + + assert.equal(0, hero_ent:GetGold()) + + combos:on_item_purchased(player_ent, purchase) + + assert.equal(0, hero_ent:GetGold()) + end) + end) + + describe("when freestyle combo is active", function() + it("refunds the purchase", function() + combos:on_start(player_ent, combos:create(BaseCombo.FREESTYLE_COMBO_ID)) + hero_ent:SetGold(0, true) + hero_ent:SetGold(0, false) + + assert.equal(0, hero_ent:GetGold()) + + combos:on_item_purchased(player_ent, purchase) + + assert.equal(12345, hero_ent:GetGold()) + end) + end) + end) + + describe(":on_start", function() + before_each(function() + mocks:spy("combo_comms", combo_comms, { "send_started", "send_stopped" }) + mocks:spy("combo_hero", combo_hero, { "setup", "teardown" }) + mocks:spy( + "combo_sound", + combo_sound, + { "on_dummy_create", "on_combo_start", "on_combo_stop" } + ) + end) + + after_each(function() + mocks:reset("combo_comms", "send_started", "send_stopped") + mocks:reset("combo_hero", "setup", "teardown") + mocks:reset("combo_sound", "on_dummy_create", "on_combo_start", "on_combo_stop") + end) + + describe("when no combo is active", function() + it("starts the combo", function() + assert.is_nil(player_state.combo) + + combos:on_start(player_ent, combos:create(13)) + + local combo = player_state.combo + local dummy = player_state.dummy + + assert.is_not_nil(combo) --- @cast combo invk.combo.Combo + assert.is_not_nil(dummy) --- @cast dummy invk.dota2.DummyTarget + + assert.equal(13, combo.id) + assert.is_true(dummy:is_alive()) + + mocks + :assert("combo_hero", "teardown") + .called_with(match.is_ref(player_ent), { hard_reset = true }) + mocks + :assert("combo_hero", "setup") + .called_with(match.is_ref(player_ent), match.is_ref(combo)) + mocks:assert("combo_sound", "on_dummy_create").called_with(match.is_ref(dummy)) + mocks:assert("combo_sound", "on_combo_stop").called(0) + mocks:assert("combo_sound", "on_combo_start").called_with(match.is_ref(player_ent)) + mocks + :assert("combo_comms", "send_started") + .called_with(match.is_ref(player_ent), match.is_ref(combo)) + mocks:assert("combo_comms", "send_stopped").called(0) + end) + end) + + describe("when the same combo is already active", function() + it("restarts the combo", function() + combos:on_start(player_ent, combos:create(13)) + + local combo_before = player_state.combo + + assert.is_not_nil(combo_before) --- @cast combo_before invk.combo.Combo + assert.equal(13, combo_before.id) + + mocks:clear("combo_comms", "send_started", "send_stopped") + mocks:clear("combo_hero", "setup", "teardown") + mocks:clear("combo_sound", "on_dummy_create", "on_combo_start", "on_combo_stop") + + combos:on_start(player_ent, combos:create(13)) + + local combo_after = player_state.combo + local dummy = player_state.dummy + + assert.is_not_nil(combo_after) --- @cast combo_after invk.combo.Combo + assert.is_not_nil(dummy) --- @cast dummy invk.dota2.DummyTarget + + assert.are_not_equal(combo_after, combo_before) + assert.equal(13, combo_after.id) + assert.is_true(dummy:is_alive()) + + mocks + :assert("combo_hero", "teardown") + .called_with(match.is_ref(player_ent), { hard_reset = false }) + mocks + :assert("combo_hero", "setup") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_sound", "on_dummy_create").not_called_with(match.is_ref(dummy)) + mocks:assert("combo_sound", "on_combo_stop").called(0) + mocks:assert("combo_sound", "on_combo_start").called_with(match.is_ref(player_ent)) + mocks + :assert("combo_comms", "send_started") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_comms", "send_stopped").called(0) + end) + end) + + describe("when a different combo is already active", function() + it("stops the previous combo and starts the new combo", function() + combos:on_start(player_ent, combos:create(13)) + + local combo_before = player_state.combo + + assert.is_not_nil(combo_before) --- @cast combo_before invk.combo.Combo + assert.equal(13, combo_before.id) + + mocks:clear("combo_comms", "send_started", "send_stopped") + mocks:clear("combo_hero", "setup", "teardown") + mocks:clear("combo_sound", "on_dummy_create", "on_combo_start", "on_combo_stop") + + combos:on_start(player_ent, combos:create(3)) + + local combo_after = player_state.combo + local dummy = player_state.dummy + + assert.is_not_nil(combo_after) --- @cast combo_after invk.combo.Combo + assert.is_not_nil(dummy) --- @cast dummy invk.dota2.DummyTarget + + assert.are_not_equal(combo_after, combo_before) + assert.equal(3, combo_after.id) + assert.is_true(dummy:is_alive()) + + mocks + :assert("combo_hero", "teardown") + .called_with(match.is_ref(player_ent), { hard_reset = true }) + mocks + :assert("combo_hero", "setup") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_sound", "on_dummy_create").not_called_with(match.is_ref(dummy)) + mocks:assert("combo_sound", "on_combo_stop").called_with(match.is_ref(player_ent)) + mocks:assert("combo_sound", "on_combo_start").called_with(match.is_ref(player_ent)) + mocks + :assert("combo_comms", "send_started") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks + :assert("combo_comms", "send_stopped") + .called_with(match.is_ref(player_ent), match.is_ref(combo_before)) + end) + end) + end) + + describe(":on_stop", function() + before_each(function() + mocks:spy("combo_hero", combo_hero, "teardown") + mocks:spy("combo_sound", combo_sound, "on_combo_stop") + mocks:spy("combo_comms", combo_comms, "send_stopped") + end) + + after_each(function() + mocks:reset("combo_hero", "teardown") + mocks:reset("combo_sound", "on_combo_stop") + mocks:reset("combo_comms", "send_stopped") + end) + + describe("when no combo is active", function() + it("throws an error", function() + assert.error(function() + combos:on_stop(player_ent) + end, "Player 13 has no active combo") + + mocks:assert("combo_hero", "teardown").called(0) + mocks:assert("combo_sound", "on_combo_stop").called(0) + mocks:assert("combo_comms", "send_stopped").called(0) + end) + end) + + describe("when a combo is active", function() + it("stops the active combo", function() + combos:on_start(player_ent, combos:create(13)) + + local combo_before = player_state.combo + local dummy_before = player_state.dummy + + assert.is_not_nil(combo_before) --- @cast combo_before invk.combo.Combo + assert.is_not_nil(dummy_before) --- @cast dummy_before invk.dota2.DummyTarget + assert.equal(13, combo_before.id) + assert.is_true(dummy_before:is_alive()) + + mocks:clear("combo_hero", "teardown") + mocks:clear("combo_sound", "on_combo_stop") + mocks:clear("combo_comms", "send_stopped") + + combos:on_stop(player_ent) + + local combo_after = player_state.combo + local dummy_after = player_state.dummy + + assert.is_nil(combo_after) --- @cast combo_after invk.combo.Combo + assert.is_not_nil(dummy_after) --- @cast dummy_after invk.dota2.DummyTarget + assert.equal(dummy_before, dummy_after) + assert.is_false(dummy_after:is_alive()) + + mocks + :assert("combo_hero", "teardown") + .called_with(match.is_ref(player_ent), { hard_reset = true }) + mocks:assert("combo_sound", "on_combo_stop").called_with(match.is_ref(player_ent)) + mocks + :assert("combo_comms", "send_stopped") + .called_with(match.is_ref(player_ent), match.is_ref(combo_before)) + end) + end) + end) + + describe(":on_restart", function() + before_each(function() + mocks:spy("combo_comms", combo_comms, { "send_started", "send_stopped" }) + mocks:spy("combo_hero", combo_hero, { "setup", "teardown" }) + mocks:spy( + "combo_sound", + combo_sound, + { "on_dummy_create", "on_combo_start", "on_combo_stop" } + ) + end) + + after_each(function() + mocks:reset("combo_comms", "send_started", "send_stopped") + mocks:reset("combo_hero", "setup", "teardown") + mocks:reset("combo_sound", "on_dummy_create", "on_combo_start", "on_combo_stop") + end) + + describe("when no combo is active", function() + it("throws an error", function() + local restart_fn = m.bindn(combos.on_restart, combos, player_ent) + + assert.error(restart_fn, "Player 13 has no active combo") + + mocks:assert("combo_hero", "teardown").called(0) + mocks:assert("combo_hero", "setup").called(0) + mocks:assert("combo_sound", "on_dummy_create").called(0) + mocks:assert("combo_sound", "on_combo_start").called(0) + mocks:assert("combo_sound", "on_combo_stop").called(0) + mocks:assert("combo_comms", "send_started").called(0) + mocks:assert("combo_comms", "send_stopped").called(0) + end) + end) + + describe("when a combo is active", function() + describe("without hard reset option", function() + it("restarts the combo", function() + combos:on_start(player_ent, combos:create(13)) + + local combo_before = player_state.combo + + assert.is_not_nil(combo_before) --- @cast combo_before invk.combo.Combo + assert.equal(13, combo_before.id) + + mocks:clear("combo_comms", "send_started", "send_stopped") + mocks:clear("combo_hero", "setup", "teardown") + mocks:clear("combo_sound", "on_dummy_create", "on_combo_start", "on_combo_stop") + + combos:on_restart(player_ent, { hard_reset = false }) + + local combo_after = player_state.combo + local dummy = player_state.dummy + + assert.is_not_nil(combo_after) --- @cast combo_after invk.combo.Combo + assert.is_not_nil(dummy) --- @cast dummy invk.dota2.DummyTarget + + assert.are_not_equal(combo_after, combo_before) + assert.equal(13, combo_after.id) + assert.is_true(dummy:is_alive()) + + mocks + :assert("combo_hero", "teardown") + .called_with(match.is_ref(player_ent), { hard_reset = false }) + mocks + :assert("combo_hero", "setup") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_sound", "on_dummy_create").not_called_with(match.is_ref(dummy)) + mocks:assert("combo_sound", "on_combo_stop").called(0) + mocks:assert("combo_sound", "on_combo_start").called_with(match.is_ref(player_ent)) + mocks + :assert("combo_comms", "send_started") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_comms", "send_stopped").called(0) + end) + end) + + describe("with hard reset option", function() + it("restarts the combo", function() + combos:on_start(player_ent, combos:create(13)) + + local combo_before = player_state.combo + + assert.is_not_nil(combo_before) --- @cast combo_before invk.combo.Combo + assert.equal(13, combo_before.id) + + mocks:clear("combo_comms", "send_started", "send_stopped") + mocks:clear("combo_hero", "setup", "teardown") + mocks:clear("combo_sound", "on_dummy_create", "on_combo_start", "on_combo_stop") + + combos:on_restart(player_ent, { hard_reset = true }) + + local combo_after = player_state.combo + local dummy = player_state.dummy + + assert.is_not_nil(combo_after) --- @cast combo_after invk.combo.Combo + assert.is_not_nil(dummy) --- @cast dummy invk.dota2.DummyTarget + + assert.are_not_equal(combo_after, combo_before) + assert.equal(13, combo_after.id) + assert.is_true(dummy:is_alive()) + + mocks + :assert("combo_hero", "teardown") + .called_with(match.is_ref(player_ent), { hard_reset = true }) + mocks + :assert("combo_hero", "setup") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_sound", "on_dummy_create").not_called_with(match.is_ref(dummy)) + mocks:assert("combo_sound", "on_combo_stop").called(0) + mocks:assert("combo_sound", "on_combo_start").called_with(match.is_ref(player_ent)) + mocks + :assert("combo_comms", "send_started") + .called_with(match.is_ref(player_ent), match.is_ref(combo_after)) + mocks:assert("combo_comms", "send_stopped").called(0) + end) + end) + end) + end) + + describe(":on_progress", function() + --- @type invk.combo.Combo + local combo + + before_each(function() + --- @type invk.combo.ComboSpec + local combo_spec = { + id = m.uniqueId("Combos_spec-Progress-%d"), + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = S.DamageRating.Brutal, + difficulty_rating = S.DifficultyRating.LiterallyUnplayable, + hero_level = 25, + orbs = { 7, 7, 7 }, + talents = talents.select( + Talents.L10_LEFT, + Talents.L15_RIGHT, + Talents.L20_RIGHT, + Talents.L25_RIGHT + ), + gold = 1234, + items = { "item_blink" }, + tags = { "late-game" }, + sequence = { + { id = 1, name = AbilityName.COLD_SNAP, required = true, next = { 2, 3 } }, + { id = 2, name = AbilityName.GHOST_WALK, next = { 3 } }, + { id = 3, name = AbilityName.EMP, required = true }, + }, + } + + combo = Combo:new(combo_spec) + + mocks:spy("combos", combos, { "on_pre_finish", "on_fail" }) + mocks:spy( + "combo_comms", + combo_comms, + { "send_in_progress", "send_progress", "send_step_error" } + ) + end) + + after_each(function() + mocks:reset("combos", "on_pre_finish", "on_fail") + mocks:reset("combo_comms", "send_in_progress", "send_progress", "send_step_error") + end) + + describe("with no active combo", function() + it("does nothing", function() + combos:on_progress(player_ent, F.ability({ name = AbilityName.COLD_SNAP })) + + mocks:assert("combos", "on_pre_finish").called(0) + mocks:assert("combos", "on_fail").called(0) + mocks:assert("combo_comms", "send_in_progress").called(0) + mocks:assert("combo_comms", "send_progress").called(0) + mocks:assert("combo_comms", "send_step_error").called(0) + end) + end) + + describe("with failed combo", function() + it("does nothing", function() + combos:on_start(player_ent, combo) + combo:fail() + combos:on_progress(player_ent, F.ability({ name = AbilityName.COLD_SNAP })) + + mocks:assert("combos", "on_pre_finish").called(0) + mocks:assert("combos", "on_fail").called(0) + mocks:assert("combo_comms", "send_in_progress").called(0) + mocks:assert("combo_comms", "send_progress").called(0) + mocks:assert("combo_comms", "send_step_error").called(0) + end) + end) + + describe("with pre-finished combo", function() + it("does nothing", function() + combos:on_start(player_ent, combo) + + assert.is_true(combo:progress(F.ability({ name = AbilityName.COLD_SNAP }))) + assert.is_true(combo:progress(F.ability({ name = AbilityName.GHOST_WALK }))) + assert.is_true(combo:progress(F.ability({ name = AbilityName.EMP }))) + assert.is_true(combo:pre_finish()) + + assert.equal(State.PreFinished, combo.state) + + combos:on_progress(player_ent, F.ability({ name = AbilityName.COLD_SNAP })) + + mocks:assert("combos", "on_pre_finish").called(0) + mocks:assert("combos", "on_fail").called(0) + mocks:assert("combo_comms", "send_in_progress").called(0) + mocks:assert("combo_comms", "send_progress").called(0) + mocks:assert("combo_comms", "send_step_error").called(0) + end) + end) + + describe("with finished combo", function() + it("does nothing", function() + combos:on_start(player_ent, combo) + + assert.is_true(combo:progress(F.ability({ name = AbilityName.COLD_SNAP }))) + assert.is_true(combo:progress(F.ability({ name = AbilityName.GHOST_WALK }))) + assert.is_true(combo:progress(F.ability({ name = AbilityName.EMP }))) + assert.is_true(combo:pre_finish()) + assert.is_true(combo:finish()) + + assert.equal(State.Finished, combo.state) + + combos:on_progress(player_ent, F.ability({ name = AbilityName.COLD_SNAP })) + + mocks:assert("combos", "on_pre_finish").called(0) + mocks:assert("combos", "on_fail").called(0) + mocks:assert("combo_comms", "send_in_progress").called(0) + mocks:assert("combo_comms", "send_progress").called(0) + mocks:assert("combo_comms", "send_step_error").called(0) + end) + end) + + describe("with regular active combo", function() + before_each(function() + combos:on_start(player_ent, combo) + end) + + describe("with invocation ability", function() + it("does nothing", function() + combos:on_progress(player_ent, F.ability({ name = AbilityName.EXORT })) + + mocks:assert("combos", "on_pre_finish").called(0) + mocks:assert("combos", "on_fail").called(0) + mocks:assert("combo_comms", "send_in_progress").called(0) + mocks:assert("combo_comms", "send_progress").called(0) + mocks:assert("combo_comms", "send_step_error").called(0) + end) + end) + + describe("with incorrect ability", function() + local ability = F.ability({ name = AbilityName.SUN_STRIKE }) + + it("fails the combo", function() + combos:on_progress(player_ent, ability) + + assert.equal(State.Failed, combo.state) + + mocks + :assert("combos", "on_fail").self + .called_with(match.is_ref(player_ent), match.is_ref(ability)) + mocks:assert("combo_comms", "send_in_progress").called(0) + mocks:assert("combo_comms", "send_progress").called(0) + mocks:assert("combo_comms", "send_step_error").called_with(player_ent, combo, ability) + end) + end) + + describe("with correct ability", function() + it("progresses the combo", function() + combos:on_progress(player_ent, F.ability({ name = AbilityName.COLD_SNAP })) + + mocks:assert("combos", "on_pre_finish").called(0) + mocks:assert("combos", "on_fail").called(0) + mocks:assert("combo_comms", "send_step_error").called(0) + mocks + :assert("combo_comms", "send_progress") + .called_with(match.is_ref(player_ent), match.is_ref(combo)) + end) + + describe("when it's the first combo step", function() + it("communicates that combo is in progress", function() + local ability = F.ability({ name = AbilityName.COLD_SNAP }) + + combos:on_progress(player_ent, ability) + + mocks + :assert("combo_comms", "send_in_progress") + .called_with(match.is_ref(player_ent), match.is_ref(combo)) + end) + end) + + describe("when it's the last combo step", function() + it("pre-finishes the combo", function() + assert.is_true(combo:progress(F.ability({ name = AbilityName.COLD_SNAP }))) + assert.is_true(combo:progress(F.ability({ name = AbilityName.GHOST_WALK }))) + + combos:on_progress(player_ent, F.ability({ name = AbilityName.EMP })) + + assert.equal(State.PreFinished, combo.state) + + mocks:assert("combos", "on_pre_finish").self.called_with(match.is_ref(player_ent)) + mocks:assert("combos", "on_fail").called(0) + end) + end) + end) + end) + end) +end) diff --git a/spec/combo/communication_spec.lua b/spec/combo/communication_spec.lua new file mode 100644 index 0000000..8492b45 --- /dev/null +++ b/spec/combo/communication_spec.lua @@ -0,0 +1,194 @@ +local assert = require("luassert") + +local F = require("support.factory") +local Mock = require("support.mock") +local MockClock = require("support.dota2.clock") + +local CUSTOM_EVENTS = require("invk.const.custom_events") +local Combo = require("invk.combo.combo") +local S = require("invk.combo.spec") +local combo_comms = require("invk.combo.communication") +local custom_ev = require("invk.dota2.custom_events") +local talents = require("invk.dota2.talents") + +local Talents = talents.Talents + +--- @type invk.combo.ComboSpec +local SPEC = { + id = 13, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = S.DamageRating.None, + difficulty_rating = S.DifficultyRating.Easy, + gold = 1234, + items = { "item_blink" }, + hero_level = 30, + orbs = { 1, 2, 3 }, + talents = Talents.NONE, + tags = { "testing" }, + sequence = { { id = 1, name = "ability" } }, +} + +describe("invk.combo.communication", function() + --- @type invk.combo.Combo + local combo + --- @type support.dota2.MockClock + local clock = MockClock() + local player = F.dota_player() + local ability = F.ability({ name = "ability" }) + --- @type support.Mock + local mocks = Mock() + + before_each(function() + mocks:spy("custom_events", custom_ev, "send_player") + clock:reset() + + combo = Combo:new(SPEC, { clock = clock }) + end) + + after_each(function() + mocks:revert("custom_events", "send_player") + end) + + describe(".send_ability_used", function() + it("sends custom event", function() + --- @type invk.custom_events.CombatLogAbilityUsedPayload + local payload = { + ability = "ability", + } + + combo_comms.send_ability_used(player, ability) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBAT_LOG_ABILITY_USED, player, payload) + end) + end) + + describe(".send_started", function() + it("sends custom event", function() + --- @type invk.custom_events.ComboStartedPayload + local payload = { + id = 13, + next = { 1 }, + } + + combo_comms.send_started(player, combo) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_STARTED, player, payload) + end) + end) + + describe(".send_stopped", function() + it("sends custom event", function() + --- @type invk.custom_events.ComboStoppedPayload + local payload = { + id = 13, + } + + combo_comms.send_stopped(player, combo) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_STOPPED, player, payload) + end) + end) + + describe(".send_in_progress", function() + it("sends custom event", function() + --- @type invk.custom_events.ComboInProgressPayload + local payload = { + id = 13, + } + + combo_comms.send_in_progress(player, combo) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_IN_PROGRESS, player, payload) + end) + end) + + describe(".send_progress", function() + it("sends custom event", function() + assert.is_true(combo:progress(ability)) + assert.equal(123, combo:increment_damage(123)) + + --- @type invk.custom_events.ComboProgressPayload + local payload = { + id = 13, + metrics = { count = 1, damage = 123, duration = 0 }, + next = {}, + } + + combo_comms.send_progress(player, combo) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_PROGRESS, player, payload) + end) + end) + + describe(".send_step_error", function() + it("sends custom event", function() + --- @type invk.custom_events.ComboStepErrorPayload + local payload = { + id = 13, + expected = { 1 }, + ability = "ability", + } + + combo_comms.send_step_error(player, combo, ability) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_STEP_ERROR, player, payload) + end) + end) + + describe(".send_pre_finish", function() + it("sends custom event", function() + local ability_with_wait = F.ability({ name = "ability", AbilityDuration = 3.5 }) + + assert.is_true(combo:progress(ability_with_wait)) + assert.equal(123, combo:increment_damage(123)) + assert.is_true(combo:pre_finish()) + + --- @type invk.custom_events.ComboPreFinishPayload + local payload = { + id = 13, + metrics = { count = 1, damage = 123, duration = 0 }, + wait = 2.5, + } + + combo_comms.send_pre_finish(player, combo) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_PRE_FINISH, player, payload) + end) + end) + + describe(".send_finished", function() + it("sends custom event", function() + assert.is_true(combo:progress(ability)) + assert.equal(123, combo:increment_damage(123)) + assert.is_true(combo:pre_finish()) + assert.is_true(combo:finish()) + + --- @type invk.custom_events.ComboFinishedPayload + local payload = { + id = 13, + metrics = { count = 1, damage = 123, duration = 3 }, + } + + combo_comms.send_finished(player, combo) + + mocks + :assert("custom_events", "send_player") + .called_with(CUSTOM_EVENTS.EVENT_COMBO_FINISHED, player, payload) + end) + end) +end) diff --git a/spec/combo/freestyle_combo_spec.lua b/spec/combo/freestyle_combo_spec.lua new file mode 100644 index 0000000..92107ae --- /dev/null +++ b/spec/combo/freestyle_combo_spec.lua @@ -0,0 +1,200 @@ +local assert = require("luassert") + +local BaseCombo = require("invk.combo.base_combo") +local FreestyleCombo = require("invk.combo.freestyle_combo") + +local State = BaseCombo.State + +describe("invk.combo.FreestyleCombo", function() + --- @type invk.combo.FreestyleCombo + local combo + + before_each(function() + combo = FreestyleCombo:new() + end) + + it("inherits from BaseCombo", function() + assert.is_true(FreestyleCombo:isSubclassOf(BaseCombo)) + assert.is_true(combo:isInstanceOf(BaseCombo)) + end) + + describe("constructor", function() + it("initializes attributes", function() + assert.equal(BaseCombo.FREESTYLE_COMBO_ID, combo.id) + assert.equal(State.Started, combo.state) + assert.equal(0, combo.metrics.count) + assert.equal(0, combo.metrics.damage) + assert.equal(0, combo.metrics.duration) + end) + end) + + describe(":current_step_id", function() + local ability = { + is_invocation_ability = function() + return false + end, + } + + it("always returns nil", function() + assert.is_nil(combo:current_step_id()) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_nil(combo:current_step_id()) + end) + end) + + describe(":current_step", function() + local ability = { + is_invocation_ability = function() + return false + end, + } + + it("always returns nil", function() + assert.is_nil(combo:current_step()) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_nil(combo:current_step()) + end) + end) + + describe(":next_steps_ids", function() + local ability = { + is_invocation_ability = function() + return false + end, + } + + it("always returns an empty array", function() + assert.same({}, combo:next_steps_ids()) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.same({}, combo:next_steps_ids()) + end) + end) + + describe(":next_steps", function() + local ability = { + is_invocation_ability = function() + return false + end, + } + + it("always returns an empty array", function() + assert.same({}, combo:next_steps()) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.same({}, combo:next_steps()) + end) + end) + + describe(":progress", function() + describe("with invocation ability", function() + local ability = { + is_invocation_ability = spy.new(function() + return true + end), + } + + before_each(function() + ability.is_invocation_ability:clear() + end) + + it("returns false", function() + assert.is_false(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.spy(ability.is_invocation_ability).called(1) + end) + + it("does not update counter", function() + assert.is_false(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.spy(ability.is_invocation_ability).called(1) + assert.equal(0, combo.metrics.count) + end) + end) + + describe("with non-invocation ability", function() + local ability = { + is_invocation_ability = spy.new(function() + return false + end), + } + + before_each(function() + ability.is_invocation_ability:clear() + end) + + it("returns true", function() + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.spy(ability.is_invocation_ability).called(1) + end) + + it("increments counter", function() + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.equal(1, combo.metrics.count) + + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.equal(2, combo.metrics.count) + + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.equal(3, combo.metrics.count) + + assert.spy(ability.is_invocation_ability).called(3) + end) + end) + end) + + describe(":fail", function() + local ability = { + is_invocation_ability = function() + return true + end, + } + + it("is a no-op", function() + assert.are_not_equal(State.Failed, combo.state) + assert.is_nil(combo:fail()) + assert.are_not_equal(State.Failed, combo.state) + assert.is_false(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_nil(combo:fail()) + assert.are_not_equal(State.Failed, combo.state) + end) + end) + + describe(":pre_finish", function() + local ability = { + is_invocation_ability = function() + return false + end, + } + + it("always returns false", function() + assert.are_not_equal(State.PreFinished, combo.state) + assert.is_false(combo:pre_finish()) + assert.are_not_equal(State.PreFinished, combo.state) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_false(combo:pre_finish()) + assert.are_not_equal(State.PreFinished, combo.state) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_false(combo:pre_finish()) + assert.are_not_equal(State.PreFinished, combo.state) + end) + end) + + describe(":finish", function() + local ability = { + is_invocation_ability = function() + return false + end, + } + + it("always returns false", function() + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + assert.is_true(combo:progress(ability --[[@as invk.dota2.Ability]])) + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + assert.is_false(combo:pre_finish()) + assert.is_false(combo:finish()) + assert.are_not_equal(State.Finished, combo.state) + end) + end) +end) diff --git a/spec/combo/hero_spec.lua b/spec/combo/hero_spec.lua new file mode 100644 index 0000000..9c67314 --- /dev/null +++ b/spec/combo/hero_spec.lua @@ -0,0 +1,423 @@ +local assert = require("luassert") +local m = require("moses") +local spy = require("luassert.spy") + +local F = require("support.factory") +local Mock = require("support.mock") +local dota2_h = require("support.dota2.helpers") + +local Combo = require("invk.combo.combo") +local INVOKER = require("invk.const.invoker") +local LIMITS = require("invk.const.limits") +local S = require("invk.combo.spec") +local SOUND_EVENTS = require("invk.const.sound_events") +local combo_hero = require("invk.combo.hero") +local talents = require("invk.dota2.talents") + +local AbilityName = INVOKER.AbilityName +local Talents = talents.Talents + +describe("invk.combo.hero", function() + describe(".setup", function() + --- @type invk.combo.ComboSpec + local combo_spec = { + id = 13, + specialty = S.Specialty.QuasWex, + stance = S.Stance.Defensive, + damage_rating = S.DamageRating.Brutal, + difficulty_rating = S.DifficultyRating.LiterallyUnplayable, + hero_level = 6, + orbs = { 7, 7, 7 }, + talents = talents.select( + Talents.L10_LEFT, + Talents.L15_RIGHT, + Talents.L20_RIGHT, + Talents.L25_RIGHT + ), + gold = 1300, + items = { + "item_travel_boots", + "item_black_king_bar", + "item_shivas_guard", + "item_refresher", + "item_octarine_core", + "item_ultimate_scepter", + }, + tags = { "testing" }, + sequence = { + { id = 1, name = "ability" }, + }, + } + + local combo = Combo:new(combo_spec) + + it("runs the combo setup", function() + local unit = F.hero_invoker() + local hero = unit.entity --[[@as support.dota2.CDOTA_BaseNPC_Hero]] + local player = F.dota_player({ hero = hero }) + + combo_hero.setup(player, combo) + + assert.equal(6, hero:GetLevel()) + assert.equal(1300, hero:GetGold()) + assert.same(m.sort(combo.items), unit:item_names({ sort = true })) + end) + + describe("when hero already has some items", function() + it("gives the hero only the missing items", function() + local unit = F.hero_invoker(nil, { items = { "item_shivas_guard", "item_refresher" } }) + local player = F.dota_player({ hero = unit.entity }) + + combo_hero.setup(player, combo) + + assert.same(m.sort(combo.items), unit:item_names({ sort = true })) + end) + end) + end) + + describe(".teardown", function() + local mocks = Mock() + --- @type CDOTA_Item[] + local dropped_items = {} + + before_each(function() + dropped_items = {} + + mocks:stub("GameRules", GameRules, "NumDroppedItems", function() + return #dropped_items + end) + + mocks:stub("GameRules", GameRules, "GetDroppedItem", function(_, i) + return dropped_items[i + 1] + end) + end) + + after_each(function() + mocks:reset() + end) + + it("stops currently playing sounds on the hero", function() + local hero = F.dota_hero_invoker() + local player = F.dota_player({ hero = hero }) + + mocks:spy("hero", hero, "StopSound") + + combo_hero.teardown(player) + + mocks:assert("hero", "StopSound").self.called_with(SOUND_EVENTS.SNDEVT_INVOKER_METEOR_LOOP) + end) + + it("resets hero abilities cooldowns", function() + local unit = F.hero_invoker() + local player = F.dota_player({ hero = unit.entity }) + --- @type luassert.spy[] + local spies = {} + + unit:for_each_ability(function(ability) + spies[#spies + 1] = spy.on(ability, "EndCooldown") + end) + + assert.is_false(m.isEmpty(spies)) + + combo_hero.teardown(player) + + for _, s in ipairs(spies) do + assert.spy(s).self.called() + end + end) + + it("resets hero items cooldowns", function() + local unit = F.hero_invoker(nil, { items = { "item_shivas_guard", "item_refresher" } }) + local hero = unit.entity + + assert.is_false(m.isEmpty(hero.inventory)) + + local player = F.dota_player({ hero = hero }) + --- @type luassert.spy[] + local spies = {} + + unit:for_each_item(function(item) + spies[#spies + 1] = spy.on(item, "EndCooldown") + end) + + assert.is_false(m.isEmpty(spies)) + + combo_hero.teardown(player) + + for _, s in ipairs(spies) do + assert.spy(s).self.called() + end + end) + + describe("with dropped items", function() + local hero = F.dota_hero_invoker() + local player = F.dota_player({ hero = hero }) + + dropped_items = { + F.dota_item({ name = "item_blink", purchaser = hero }), + F.dota_item({ name = "item_refresher", purchaser = hero }), + F.dota_item({ name = "item_travel_boots", purchaser = hero }), + } + + it("removes dropped items owned by the hero", function() + --- @type { [CDOTA_Item]: luassert.spy } + local item_spies = m.map(dropped_items, function(item) + return item, spy.on(item, "RemoveSelf") + end) + + combo_hero.teardown(player) + + for item, spy in pairs(item_spies) do + assert.spy(spy).self.called() + assert.is_true(item:IsNull()) + end + end) + end) + + describe("with spawned units by the hero", function() + local hero = F.dota_hero_invoker() + local player = F.dota_player({ hero = hero }) + local units = {} + local unit_spies = {} + + for _, name in pairs(INVOKER.SPAWNED_UNITS) do + for _ = 0, 1 do + local unit = F.dota_unit({ name = name, player_owner = player }) + + units[name] = units[name] or {} + units[name][#units[name] + 1] = unit + + unit_spies[name] = unit_spies[name] or {} + unit_spies[name][unit] = { RemoveSelf = spy.on(unit, "RemoveSelf") } + end + end + + --- @type support.Mock + local units_mocks = Mock() + + before_each(function() + units_mocks:stub("Entities", Entities, "FindByName", function(_, start_ent, name) + local ent_idx = start_ent and start_ent:GetEntityIndex() or 0 + + local unit_idx = m.findIndex(units[name], function(unit) + return unit:GetEntityIndex() > ent_idx + end) + + return units[name][unit_idx] + end) + end) + + after_each(function() + units_mocks:reset() + end) + + it("removes spawned units by the hero", function() + combo_hero.teardown(player) + + for _, group in pairs(unit_spies) do + for unit, spies in pairs(group) do + assert.spy(spies.RemoveSelf).self.called_with() + assert.is_true(unit:IsNull()) + end + end + end) + end) + + describe("with soft reset", function() + it("purges the hero", function() + local hero = F.dota_hero_invoker() + local player = F.dota_player({ hero = hero }) + + mocks:spy("hero", hero, "Purge") + + combo_hero.teardown(player) + + mocks:assert("hero", "Purge").self.called_with(true, true, false, true, true) + end) + + it("heals the hero to max health", function() + local hero = F.dota_hero_invoker({ max_health = 1000.0, health = 301.25 }) + local player = F.dota_player({ hero = hero }) + + assert.equal(301.25, hero:GetHealth()) + + combo_hero.teardown(player) + + assert.equal(1000.0, hero:GetHealth()) + end) + + it("gives the hero max mana", function() + local hero = F.dota_hero_invoker({ max_mana = 1000.0, mana = 301.25 }) + local player = F.dota_player({ hero = hero }) + + assert.equal(301.25, hero:GetMana()) + + combo_hero.teardown(player) + + assert.equal(1000.0, hero:GetMana()) + end) + end) + + describe("with hard reset", function() + before_each(function() + mocks:stub("PlayerResource", PlayerResource, "ReplaceHeroWith") + end) + + after_each(function() + mocks:reset("PlayerResource", "ReplaceHeroWith") + end) + + it("removes all hero's items", function() + local hero = F.dota_hero_invoker(nil, { items = { "item_shivas_guard", "item_refresher" } }) + local player = F.dota_player({ hero = hero }) + + combo_hero.teardown(player, { hard_reset = true }) + + assert.same({}, hero.inventory) + end) + + it("resets hero abilities", function() + local abilities = { + [AbilityName.QUAS] = 7, + [AbilityName.WEX] = 4, + [AbilityName.EXORT] = 6, + [AbilityName.COLD_SNAP] = 1, + [AbilityName.SUN_STRIKE] = 1, + [AbilityName.TALENT_L10_RIGHT] = 1, + [AbilityName.TALENT_L10_LEFT] = 0, + [AbilityName.TALENT_L15_RIGHT] = 1, + [AbilityName.TALENT_L15_LEFT] = 0, + [AbilityName.TALENT_L20_RIGHT] = 1, + [AbilityName.TALENT_L20_LEFT] = 0, + [AbilityName.TALENT_L25_RIGHT] = 1, + [AbilityName.TALENT_L25_LEFT] = 0, + } + + local hero = F.dota_hero_invoker(nil, { abilities = abilities }) + local player = F.dota_player({ hero = hero }) + + combo_hero.teardown(player, { hard_reset = true }) + + for _, name in ipairs(INVOKER.ORB_ABILITIES) do + assert.equal(0, dota2_h.require_ability(hero, name):GetLevel()) + end + + for _, name in ipairs(INVOKER.TALENT_ABILITIES) do + assert.equal(0, dota2_h.require_ability(hero, name):GetLevel()) + end + + assert.equal(1, dota2_h.require_ability(hero, AbilityName.COLD_SNAP):GetLevel()) + assert.equal(1, dota2_h.require_ability(hero, AbilityName.SUN_STRIKE):GetLevel()) + assert.equal(1, hero:GetAbilityPoints()) + end) + + it("replaces hero with a new one", function() + local hero = F.dota_hero_invoker() + local player = F.dota_player({ player_id = 31, hero = hero }) + + mocks:spy("hero", hero, "RemoveSelf") + + combo_hero.teardown(player, { hard_reset = true }) + + mocks + :assert("PlayerResource", "ReplaceHeroWith").self + .called_with(31, INVOKER.UNIT_NAME, 0, 0) + mocks:assert("hero", "RemoveSelf").self.called() + assert.is_true(hero:IsNull()) + end) + end) + end) + + describe(".refund_purchase", function() + it("refunds a purchase", function() + local hero = F.dota_hero_invoker() + local player = F.dota_player({ hero = hero }) + local purchase = { item = "item_blink", cost = 12345 } + + hero:SetGold(0, true) + hero:SetGold(0, false) + + assert.equal(0, hero:GetGold()) + + combo_hero.refund_purchase(player, purchase) + + assert.equal(12345, hero:GetGold()) + end) + end) + + describe(".level_up", function() + local abilities = { + [AbilityName.QUAS] = 1, + [AbilityName.WEX] = 1, + [AbilityName.EXORT] = 1, + [AbilityName.COLD_SNAP] = 1, + [AbilityName.SUN_STRIKE] = 1, + } + + --- @type CDOTA_BaseNPC_Hero + local hero + --- @type CDOTAPlayerController + local player + + before_each(function() + hero = F.dota_hero_invoker({ level = 3, ability_points = 0 }, { abilities = abilities }) + player = F.dota_player({ hero = hero }) + end) + + describe("with specific level option", function() + it("levels up the player hero to the specified level", function() + assert.equal(3, hero:GetLevel()) + assert.equal(0, hero:GetAbilityPoints()) + + combo_hero.level_up(player, { level = 6 }) + + assert.equal(6, hero:GetLevel()) + assert.equal(3, hero:GetAbilityPoints()) + end) + end) + + describe("with empty level option", function() + it("levels up the player hero by one level", function() + assert.equal(3, hero:GetLevel()) + assert.equal(0, hero:GetAbilityPoints()) + + combo_hero.level_up(player) + + assert.equal(4, hero:GetLevel()) + assert.equal(1, hero:GetAbilityPoints()) + end) + end) + + describe("with max_level option", function() + it("levels up the player hero, abilities and talents to max level", function() + assert.equal(3, hero:GetLevel()) + assert.equal(0, hero:GetAbilityPoints()) + + -- selene: allow(global_usage) + local spy_hero_max_level = spy.on(_G, "HeroMaxLevel") + + combo_hero.level_up(player, { max_level = true }) + + assert.spy(spy_hero_max_level).called(1) + + assert.equal(LIMITS.MAX_HERO_LEVEL, hero:GetLevel()) + assert.equal(0, hero:GetAbilityPoints()) + + for _, name in ipairs(INVOKER.ORB_ABILITIES) do + local ability = dota2_h.require_ability(hero, name) + + assert.equal(ability:GetMaxLevel(), ability:GetLevel()) + end + + for _, name in ipairs(INVOKER.TALENT_ABILITIES) do + local ability = dota2_h.require_ability(hero, name) + + assert.equal(ability:GetMaxLevel(), ability:GetLevel()) + end + + assert.equal(1, dota2_h.require_ability(hero, AbilityName.COLD_SNAP):GetLevel()) + assert.equal(1, dota2_h.require_ability(hero, AbilityName.SUN_STRIKE):GetLevel()) + end) + end) + end) +end) diff --git a/spec/combo/sound_spec.lua b/spec/combo/sound_spec.lua new file mode 100644 index 0000000..88c78b7 --- /dev/null +++ b/spec/combo/sound_spec.lua @@ -0,0 +1,90 @@ +local F = require("support.factory") +local Mock = require("support.mock") + +local SOUND_EVENTS = require("invk.const.sound_events") +local combo_sound = require("invk.combo.sound") +local sound_ev = require("invk.dota2.sound_events") + +describe("invk.combo.sound", function() + local mocks = Mock() + local player = F.dota_player() + local entity = F.dota_entity({ name = "ent_dummy" }) + local dummy = { entity = entity } --- @cast dummy invk.dota2.DummyTarget + + before_each(function() + -- selene: allow(global_usage) + mocks:stub("_G", _G, "RandomInt", 1) + mocks:spy("sound_events", sound_ev, "emit_on_entity") + mocks:spy("sound_events", sound_ev, "emit_on_player") + mocks:spy("player", player, "SetMusicStatus") + end) + + after_each(function() + mocks:reset() + end) + + describe(".emit_random_event_on_entity", function() + it("emits random sound event on entity", function() + local events = { "a", "b", "c" } + + combo_sound.emit_random_event_on_entity(entity, events) + + mocks:assert("_G", "RandomInt").called_with(1, 3) + mocks:assert("sound_events", "emit_on_entity").called_with("a", entity) + end) + end) + + describe(".emit_random_event_on_player", function() + it("emits random sound event on player", function() + local events = { "a", "b", "c" } + + combo_sound.emit_random_event_on_player(player, events) + + mocks:assert("_G", "RandomInt").called_with(1, 3) + mocks:assert("sound_events", "emit_on_player").called_with("a", player) + end) + end) + + describe(".on_dummy_create", function() + it("emits random dummy create sound event on dummy entity", function() + combo_sound.on_dummy_create(dummy) + + mocks:assert("_G", "RandomInt").called_with(1, #SOUND_EVENTS.SNDEVTS_DUMMY_CREATE) + mocks + :assert("sound_events", "emit_on_entity") + .called_with(SOUND_EVENTS.SNDEVTS_DUMMY_CREATE[1], dummy.entity) + end) + end) + + describe(".on_combo_start", function() + it("sets the music status on the player", function() + combo_sound.on_combo_start(player) + + mocks:assert("player", "SetMusicStatus").called(1) + end) + end) + + describe(".on_combo_stop", function() + it("sets the music status on the player", function() + combo_sound.on_combo_stop(player) + + mocks:assert("player", "SetMusicStatus").called(1) + end) + end) + + describe(".on_combo_step_error", function() + it("sets the music status on the player", function() + combo_sound.on_combo_step_error(player) + + mocks:assert("player", "SetMusicStatus").called(1) + end) + end) + + describe(".on_combo_finished", function() + it("sets the music status on the player", function() + combo_sound.on_combo_finished(player) + + mocks:assert("player", "SetMusicStatus").called(1) + end) + end) +end) diff --git a/spec/combo/wait_spec.lua b/spec/combo/wait_spec.lua new file mode 100644 index 0000000..958f5d9 --- /dev/null +++ b/spec/combo/wait_spec.lua @@ -0,0 +1,121 @@ +local assert = require("luassert") + +local F = require("support.factory") +local MockClock = require("support.dota2.clock") + +local INVOKER = require("invk.const.invoker") +local Wait = require("invk.combo.wait") + +local AbilityName = INVOKER.AbilityName + +describe("invk.combo.Wait", function() + --- @type support.dota2.MockClock + local clock = MockClock(10, true) + --- @type invk.combo.Wait + local wait + + before_each(function() + wait = Wait:new(clock) + end) + + describe(":enqueue", function() + describe("with abilities without special wait values", function() + local ability1 = F.ability({ + name = "step1", + AbilityDuration = 0.5, + }) + + local ability2 = F.ability({ + name = "step2", + AbilityDuration = 0.3, + }) + + local ability3 = F.ability({ + name = "step3", + AbilityDuration = 0.25, + }) + + it("enqueues the abilities durations", function() + assert.same({}, wait.queue) + + wait:enqueue(ability1) + + assert.same({ 10.5 }, wait.queue) + + wait:enqueue(ability2) + + assert.same({ 10.5, 10.3 }, wait.queue) + + wait:enqueue(ability3) + + assert.same({ 10.5, 10.3, 10.25 }, wait.queue) + end) + end) + + describe("with abilities with special wait values", function() + local ability_alacrity = F.ability({ + name = AbilityName.ALACRITY, + AbilityDuration = 1.0, + special = { duration = 3.5 }, + }) + + local ability_cold_snap = F.ability({ + name = AbilityName.COLD_SNAP, + AbilityDuration = 2.0, + special = { duration = 1.25 }, + }) + + local ability_sun_strike = F.ability({ + name = AbilityName.SUN_STRIKE, + special = { delay = 2.6 }, + }) + + it("enqueues the abilities durations with special values", function() + assert.same({}, wait.queue) + + wait:enqueue(ability_alacrity) + + assert.same({ 14.5 }, wait.queue) + + wait:enqueue(ability_cold_snap) + + assert.same({ 14.5, 13.25 }, wait.queue) + + wait:enqueue(ability_sun_strike) + + assert.same({ 14.5, 13.25, 12.6 }, wait.queue) + end) + end) + end) + + describe(":finish", function() + local ability_alacrity = F.ability({ + name = AbilityName.ALACRITY, + AbilityDuration = 1.0, + special = { duration = 3.5 }, + }) + + local ability_cold_snap = F.ability({ + name = AbilityName.COLD_SNAP, + AbilityDuration = 2.0, + special = { duration = 1.25 }, + }) + + local ability_sun_strike = F.ability({ + name = AbilityName.SUN_STRIKE, + special = { delay = 2.6 }, + }) + + it("sets duration from max enqueued time, relative to the given base time", function() + wait:enqueue(ability_alacrity) + wait:enqueue(ability_cold_snap) + wait:enqueue(ability_sun_strike) + + assert.same({ 14.5, 13.25, 12.6 }, wait.queue) + + wait:finish(5.0) + + assert.equal(9.5, wait.duration) + end) + end) +end) diff --git a/spec/combos/BaseCombo_spec.lua b/spec/combos/BaseCombo_spec.lua deleted file mode 100644 index a1b99e8..0000000 --- a/spec/combos/BaseCombo_spec.lua +++ /dev/null @@ -1,108 +0,0 @@ -local m = require("moses") - -local Talents = require("invokation.dota2.talents") -local BaseCombo = require("invokation.combos.BaseCombo") - -local SPEC = { - id = 13, - specialty = "qw", - stance = "defensive", - heroLevel = 25, - damageRating = 5, - difficultyRating = 5, - gold = 1234, - tags = { "late-game" }, - items = { "item_blink" }, - orbs = { 7, 7, 7 }, - talents = Talents.Select(Talents.L10_LEFT, Talents.L15_RIGHT, Talents.L20_RIGHT, Talents.L25_RIGHT), -} - -describe("BaseCombo", function() - local combo - - before_each(function() - combo = BaseCombo(SPEC) - end) - - describe("constructor", function() - it("initializes attributes", function() - for key, value in pairs(SPEC) do - assert.same(value, combo[key]) - end - - assert.is_false(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.finished) - assert.equal(0, combo.count) - assert.equal(0, combo.damage) - end) - end) - - describe("#CurrentStepId", function() - it("raises an error", function() - local fn = m.partial(combo.CurrentStepId, combo) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - end) - end) - - describe("#CurrentStep", function() - it("raises an error", function() - local fn = m.partial(combo.CurrentStep, combo) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - end) - end) - - describe("#NextStepsIds", function() - it("raises an error", function() - local fn = m.partial(combo.NextStepsIds, combo) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - end) - end) - - describe("#NextSteps", function() - it("raises an error", function() - local fn = m.partial(combo.NextSteps, combo) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - end) - end) - - describe("#Progress", function() - it("raises an error", function() - local fn = m.partial(combo.Progress, combo, {}) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - end) - end) - - describe("#Fail", function() - it("flags the combo as failed", function() - assert.is_false(combo.failed) - combo:Fail() - assert.is_true(combo.failed) - end) - end) - - describe("#PreFinish", function() - it("raises an error", function() - local fn = m.partial(combo.PreFinish, combo) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - assert.is_false(combo.preFinished) - end) - end) - - describe("#Finish", function() - it("raises an error", function() - local fn = m.partial(combo.Finish, combo) - assert.error(fn, BaseCombo.ERR_NOT_IMPLEMENTED) - assert.is_false(combo.finished) - end) - end) - - describe("#IncrementDamage", function() - it("increments the damage accumulator and returns the accumulated value", function() - assert.equal(13, combo:IncrementDamage(13)) - assert.equal(13, combo.damage) - assert.equal(44, combo:IncrementDamage(31)) - assert.equal(44, combo.damage) - end) - end) -end) diff --git a/spec/combos/ComboSequence_spec.lua b/spec/combos/ComboSequence_spec.lua deleted file mode 100644 index 117691e..0000000 --- a/spec/combos/ComboSequence_spec.lua +++ /dev/null @@ -1,227 +0,0 @@ -local m = require("moses") - -local ComboStep = require("invokation.combos.ComboStep") -local ComboSequence = require("invokation.combos.ComboSequence") - -local STATES = ComboSequence.STATES - -describe("ComboSequence", function() - local steps = { - { id = 1, name = "step1", required = true, next = { 2, 3 } }, - { id = 2, name = "step2", next = { 3 } }, - { id = 3, name = "step3", required = true }, - } - - local clockIdx - local function clock() - clockIdx = clockIdx + 1 - return clockIdx - end - - local getId = m.property("id") - local function stepsIds(arr) - return m.map(arr, getId) - end - - local seq, seqId, spyClock - - before_each(function() - clockIdx = 0 - seqId = m.uniqueId() - spyClock = spy.new(clock) - seq = ComboSequence(seqId, steps, { clock = spyClock }) - end) - - describe("constructor", function() - it("initializes attributes", function() - assert.equal(seqId, seq.id) - assert.equal(spyClock, seq.clock) - assert.is_table(seq.sequence) - assert.is_true(m.all(seq.sequence, function(s) - return ComboStep:class_of(s) - end)) - end) - end) - - describe("#EnterTime", function() - it("returns the time when the sequence entered a state", function() - assert.is_true(seq:Progress("step1")) - assert.is_true(seq:Progress("step2")) - assert.is_true(seq:Progress("step3")) - assert.is_true(seq:PreFinish()) - assert.equal(4, seq:EnterTime(STATES.PRE_FINISH)) - assert.is_nil(seq:EnterTime(STATES.FINISH)) - assert.spy(seq.clock) - end) - - it("returns nil for an invalid state", function() - assert.is_true(seq:Progress("step1")) - assert.is_true(seq:Progress("step2")) - assert.is_true(seq:Progress("step3")) - assert.is_true(seq:PreFinish()) - assert.is_true(seq:Finish()) - assert.is_nil(seq:EnterTime("invalid")) - end) - end) - - describe("#LeaveTime", function() - it("returns the time when the sequence left a state", function() - assert.is_true(seq:Progress("step1")) - assert.is_true(seq:Progress("step2")) - assert.is_true(seq:Progress("step3")) - assert.is_true(seq:PreFinish()) - assert.is_true(seq:Finish()) - assert.equal(5, seq:LeaveTime(STATES.PRE_FINISH)) - assert.is_nil(seq:LeaveTime(STATES.FINISH)) - end) - - it("returns nil for an invalid state", function() - assert.is_true(seq:Progress("step1")) - assert.is_true(seq:Progress("step2")) - assert.is_true(seq:Progress("step3")) - assert.is_true(seq:PreFinish()) - assert.is_true(seq:Finish()) - assert.is_nil(seq:LeaveTime("invalid")) - end) - end) - - describe("#Progress", function() - describe("with a valid event", function() - it("progresses the sequence", function() - assert.is_nil(seq.current) - assert.is_nil(seq.currentId) - assert.same({ 1 }, seq.nextIds) - assert.same({ 1 }, stepsIds(seq.next)) - assert.is_nil(seq:EnterTime(STATES.INITIAL)) - assert.is_nil(seq:LeaveTime(STATES.INITIAL)) - - assert.is_true(seq:Progress("step1")) - - assert.same(1, seq.current.id) - assert.equal(1, seq.currentId) - assert.same({ 2, 3 }, seq.nextIds) - assert.same({ 2, 3 }, stepsIds(seq.next)) - assert.equal(1, seq:LeaveTime(STATES.INITIAL)) - - assert.is_true(seq:Progress("step2")) - - assert.same(2, seq.current.id) - assert.equal(2, seq.currentId) - assert.same({ 3 }, seq.nextIds) - assert.same({ 3 }, stepsIds(seq.next)) - - assert.is_true(seq:Progress("step3")) - - assert.same(3, seq.current.id) - assert.equal(3, seq.currentId) - assert.same({}, seq.nextIds) - assert.same({}, stepsIds(seq.next)) - - assert.is_true(seq:PreFinish()) - - assert.is_nil(seq.current) - assert.is_nil(seq.currentId) - assert.same({}, seq.nextIds) - assert.same({}, stepsIds(seq.next)) - assert.equal(4, seq:EnterTime(STATES.PRE_FINISH)) - - assert.is_true(seq:Finish()) - - assert.is_nil(seq.current) - assert.is_nil(seq.currentId) - assert.same({}, seq.nextIds) - assert.same({}, stepsIds(seq.next)) - assert.equal(5, seq:LeaveTime(STATES.PRE_FINISH)) - assert.equal(5, seq:EnterTime(STATES.FINISH)) - end) - - it("enables skipping optional steps", function() - assert.is_nil(seq.current) - assert.is_nil(seq.currentId) - assert.same({ 1 }, seq.nextIds) - assert.same({ 1 }, stepsIds(seq.next)) - assert.is_nil(seq:EnterTime(STATES.INITIAL)) - assert.is_nil(seq:LeaveTime(STATES.INITIAL)) - - assert.is_true(seq:Progress("step1")) - - assert.same(1, seq.current.id) - assert.equal(1, seq.currentId) - assert.same({ 2, 3 }, seq.nextIds) - assert.same({ 2, 3 }, stepsIds(seq.next)) - assert.equal(1, seq:LeaveTime(STATES.INITIAL)) - - assert.is_true(seq:Progress("step3")) - - assert.same(3, seq.current.id) - assert.equal(3, seq.currentId) - assert.same({}, seq.nextIds) - assert.same({}, stepsIds(seq.next)) - - assert.is_true(seq:PreFinish()) - - assert.is_nil(seq.current) - assert.is_nil(seq.currentId) - assert.same({}, seq.nextIds) - assert.same({}, stepsIds(seq.next)) - assert.equal(3, seq:EnterTime(STATES.PRE_FINISH)) - - assert.is_true(seq:Finish()) - - assert.is_nil(seq.current) - assert.is_nil(seq.currentId) - assert.same({}, seq.nextIds) - assert.same({}, stepsIds(seq.next)) - assert.equal(4, seq:LeaveTime(STATES.PRE_FINISH)) - assert.equal(4, seq:EnterTime(STATES.FINISH)) - end) - end) - - describe("with an invalid event", function() - it("does NOT progress the sequence", function() - assert.is_false(seq:Progress("invalid")) - assert.is_false(seq:Progress("step2")) - assert.is_true(seq:Progress("step1")) - assert.is_true(seq:Progress("step3")) - assert.is_false(seq:Progress("step1")) - assert.is_false(seq:Progress("step2")) - assert.is_false(seq:Progress("invalid")) - end) - end) - end) - - describe("#PreFinish", function() - it("pre-finishes the sequence", function() - assert.is_false(seq:PreFinish()) - assert.is_true(seq:Progress("step1")) - assert.is_false(seq:PreFinish()) - assert.is_true(seq:Progress("step2")) - assert.is_false(seq:PreFinish()) - assert.is_true(seq:Progress("step3")) - assert.is_true(seq:PreFinish()) - end) - end) - - describe("#Finish", function() - it("finishes the sequence", function() - assert.is_false(seq:Finish()) - assert.is_true(seq:Progress("step1")) - assert.is_false(seq:Finish()) - assert.is_true(seq:Progress("step2")) - assert.is_false(seq:Finish()) - assert.is_true(seq:Progress("step3")) - assert.is_false(seq:Finish()) - assert.is_true(seq:PreFinish()) - assert.is_true(seq:Finish()) - end) - - it("sets the duration", function() - assert.is_true(seq:Progress("step1")) - assert.is_true(seq:Progress("step2")) - assert.is_true(seq:Progress("step3")) - assert.is_true(seq:PreFinish()) - assert.is_true(seq:Finish()) - assert.equal(4, seq.duration) - end) - end) -end) diff --git a/spec/combos/ComboStep_spec.lua b/spec/combos/ComboStep_spec.lua deleted file mode 100644 index b81f5c1..0000000 --- a/spec/combos/ComboStep_spec.lua +++ /dev/null @@ -1,61 +0,0 @@ -local ComboStep = require("invokation.combos.ComboStep") - -describe("ComboStep", function() - local data = { id = 1, name = "step_name", required = true, next = { 2, 3 } } - - local step - - before_each(function() - step = ComboStep(data) - end) - - describe(".StateName", function() - it("generates a state name", function() - assert.equal("1:step_name", ComboStep.StateName(step)) - - step.id = 2 - - assert.equal("2:step_name", ComboStep.StateName(step)) - - step.id = 3 - step.name = "another_step" - - assert.equal("3:another_step", ComboStep.StateName(step)) - end) - end) - - describe(".EventName", function() - it("generates an event name", function() - assert.equal("step_name", ComboStep.EventName(step)) - - step.name = "another_step" - - assert.equal("another_step", ComboStep.EventName(step)) - end) - end) - - describe(".StepId", function() - describe("with valid state name", function() - it("extracts a numeric step id from a state name", function() - assert.equal(13, ComboStep.StepId("13:step_name")) - assert.equal(31, ComboStep.StepId("31:another_step")) - assert.equal(44, ComboStep.StepId("44:yet_another_step")) - end) - end) - - describe("with an invalid state name", function() - it("returns nil", function() - assert.is_nil(ComboStep.StepId("invalid_state_name")) - assert.is_nil(ComboStep.StepId("invalid:state_name")) - assert.is_nil(ComboStep.StepId("0.5:state_name")) - end) - end) - end) - - describe("constructor", function() - it("initializes attributes", function() - assert.equal(ComboStep.StateName(step), step.state) - assert.equal(ComboStep.EventName(step), step.event) - end) - end) -end) diff --git a/spec/combos/Combo_spec.lua b/spec/combos/Combo_spec.lua deleted file mode 100644 index 23f9207..0000000 --- a/spec/combos/Combo_spec.lua +++ /dev/null @@ -1,392 +0,0 @@ -local m = require("moses") -local create = require("support.factory").create - -local Combo = require("invokation.combos.Combo") -local Talents = require("invokation.dota2.talents") -local BaseCombo = require("invokation.combos.BaseCombo") -local ComboSequence = require("invokation.combos.ComboSequence") - -local INVOKER = require("invokation.const.invoker") - -local SPEC = { - id = 13, - specialty = "qw", - stance = "defensive", - heroLevel = 25, - damageRating = 5, - difficultyRating = 5, - gold = 1234, - tags = { "late-game" }, - items = { "item_blink" }, - orbs = { 7, 7, 7 }, - talents = Talents.Select(Talents.L10_LEFT, Talents.L15_RIGHT, Talents.L20_RIGHT, Talents.L25_RIGHT), - sequence = { - { id = 1, name = "step1", required = true, next = { 2, 3 } }, - { id = 2, name = "step2", next = { 3 } }, - { id = 3, name = "step3", required = true }, - }, -} - -describe("Combo", function() - local combo, spyClock - - local function clock() - return 10 - end - - local getId = m.property("id") - local function stepsIds(arr) - return m.map(arr, getId) - end - - local ability1 = create("ability", { name = "step1", AbilityDuration = 0.5 }) - local ability2 = create("ability", { name = "step2", AbilityDuration = 0.3 }) - local ability3 = create("ability", { name = "step3", AbilityDuration = 0.25 }) - - before_each(function() - spyClock = spy.new(clock) - combo = Combo(SPEC, { clock = spyClock }) - end) - - it("inherits from BaseCombo", function() - assert.is_true(BaseCombo:class_of(combo)) - end) - - describe("constructor", function() - it("initializes attributes", function() - for key, value in pairs(m.omit(SPEC, { "sequence" })) do - assert.same(SPEC[key], value) - end - - assert.is_false(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.finished) - assert.equal(0, combo.count) - assert.equal(0, combo.damage) - assert.equal(spyClock, combo.clock) - assert.is_true(ComboSequence:class_of(combo.sequence)) - end) - end) - - describe("#todot", function() - it("delegates to sequence", function() - local spyTodot = spy.on(combo.sequence, "todot") - combo:todot() - assert.spy(spyTodot).was_called(1) - end) - end) - - describe("#CurrentStepId", function() - it("returns the current step id", function() - assert.is_nil(combo:CurrentStepId()) - assert.is_true(combo:Progress(ability1)) - assert.equal(1, combo:CurrentStepId()) - assert.is_true(combo:Progress(ability2)) - assert.equal(2, combo:CurrentStepId()) - assert.is_true(combo:Progress(ability3)) - assert.equal(3, combo:CurrentStepId()) - assert.is_true(combo:PreFinish()) - assert.is_nil(combo:CurrentStepId()) - assert.is_true(combo:Finish()) - assert.is_nil(combo:CurrentStepId()) - end) - end) - - describe("#CurrentStep", function() - it("returns the current step", function() - assert.is_nil(combo:CurrentStep()) - - assert.is_true(combo:Progress(ability1)) - assert.is_table(combo:CurrentStep()) - assert.equal(1, combo:CurrentStep().id) - assert.equal("step1", combo:CurrentStep().name) - - assert.is_true(combo:Progress(ability2)) - assert.is_table(combo:CurrentStep()) - assert.equal(2, combo:CurrentStep().id) - assert.equal("step2", combo:CurrentStep().name) - - assert.is_true(combo:Progress(ability3)) - assert.is_table(combo:CurrentStep()) - assert.equal(3, combo:CurrentStep().id) - assert.equal("step3", combo:CurrentStep().name) - - assert.is_true(combo:PreFinish()) - assert.is_nil(combo:CurrentStep()) - assert.is_true(combo:Finish()) - assert.is_nil(combo:CurrentStep()) - end) - end) - - describe("#NextStepsIds", function() - it("returns the next steps ids", function() - assert.same({ 1 }, combo:NextStepsIds()) - assert.is_true(combo:Progress(ability1)) - assert.same({ 2, 3 }, combo:NextStepsIds()) - assert.is_true(combo:Progress(ability2)) - assert.same({ 3 }, combo:NextStepsIds()) - assert.is_true(combo:Progress(ability3)) - assert.same({}, combo:NextStepsIds()) - assert.is_true(combo:PreFinish()) - assert.same({}, combo:NextStepsIds()) - assert.is_true(combo:Finish()) - assert.same({}, combo:NextStepsIds()) - end) - end) - - describe("#NextSteps", function() - it("returns the next steps", function() - assert.same({ 1 }, stepsIds(combo:NextSteps())) - assert.is_true(combo:Progress(ability1)) - assert.same({ 2, 3 }, stepsIds(combo:NextSteps())) - assert.is_true(combo:Progress(ability2)) - assert.same({ 3 }, stepsIds(combo:NextSteps())) - assert.is_true(combo:Progress(ability3)) - assert.same({}, combo:NextSteps()) - assert.is_true(combo:PreFinish()) - assert.same({}, combo:NextSteps()) - assert.is_true(combo:Finish()) - assert.same({}, combo:NextSteps()) - end) - end) - - describe("#Progress", function() - describe("with valid abilities", function() - it("progresses the combo", function() - assert.is_false(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(0, combo.count) - assert.same({}, combo.waitQueue) - assert.spy(combo.clock).was_not_called() - assert.is_nil(combo:CurrentStep()) - assert.is_nil(combo:CurrentStepId()) - assert.same({ 1 }, combo:NextStepsIds()) - assert.same({ 1 }, stepsIds(combo:NextSteps())) - - assert.is_true(combo:Progress(ability1)) - - assert.is_true(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(1, combo.count) - assert.same({ 10.5 }, combo.waitQueue) - assert.spy(combo.clock).was_called(2) - assert.same(1, combo:CurrentStep().id) - assert.equal(1, combo:CurrentStepId()) - assert.same({ 2, 3 }, combo:NextStepsIds()) - assert.same({ 2, 3 }, stepsIds(combo:NextSteps())) - - assert.is_true(combo:Progress(ability2)) - - assert.is_true(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(2, combo.count) - assert.same({ 10.5, 10.3 }, combo.waitQueue) - assert.spy(combo.clock).was_called(4) - assert.same(2, combo:CurrentStep().id) - assert.equal(2, combo:CurrentStepId()) - assert.same({ 3 }, combo:NextStepsIds()) - assert.same({ 3 }, stepsIds(combo:NextSteps())) - - assert.is_true(combo:Progress(ability3)) - - assert.is_true(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(3, combo.count) - assert.same({ 10.5, 10.3, 10.25 }, combo.waitQueue) - assert.spy(combo.clock).was_called(6) - assert.same(3, combo:CurrentStep().id) - assert.equal(3, combo:CurrentStepId()) - assert.same({}, combo:NextStepsIds()) - assert.same({}, stepsIds(combo:NextSteps())) - end) - - it("enables skipping optional steps", function() - assert.is_true(combo:Progress(ability1)) - assert.is_true(combo:Progress(ability3)) - end) - end) - - describe("with abilities listed in the wait special table", function() - local specFields = { - id = m.uniqueId(), - sequence = { - { id = 1, name = INVOKER.ABILITY_ALACRITY, required = true, next = { 2 } }, - { id = 2, name = INVOKER.ABILITY_COLD_SNAP, required = true, next = { 3 } }, - { id = 3, name = INVOKER.ABILITY_SUN_STRIKE, required = true }, - }, - } - - local spec = m.chain(SPEC):omit({ "id", "sequence" }):extend(specFields):value() - - local abilityAlacrity = create("ability", { name = INVOKER.ABILITY_ALACRITY, special = { duration = 3.5 } }) - - local abilityColdSnap = create("ability", { - name = INVOKER.ABILITY_COLD_SNAP, - special = { duration = 1.25 }, - }) - - local abilitySunStrike = create("ability", { name = INVOKER.ABILITY_SUN_STRIKE, special = { delay = 2.6 } }) - - it("uses abilities special values for wait times", function() - combo = Combo(spec, { clock = spyClock }) - - assert.same({}, combo.waitQueue) - - assert.is_true(combo:Progress(abilityAlacrity)) - assert.same({ 13.5 }, combo.waitQueue) - - assert.is_true(combo:Progress(abilityColdSnap)) - assert.same({ 13.5, 11.25 }, combo.waitQueue) - - assert.is_true(combo:Progress(abilitySunStrike)) - assert.same({ 13.5, 11.25, 12.6 }, combo.waitQueue) - end) - end) - - describe("with invalid abilities", function() - local invalidAbility = create("ability", { name = "invalid", AbilityDuration = 0.5 }) - - it("does NOT progress the combo", function() - assert.is_false(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(0, combo.count) - assert.same({}, combo.waitQueue) - assert.spy(combo.clock).was_not_called() - assert.is_nil(combo:CurrentStep()) - assert.is_nil(combo:CurrentStepId()) - assert.same({ 1 }, combo:NextStepsIds()) - assert.same({ 1 }, stepsIds(combo:NextSteps())) - - assert.is_false(combo:Progress(invalidAbility)) - - assert.is_false(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(0, combo.count) - assert.same({}, combo.waitQueue) - assert.spy(combo.clock).was_not_called() - assert.is_nil(combo:CurrentStep()) - assert.is_nil(combo:CurrentStepId()) - assert.same({ 1 }, combo:NextStepsIds()) - assert.same({ 1 }, stepsIds(combo:NextSteps())) - - assert.is_true(combo:Progress(ability1)) - - assert.is_true(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(1, combo.count) - assert.same({ 10.5 }, combo.waitQueue) - assert.spy(combo.clock).was_called(2) - assert.same(1, combo:CurrentStep().id) - assert.equal(1, combo:CurrentStepId()) - assert.same({ 2, 3 }, combo:NextStepsIds()) - assert.same({ 2, 3 }, stepsIds(combo:NextSteps())) - - assert.is_false(combo:Progress(invalidAbility)) - - assert.is_true(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.preFinished) - assert.is_false(combo.finished) - assert.equal(1, combo.count) - assert.same({ 10.5 }, combo.waitQueue) - assert.spy(combo.clock).was_called(2) - assert.same(1, combo:CurrentStep().id) - assert.equal(1, combo:CurrentStepId()) - assert.same({ 2, 3 }, combo:NextStepsIds()) - assert.same({ 2, 3 }, stepsIds(combo:NextSteps())) - end) - end) - end) - - describe("#Fail", function() - it("flags the combo as failed", function() - assert.is_false(combo.failed) - combo:Fail() - assert.is_true(combo.failed) - end) - end) - - describe("#PreFinish", function() - it("advances the combo to pre-finished state", function() - assert.is_false(combo:PreFinish()) - assert.is_false(combo.preFinished) - assert.is_true(combo:Progress(ability1)) - assert.is_false(combo:PreFinish()) - assert.is_false(combo.preFinished) - assert.is_true(combo:Progress(ability2)) - assert.is_false(combo:PreFinish()) - assert.is_false(combo.preFinished) - assert.is_true(combo:Progress(ability3)) - assert.is_true(combo:PreFinish()) - assert.is_true(combo.preFinished) - end) - - it("sets the wait times", function() - assert.is_true(combo:Progress(ability1)) - assert.is_true(combo:Progress(ability2)) - assert.is_true(combo:Progress(ability3)) - assert.is_true(combo:PreFinish()) - assert.equal(10.5, combo.waitTime) - assert.equal(0.5, combo.waitDuration) - end) - end) - - describe("#Finish", function() - it("advances the combo to finished state", function() - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_true(combo:Progress(ability1)) - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_true(combo:Progress(ability2)) - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_true(combo:Progress(ability3)) - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_true(combo:PreFinish()) - assert.is_true(combo:Finish()) - assert.is_true(combo.finished) - end) - - it("sets the combo duration", function() - local clockIdx = 0 - local function incrClock() - clockIdx = clockIdx + 1 - return clockIdx - end - - combo = Combo(SPEC, { clock = incrClock }) - - assert.is_true(combo:Progress(ability1)) - assert.is_true(combo:Progress(ability2)) - assert.is_true(combo:Progress(ability3)) - assert.is_true(combo:PreFinish()) - assert.is_true(combo:Finish()) - assert.equal(7, combo.duration) - end) - end) - - describe("#IncrementDamage", function() - it("increments the damage accumulator and returns the accumulated value", function() - assert.equal(13, combo:IncrementDamage(13)) - assert.equal(13, combo.damage) - assert.equal(44, combo:IncrementDamage(31)) - assert.equal(44, combo.damage) - end) - end) -end) diff --git a/spec/combos/Combos_spec.lua b/spec/combos/Combos_spec.lua deleted file mode 100644 index df7ecc9..0000000 --- a/spec/combos/Combos_spec.lua +++ /dev/null @@ -1,694 +0,0 @@ -local m = require("moses") -local match = require("luassert.match") -local create = require("support.factory").create - -local Combo = require("invokation.combos.Combo") -local Combos = require("invokation.combos.Combos") -local Talents = require("invokation.dota2.talents") -local CombosHero = require("invokation.combos.hero") -local CombosComm = require("invokation.combos.communication") -local CombosSound = require("invokation.combos.sound") -local FreestyleCombo = require("invokation.combos.FreestyleCombo") -local DamageInstance = require("invokation.dota2.DamageInstance") - -local UNITS = require("invokation.const.units") -local COMBOS = require("invokation.const.combos") -local INVOKER = require("invokation.const.invoker") -local NET_TABLE = require("invokation.const.net_table") - -describe("Combos", function() - local combos - local netTable = {} - local dummySpawn = create("entity") - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - - setup(function() - stub.new(Entities, "FindByName", function(_, _, name) - return name == UNITS.DUMMY_TARGET_SPAWN and dummySpawn or nil - end) - end) - - teardown(function() - -- selene: allow(incorrect_standard_library_use) - Entities.FindByName:revert() - end) - - before_each(function() - stub.new(netTable, "Set") - - combos = Combos(netTable) - end) - - after_each(function() - netTable.Set:clear() - end) - - describe("constructor", function() - it("loads and transforms specs", function() - assert.equal(m.count(COMBOS), m.count(combos.specs)) - - for _, spec in pairs(combos.specs) do - assert.is_table(spec) - assert.not_nil(spec.id) - - for _, step in pairs(spec.sequence) do - assert.is_table(step) - assert.not_nil(step.id) - end - end - end) - - it("sets NetTable key with loaded specs", function() - assert.stub(netTable.Set).was.self.called_with(NET_TABLE.MAIN.KEYS.COMBOS, combos.specs) - end) - end) - - describe("#OnAbilityUsed", function() - before_each(function() - stub.new(combos, "CaptureAbility") - stub.new(combos, "Progress") - end) - - after_each(function() - combos.CaptureAbility:revert() - combos.Progress:revert() - end) - - local unit = create("hero_invoker") - - describe("with relevant ability", function() - local ability = create("ability", { name = INVOKER.ABILITY_SUN_STRIKE }) - - it("handles ability capture and combo progress", function() - combos:OnAbilityUsed(player, unit, ability) - - assert.stub(combos.CaptureAbility).was.self.called_with(player, ability) - assert.stub(combos.Progress).was.self.called_with(player, ability) - end) - end) - - describe("with ignored ability", function() - local ability = create("ability", { name = "item_phase_boots" }) - - it("is a noop", function() - combos:OnAbilityUsed(player, unit, ability) - - assert.stub(combos.CaptureAbility).was_not.called() - assert.stub(combos.Progress).was_not.called() - end) - end) - end) - - describe("#OnEntityHurt", function() - before_each(function() - stub.new(combos, "ProgressDamage") - end) - - after_each(function() - combos.ProgressDamage:revert() - end) - - local victim = create("unit", { name = UNITS.DUMMY_TARGET }) - - describe("with player-owned attacker", function() - local attacker = create("hero_invoker", { playerOwner = player }) - local inflictor = create("ability", { name = INVOKER.ABILITY_SUN_STRIKE }) - - it("handles combo damage progress", function() - local damage = DamageInstance(victim, 123.4, attacker, inflictor) - local owner = damage:AttackerPlayerOwner() - - combos:OnEntityHurt(damage) - - assert.stub(combos.ProgressDamage).was.self.called_with(owner, damage) - end) - end) - - describe("with non-player attacker", function() - local attacker = create("unit", { name = "npc_dota_hero_axe" }) - local inflictor = create("ability", { name = "item_dagon_5" }) - - it("is a noop", function() - local damage = DamageInstance(victim, 123.4, attacker, inflictor) - - combos:OnEntityHurt(damage) - - assert.stub(combos.ProgressDamage).was_not.called() - end) - end) - end) - - describe("#OnItemPurchased", function() - local purchase = { item = "item_blink", cost = 1234.5 } - - describe("when no combo is active", function() - it("is a noop", function() - hero:SetGold(0, true) - hero:SetGold(0, false) - - assert.equal(0, hero:GetGold()) - - combos:OnItemPurchased(player, purchase) - - assert.equal(0, hero:GetGold()) - end) - end) - - describe("when a regular combo is active", function() - it("is a noop", function() - combos:Start(player, combos:Create(1)) - hero:SetGold(0, true) - hero:SetGold(0, false) - - assert.equal(0, hero:GetGold()) - - combos:OnItemPurchased(player, purchase) - - assert.equal(0, hero:GetGold()) - end) - end) - - describe("when freestyle combo is active", function() - it("refunds the purchase", function() - combos:Start(player, combos:Create(FreestyleCombo.COMBO_ID)) - hero:SetGold(0, true) - hero:SetGold(0, false) - - assert.equal(0, hero:GetGold()) - - combos:OnItemPurchased(player, purchase) - - assert.equal(1234.5, hero:GetGold()) - end) - end) - end) - - describe("#Create", function() - describe("with an invalid id", function() - it("throws an error", function() - local createFn = m.bindn(combos.Create, combos, -1) - assert.error(createFn, 'Combo "-1" not found') - end) - end) - - describe("with freestyle id", function() - it("creates a freestyle combo", function() - local combo = combos:Create(FreestyleCombo.COMBO_ID) - - assert.not_nil(combo) - assert.is_true(FreestyleCombo:class_of(combo)) - end) - end) - - describe("with a valid id", function() - it("creates a combo", function() - local combo = combos:Create(13) - - assert.not_nil(combo) - assert.is_true(Combo:class_of(combo)) - end) - end) - end) - - describe("#Start", function() - before_each(function() - spy.on(CombosHero, "setup") - spy.on(CombosHero, "teardown") - spy.on(CombosSound, "onDummyCreate") - spy.on(CombosSound, "onComboStart") - spy.on(CombosSound, "onComboStop") - spy.on(CombosComm, "sendStarted") - spy.on(CombosComm, "sendStopped") - end) - - after_each(function() - CombosHero.setup:revert() - CombosHero.teardown:revert() - CombosSound.onDummyCreate:revert() - CombosSound.onComboStart:revert() - CombosSound.onComboStop:revert() - CombosComm.sendStarted:revert() - CombosComm.sendStopped:revert() - end) - - describe("when no combo is active", function() - it("starts the combo", function() - assert.is_nil(combos.state[player].combo) - - combos:Start(player, combos:Create(13)) - - local combo = combos.state[player].combo - local dummy = combos.state[player].dummy - - assert.not_nil(combo) - assert.not_nil(dummy) - - assert.equal(13, combo.id) - assert.is_true(dummy:IsAlive()) - - assert.spy(CombosHero.teardown).was.called_with(match.is_ref(player), { hardReset = true }) - assert.spy(CombosHero.setup).was.called_with(match.is_ref(player), match.is_ref(combo)) - assert.spy(CombosSound.onDummyCreate).was.called_with(match.is_ref(dummy)) - assert.spy(CombosSound.onComboStop).was_not.called() - assert.spy(CombosSound.onComboStart).was.called_with(match.is_ref(player)) - assert.spy(CombosComm.sendStarted).was.called_with(match.is_ref(player), match.is_ref(combo)) - assert.spy(CombosComm.sendStopped).was_not.called() - end) - end) - - describe("when the same combo is already active", function() - it("restarts the combo", function() - combos:Start(player, combos:Create(13)) - - local comboBefore = combos.state[player].combo - - assert.not_nil(comboBefore) - assert.equal(13, comboBefore.id) - - CombosHero.setup:clear() - CombosHero.teardown:clear() - CombosSound.onDummyCreate:clear() - CombosSound.onComboStart:clear() - CombosSound.onComboStop:clear() - CombosComm.sendStarted:clear() - CombosComm.sendStopped:clear() - - combos:Start(player, combos:Create(13)) - - local comboAfter = combos.state[player].combo - local dummy = combos.state[player].dummy - - assert.not_nil(comboAfter) - assert.not_nil(dummy) - - assert.not_equal(comboAfter, comboBefore) - assert.equal(13, comboAfter.id) - assert.is_true(dummy:IsAlive()) - - assert.spy(CombosHero.teardown).was.called_with(match.is_ref(player), { hardReset = false }) - - assert.spy(CombosHero.setup).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosSound.onDummyCreate).was_not.called_with(match.is_ref(dummy)) - assert.spy(CombosSound.onComboStop).was_not.called() - assert.spy(CombosSound.onComboStart).was.called_with(match.is_ref(player)) - - assert.spy(CombosComm.sendStarted).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosComm.sendStopped).was_not.called() - end) - end) - - describe("when a different combo is already active", function() - it("stops the previous combo and starts the new combo", function() - combos:Start(player, combos:Create(13)) - - local comboBefore = combos.state[player].combo - - assert.not_nil(comboBefore) - assert.equal(13, comboBefore.id) - - CombosHero.setup:clear() - CombosHero.teardown:clear() - CombosSound.onDummyCreate:clear() - CombosSound.onComboStart:clear() - CombosSound.onComboStop:clear() - CombosComm.sendStarted:clear() - CombosComm.sendStopped:clear() - - combos:Start(player, combos:Create(3)) - - local comboAfter = combos.state[player].combo - local dummy = combos.state[player].dummy - - assert.not_nil(comboAfter) - assert.not_nil(dummy) - - assert.not_equal(comboAfter, comboBefore) - assert.equal(3, comboAfter.id) - assert.is_true(dummy:IsAlive()) - - assert.spy(CombosHero.teardown).was.called_with(match.is_ref(player), { hardReset = true }) - - assert.spy(CombosHero.setup).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosSound.onDummyCreate).was_not.called_with(match.is_ref(dummy)) - assert.spy(CombosSound.onComboStop).was.called_with(match.is_ref(player)) - assert.spy(CombosSound.onComboStart).was.called_with(match.is_ref(player)) - - assert.spy(CombosComm.sendStarted).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosComm.sendStopped).was.called_with(match.is_ref(player), match.is_ref(comboBefore)) - end) - end) - end) - - describe("#Stop", function() - before_each(function() - spy.on(CombosHero, "teardown") - spy.on(CombosSound, "onComboStop") - spy.on(CombosComm, "sendStopped") - end) - - after_each(function() - CombosHero.teardown:revert() - CombosSound.onComboStop:revert() - CombosComm.sendStopped:revert() - end) - - describe("when no combo is active", function() - it("throws an error", function() - local stopFn = m.bindn(combos.Stop, combos, player) - - assert.error(stopFn, "Player 13 has no active combo") - assert.spy(CombosHero.teardown).was_not.called() - assert.spy(CombosSound.onComboStop).was_not.called() - assert.spy(CombosComm.sendStopped).was_not.called() - end) - end) - - describe("when a combo is active", function() - it("stops the active combo", function() - combos:Start(player, combos:Create(13)) - - local comboBefore = combos.state[player].combo - local dummyBefore = combos.state[player].dummy - - assert.not_nil(comboBefore) - assert.not_nil(dummyBefore) - assert.equal(13, comboBefore.id) - assert.is_true(dummyBefore:IsAlive()) - - CombosHero.teardown:clear() - CombosSound.onComboStop:clear() - CombosComm.sendStopped:clear() - - combos:Stop(player) - - local comboAfter = combos.state[player].combo - local dummyAfter = combos.state[player].dummy - - assert.is_nil(comboAfter) - assert.not_nil(dummyAfter) - assert.equal(dummyBefore, dummyAfter) - assert.is_false(dummyAfter:IsAlive()) - - assert.spy(CombosHero.teardown).was.called_with(match.is_ref(player), { hardReset = true }) - assert.spy(CombosSound.onComboStop).was.called_with(match.is_ref(player)) - assert.spy(CombosComm.sendStopped).was.called_with(match.is_ref(player), match.is_ref(comboBefore)) - end) - end) - end) - - describe("#Restart", function() - before_each(function() - spy.on(CombosHero, "setup") - spy.on(CombosHero, "teardown") - spy.on(CombosSound, "onDummyCreate") - spy.on(CombosSound, "onComboStart") - spy.on(CombosSound, "onComboStop") - spy.on(CombosComm, "sendStarted") - spy.on(CombosComm, "sendStopped") - end) - - after_each(function() - CombosHero.setup:revert() - CombosHero.teardown:revert() - CombosSound.onDummyCreate:revert() - CombosSound.onComboStart:revert() - CombosSound.onComboStop:revert() - CombosComm.sendStarted:revert() - CombosComm.sendStopped:revert() - end) - - describe("when no combo is active", function() - it("throws an error", function() - local restartFn = m.bindn(combos.Restart, combos, player) - - assert.error(restartFn, "Player 13 has no active combo") - - assert.spy(CombosHero.teardown).was_not.called() - assert.spy(CombosHero.setup).was_not.called() - assert.spy(CombosSound.onDummyCreate).was_not.called() - assert.spy(CombosSound.onComboStart).was_not.called() - assert.spy(CombosSound.onComboStop).was_not.called() - assert.spy(CombosComm.sendStarted).was_not.called() - assert.spy(CombosComm.sendStopped).was_not.called() - end) - end) - - describe("when a combo is active", function() - describe("without hard reset option", function() - it("restarts the combo", function() - combos:Start(player, combos:Create(13)) - - local comboBefore = combos.state[player].combo - - assert.not_nil(comboBefore) - assert.equal(13, comboBefore.id) - - CombosHero.setup:clear() - CombosHero.teardown:clear() - CombosSound.onDummyCreate:clear() - CombosSound.onComboStart:clear() - CombosSound.onComboStop:clear() - CombosComm.sendStarted:clear() - CombosComm.sendStopped:clear() - - combos:Restart(player, { hardReset = false }) - - local comboAfter = combos.state[player].combo - local dummy = combos.state[player].dummy - - assert.not_nil(comboAfter) - assert.not_nil(dummy) - - assert.not_equal(comboAfter, comboBefore) - assert.equal(13, comboAfter.id) - assert.is_true(dummy:IsAlive()) - - assert.spy(CombosHero.teardown).was.called_with(match.is_ref(player), { hardReset = false }) - - assert.spy(CombosHero.setup).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosSound.onDummyCreate).was_not.called_with(match.is_ref(dummy)) - assert.spy(CombosSound.onComboStop).was_not.called() - assert.spy(CombosSound.onComboStart).was.called_with(match.is_ref(player)) - - assert.spy(CombosComm.sendStarted).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosComm.sendStopped).was_not.called() - end) - end) - - describe("with hard reset option", function() - it("restarts the combo", function() - combos:Start(player, combos:Create(13)) - - local comboBefore = combos.state[player].combo - - assert.not_nil(comboBefore) - assert.equal(13, comboBefore.id) - - CombosHero.setup:clear() - CombosHero.teardown:clear() - CombosSound.onDummyCreate:clear() - CombosSound.onComboStart:clear() - CombosSound.onComboStop:clear() - CombosComm.sendStarted:clear() - CombosComm.sendStopped:clear() - - combos:Restart(player, { hardReset = true }) - - local comboAfter = combos.state[player].combo - local dummy = combos.state[player].dummy - - assert.not_nil(comboAfter) - assert.not_nil(dummy) - - assert.not_equal(comboAfter, comboBefore) - assert.equal(13, comboAfter.id) - assert.is_true(dummy:IsAlive()) - - assert.spy(CombosHero.teardown).was.called_with(match.is_ref(player), { hardReset = true }) - - assert.spy(CombosHero.setup).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosSound.onDummyCreate).was_not.called_with(match.is_ref(dummy)) - assert.spy(CombosSound.onComboStop).was_not.called() - assert.spy(CombosSound.onComboStart).was.called_with(match.is_ref(player)) - - assert.spy(CombosComm.sendStarted).was.called_with(match.is_ref(player), match.is_ref(comboAfter)) - - assert.spy(CombosComm.sendStopped).was_not.called() - end) - end) - end) - end) - - describe("#Progress", function() - local combo - - before_each(function() - combo = Combo({ - id = m.uniqueId("Combos_spec-Progress-%d"), - specialty = "qw", - stance = "defensive", - heroLevel = 25, - damageRating = 5, - difficultyRating = 5, - gold = 1234, - tags = { "late-game" }, - items = { "item_blink" }, - orbs = { 7, 7, 7 }, - talents = Talents.Select(Talents.L10_LEFT, Talents.L15_RIGHT, Talents.L20_RIGHT, Talents.L25_RIGHT), - sequence = { - { id = 1, name = INVOKER.ABILITY_COLD_SNAP, required = true, next = { 2, 3 } }, - { id = 2, name = INVOKER.ABILITY_GHOST_WALK, next = { 3 } }, - { id = 3, name = INVOKER.ABILITY_EMP, required = true }, - }, - }) - - spy.on(combos, "PreFinish") - spy.on(combos, "Fail") - spy.on(CombosComm, "sendInProgress") - spy.on(CombosComm, "sendProgress") - end) - - after_each(function() - combos.PreFinish:revert() - combos.Fail:revert() - CombosComm.sendInProgress:revert() - CombosComm.sendProgress:revert() - end) - - describe("with no active combo", function() - it("does nothing", function() - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_COLD_SNAP })) - - assert.spy(combos.PreFinish).was_not.called() - assert.spy(combos.Fail).was_not.called() - assert.spy(CombosComm.sendInProgress).was_not.called() - assert.spy(CombosComm.sendProgress).was_not.called() - end) - end) - - describe("with failed combo", function() - it("does nothing", function() - combos:Start(player, combo) - combo:Fail() - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_COLD_SNAP })) - - assert.spy(combos.PreFinish).was_not.called() - assert.spy(combos.Fail).was_not.called() - assert.spy(CombosComm.sendInProgress).was_not.called() - assert.spy(CombosComm.sendProgress).was_not.called() - end) - end) - - describe("with pre-finished combo", function() - it("does nothing", function() - combos:Start(player, combo) - - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_COLD_SNAP }))) - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_GHOST_WALK }))) - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_EMP }))) - assert.is_true(combo:PreFinish()) - - assert.is_true(combo.preFinished) - - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_COLD_SNAP })) - - assert.spy(combos.PreFinish).was_not.called() - assert.spy(combos.Fail).was_not.called() - assert.spy(CombosComm.sendInProgress).was_not.called() - assert.spy(CombosComm.sendProgress).was_not.called() - end) - end) - - describe("with finished combo", function() - it("does nothing", function() - combos:Start(player, combo) - - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_COLD_SNAP }))) - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_GHOST_WALK }))) - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_EMP }))) - assert.is_true(combo:PreFinish()) - assert.is_true(combo:Finish()) - - assert.is_true(combo.finished) - - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_COLD_SNAP })) - - assert.spy(combos.PreFinish).was_not.called() - assert.spy(combos.Fail).was_not.called() - assert.spy(CombosComm.sendInProgress).was_not.called() - assert.spy(CombosComm.sendProgress).was_not.called() - end) - end) - - describe("with regular active combo", function() - before_each(function() - combos:Start(player, combo) - end) - - describe("with invocation ability", function() - it("does nothing", function() - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_EXORT })) - - assert.spy(combos.PreFinish).was_not.called() - assert.spy(combos.Fail).was_not.called() - assert.spy(CombosComm.sendInProgress).was_not.called() - assert.spy(CombosComm.sendProgress).was_not.called() - end) - end) - - describe("with incorrect ability", function() - local ability = create("ability", { name = INVOKER.ABILITY_SUN_STRIKE }) - - it("fails the combo", function() - combos:Progress(player, ability) - - assert.is_true(combo.failed) - assert.spy(combos.Fail).was.self.called_with(match.is_ref(player), match.is_ref(ability)) - assert.spy(CombosComm.sendInProgress).was_not.called() - assert.spy(CombosComm.sendProgress).was_not.called() - end) - end) - - describe("with correct ability", function() - it("progresses the combo", function() - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_COLD_SNAP })) - - assert.spy(combos.PreFinish).was_not.called() - assert.spy(combos.Fail).was_not.called() - assert.spy(CombosComm.sendProgress).was.called_with(match.is_ref(player), match.is_ref(combo)) - end) - - describe("when it's the first combo step", function() - it("communicates that combo is in progress", function() - local ability = create("ability", { name = INVOKER.ABILITY_COLD_SNAP }) - - combos:Progress(player, ability) - - assert.spy(CombosComm.sendInProgress).was.called_with(match.is_ref(player), match.is_ref(combo)) - end) - end) - - describe("when it's the last combo step", function() - it("pre-finishes the combo", function() - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_COLD_SNAP }))) - assert.is_true(combo:Progress(create("ability", { name = INVOKER.ABILITY_GHOST_WALK }))) - - combos:Progress(player, create("ability", { name = INVOKER.ABILITY_EMP })) - - assert.is_true(combo.preFinished) - assert.spy(combos.PreFinish).was.self.called_with(match.is_ref(player)) - assert.spy(combos.Fail).was_not.called() - end) - end) - end) - end) - end) -end) diff --git a/spec/combos/FreestyleCombo_spec.lua b/spec/combos/FreestyleCombo_spec.lua deleted file mode 100644 index 13a5416..0000000 --- a/spec/combos/FreestyleCombo_spec.lua +++ /dev/null @@ -1,203 +0,0 @@ -local BaseCombo = require("invokation.combos.BaseCombo") -local FreestyleCombo = require("invokation.combos.FreestyleCombo") - -describe("FreestyleCombo", function() - local combo - - before_each(function() - combo = FreestyleCombo() - end) - - it("inherits from BaseCombo", function() - assert.is_true(BaseCombo:class_of(combo)) - end) - - describe("constructor", function() - it("initializes attributes", function() - assert.equal(FreestyleCombo.COMBO_ID, combo.id) - assert.is_true(combo.started) - assert.is_false(combo.failed) - assert.is_false(combo.finished) - assert.equal(0, combo.count) - assert.equal(0, combo.damage) - end) - end) - - describe("#CurrentStepId", function() - local ability = { - IsInvocationAbility = function() - return false - end, - } - - it("always returns nil", function() - assert.is_nil(combo:CurrentStepId()) - assert.is_true(combo:Progress(ability)) - assert.is_nil(combo:CurrentStepId()) - end) - end) - - describe("#CurrentStep", function() - local ability = { - IsInvocationAbility = function() - return false - end, - } - - it("always returns nil", function() - assert.is_nil(combo:CurrentStep()) - assert.is_true(combo:Progress(ability)) - assert.is_nil(combo:CurrentStep()) - end) - end) - - describe("#NextStepsIds", function() - local ability = { - IsInvocationAbility = function() - return false - end, - } - - it("always returns an empty array", function() - assert.same({}, combo:NextStepsIds()) - assert.is_true(combo:Progress(ability)) - assert.same({}, combo:NextStepsIds()) - end) - end) - - describe("#NextSteps", function() - local ability = { - IsInvocationAbility = function() - return false - end, - } - - it("always returns an empty array", function() - assert.same({}, combo:NextSteps()) - assert.is_true(combo:Progress(ability)) - assert.same({}, combo:NextSteps()) - end) - end) - - describe("#Progress", function() - describe("with invocation ability", function() - local ability = { - IsInvocationAbility = spy.new(function() - return true - end), - } - - before_each(function() - ability.IsInvocationAbility:clear() - end) - - it("returns false", function() - assert.is_false(combo:Progress(ability)) - assert.spy(ability.IsInvocationAbility).was_called(1) - end) - - it("does not update counter", function() - assert.is_false(combo:Progress(ability)) - assert.spy(ability.IsInvocationAbility).was_called(1) - assert.equal(0, combo.count) - end) - end) - - describe("with non-invocation ability", function() - local ability = { - IsInvocationAbility = spy.new(function() - return false - end), - } - - before_each(function() - ability.IsInvocationAbility:clear() - end) - - it("returns true", function() - assert.is_true(combo:Progress(ability)) - assert.spy(ability.IsInvocationAbility).was_called(1) - end) - - it("increments counter", function() - assert.is_true(combo:Progress(ability)) - assert.equal(1, combo.count) - - assert.is_true(combo:Progress(ability)) - assert.equal(2, combo.count) - - assert.is_true(combo:Progress(ability)) - assert.equal(3, combo.count) - - assert.spy(ability.IsInvocationAbility).was_called(3) - end) - end) - end) - - describe("#Fail", function() - local ability = { - IsInvocationAbility = function() - return true - end, - } - - it("is a no-op", function() - assert.is_false(combo.failed) - assert.is_nil(combo:Fail()) - assert.is_false(combo.failed) - assert.is_false(combo:Progress(ability)) - assert.is_nil(combo:Fail()) - assert.is_false(combo.failed) - end) - end) - - describe("#PreFinish", function() - local ability = { - IsInvocationAbility = function() - return false - end, - } - - it("always returns false", function() - assert.is_false(combo:PreFinish()) - assert.is_false(combo.preFinished) - assert.is_true(combo:Progress(ability)) - assert.is_false(combo:PreFinish()) - assert.is_false(combo.preFinished) - assert.is_true(combo:Progress(ability)) - assert.is_false(combo:PreFinish()) - assert.is_false(combo.preFinished) - end) - end) - - describe("#Finish", function() - local ability = { - IsInvocationAbility = function() - return false - end, - } - - it("always returns false", function() - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_true(combo:Progress(ability)) - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_true(combo:Progress(ability)) - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - assert.is_false(combo:PreFinish()) - assert.is_false(combo:Finish()) - assert.is_false(combo.finished) - end) - end) - - describe("#IncrementDamage", function() - it("increments the damage accumulator and returns the accumulated value", function() - assert.equal(13, combo:IncrementDamage(13)) - assert.equal(13, combo.damage) - assert.equal(44, combo:IncrementDamage(31)) - assert.equal(44, combo.damage) - end) - end) -end) diff --git a/spec/combos/PlayerStates_spec.lua b/spec/combos/PlayerStates_spec.lua deleted file mode 100644 index c240492..0000000 --- a/spec/combos/PlayerStates_spec.lua +++ /dev/null @@ -1,87 +0,0 @@ -local PlayerStates = require("invokation.combos.PlayerStates") - -describe("PlayerStates", function() - describe("#__index", function() - it("creates a new player state if it doesn't exist yet", function() - local player1 = { - GetPlayerID = spy.new(function() - return 1 - end), - } - - local player2 = { - GetPlayerID = spy.new(function() - return 2 - end), - } - - local states = PlayerStates() - - assert.is_nil(states.states[1]) - - local state1 = states[player1] - - assert.same({}, state1) - assert.equal(states.states[1], state1) - assert.spy(player1.GetPlayerID).was_called(1) - - assert.is_nil(states.states[2]) - - local state2 = states[player2] - - assert.same({}, state2) - assert.equal(states.states[2], state2) - assert.spy(player2.GetPlayerID).was_called(1) - - assert.not_equal(state1, state2) - end) - - it("returns a previously created state", function() - local player = { - GetPlayerID = spy.new(function() - return 1 - end), - } - - local states = PlayerStates() - - assert.is_nil(states.states[1]) - - local state1 = states[player] - - assert.same({}, state1) - assert.equal(states.states[1], state1) - assert.spy(player.GetPlayerID).was_called(1) - - player.GetPlayerID:clear() - - local state2 = states[player] - - assert.same({}, state2) - assert.equal(state1, state2) - assert.equal(states.states[1], state2) - assert.spy(player.GetPlayerID).was_called(1) - - state2.key1 = "value" - - assert.equal("value", state1.key1) - - player.GetPlayerID:clear() - - local state3 = states[player] - - assert.same({ key1 = "value" }, state3) - assert.equal(state1, state2, state3) - assert.equal(states.states[1], state3) - assert.spy(player.GetPlayerID).was_called(1) - - state3.key2 = 13 - - assert.same({ key1 = "value", key2 = 13 }, state1) - - assert.same({ key1 = "value", key2 = 13 }, state2) - - assert.same({ key1 = "value", key2 = 13 }, state3) - end) - end) -end) diff --git a/spec/combos/communication_spec.lua b/spec/combos/communication_spec.lua deleted file mode 100644 index 1609a74..0000000 --- a/spec/combos/communication_spec.lua +++ /dev/null @@ -1,126 +0,0 @@ -local create = require("support.factory").create - -local Combo = require("invokation.combos.Combo") -local CombosComm = require("invokation.combos.communication") -local CustomEvents = require("invokation.dota2.custom_events") - -describe("combos.communication", function() - local combo - local player = {} - local ability = create("ability", { name = "ability" }) - - local comboSpec = { id = 13, sequence = { { id = 1, name = "ability" } } } - - local clockIdx - local function clock() - clockIdx = clockIdx + 1 - return clockIdx - end - - before_each(function() - combo = Combo(comboSpec) - clockIdx = 0 - spy.on(CustomEvents, "SendPlayer") - end) - - after_each(function() - CustomEvents.SendPlayer:revert() - end) - - describe(".sendAbilityUsed", function() - it("sends custom event", function() - local payload = { ability = "ability" } - - CombosComm.sendAbilityUsed(player, ability) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBAT_LOG_ABILITY_USED, player, payload) - end) - end) - - describe(".sendStarted", function() - it("sends custom event", function() - local payload = { id = 13, next = { 1 } } - - CombosComm.sendStarted(player, combo) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_STARTED, player, payload) - end) - end) - - describe(".sendStopped", function() - it("sends custom event", function() - local payload = { id = 13 } - - CombosComm.sendStopped(player, combo) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_STOPPED, player, payload) - end) - end) - - describe(".sendInProgress", function() - it("sends custom event", function() - local payload = { id = 13 } - - CombosComm.sendInProgress(player, combo) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_IN_PROGRESS, player, payload) - end) - end) - - describe(".sendProgress", function() - it("sends custom event", function() - assert.is_true(combo:Progress(ability)) - assert.equal(123, combo:IncrementDamage(123)) - - local payload = { id = 13, metrics = { count = 1, damage = 123, duration = nil }, next = {} } - - CombosComm.sendProgress(player, combo) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_PROGRESS, player, payload) - end) - end) - - describe(".sendStepError", function() - it("sends custom event", function() - local payload = { id = 13, expected = { 1 }, ability = "ability" } - - CombosComm.sendStepError(player, combo, ability) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_STEP_ERROR, player, payload) - end) - end) - - describe(".sendPreFinish", function() - it("sends custom event", function() - local abilityWithWait = create("ability", { name = "ability", AbilityDuration = 3.5 }) - local comboWithDelay = Combo(comboSpec, { clock = clock }) - - assert.is_true(comboWithDelay:Progress(abilityWithWait)) - assert.equal(123, comboWithDelay:IncrementDamage(123)) - assert.is_true(comboWithDelay:PreFinish()) - - local payload = { id = 13, metrics = { count = 1, damage = 123, duration = nil }, wait = 2.5 } - - CombosComm.sendPreFinish(player, comboWithDelay) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_PRE_FINISH, player, payload) - end) - end) - - describe(".sendFinished", function() - it("sends custom event", function() - local comboWithDelay = Combo(comboSpec, { clock = clock }) - - assert.is_true(comboWithDelay:Progress(ability)) - assert.equal(123, comboWithDelay:IncrementDamage(123)) - assert.is_true(comboWithDelay:PreFinish()) - assert.is_true(comboWithDelay:Finish()) - - local payload = { id = 13, metrics = { count = 1, damage = 123, duration = 3 } } - - CombosComm.sendFinished(player, comboWithDelay) - - assert.spy(CustomEvents.SendPlayer).was.called_with(CustomEvents.EVENT_COMBO_FINISHED, player, payload) - end) - end) -end) diff --git a/spec/combos/hero_spec.lua b/spec/combos/hero_spec.lua deleted file mode 100644 index 841866d..0000000 --- a/spec/combos/hero_spec.lua +++ /dev/null @@ -1,376 +0,0 @@ -local m = require("moses") -local create = require("support.factory").create - -local Combo = require("invokation.combos.Combo") -local CombosHero = require("invokation.combos.hero") - -local LIMITS = require("invokation.const.limits") -local INVOKER = require("invokation.const.invoker") -local SOUND_EVENTS = require("invokation.const.sound_events") - -describe("combos.hero", function() - describe(".setup", function() - local combo = Combo({ - id = 13, - heroLevel = 6, - gold = 1300, - items = { - "item_travel_boots", - "item_black_king_bar", - "item_shivas_guard", - "item_refresher", - "item_octarine_core", - "item_ultimate_scepter", - }, - sequence = { { id = 1, name = "ability" } }, - }) - - it("runs the combo setup", function() - local unit = create("hero_invoker") - local hero = unit.entity - local player = create("dota_player", { id = 13, hero = hero }) - - CombosHero.setup(player, combo) - - assert.equal(6, hero:GetLevel()) - assert.equal(1300, hero:GetGold()) - assert.same(m.sort(combo.items), unit:ItemNames({ sort = true })) - end) - - describe("when hero already has some items", function() - it("gives the hero only the missing items", function() - local items = { "item_shivas_guard", "item_refresher" } - local unit = create("hero_invoker", {}, { items = items }) - local player = create("dota_player", { id = 13, hero = unit.entity }) - - CombosHero.setup(player, combo) - - assert.same(m.sort(combo.items), unit:ItemNames({ sort = true })) - end) - end) - end) - - describe(".teardown", function() - it("stops currently playing sounds on the hero", function() - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - local spyStopSound = spy.on(hero, "StopSound") - - CombosHero.teardown(player) - - assert.spy(spyStopSound).was.self.called_with(SOUND_EVENTS.SNDEVT_INVOKER_METEOR_LOOP) - end) - - it("resets hero abilities cooldowns", function() - local unit = create("hero_invoker") - local player = create("dota_player", { id = 13, hero = unit.entity }) - local spies = {} - - unit:ForEachAbility(function(ability) - spies[ability:GetAbilityName()] = { EndCooldown = spy.on(ability, "EndCooldown") } - end) - - assert.is_false(m.isEmpty(spies)) - - CombosHero.teardown(player) - - for _, s in pairs(spies) do - assert.spy(s.EndCooldown).was.self.called() - end - end) - - it("resets hero items cooldowns", function() - local items = { "item_shivas_guard", "item_refresher" } - local unit = create("hero_invoker", {}, { items = items }) - local hero = unit.entity - - assert.is_false(m.isEmpty(hero.inventory)) - - local player = create("dota_player", { id = 13, hero = hero }) - local spies = {} - - unit:ForEachItem(function(item) - spies[item:GetAbilityName()] = { EndCooldown = spy.on(item, "EndCooldown") } - end) - - assert.is_false(m.isEmpty(spies)) - - CombosHero.teardown(player) - - for _, s in pairs(spies) do - assert.spy(s.EndCooldown).was.self.called() - end - end) - - describe("with dropped items", function() - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - local items = { - create("dota_item", { name = "item_blink", purchaser = hero }), - create("dota_item", { name = "item_refresher", purchaser = hero }), - create("dota_item", { name = "item_travel_boots", purchaser = hero }), - } - - before_each(function() - stub.new(GameRules, "NumDroppedItems", #items) - stub.new(GameRules, "GetDroppedItem", function(_, i) - return items[i + 1] - end) - end) - - after_each(function() - -- selene: allow(incorrect_standard_library_use) - GameRules.NumDroppedItems:revert() - -- selene: allow(incorrect_standard_library_use) - GameRules.GetDroppedItem:revert() - end) - - it("removes dropped items owned by the hero", function() - local itemSpies = m.map(items, function(item) - return item, { RemoveSelf = spy.on(item, "RemoveSelf") } - end) - - CombosHero.teardown(player) - - for item, spies in pairs(itemSpies) do - assert.spy(spies.RemoveSelf).was.self.called() - assert.is_true(item:IsNull()) - end - end) - end) - - describe("with spawned units by the hero", function() - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - local units = {} - local unitSpies = {} - - for _, name in pairs(INVOKER.SPAWNED_UNITS) do - for _ = 0, 1 do - local unit = create("dota_unit", { name = name, playerOwner = player }) - - units[name] = units[name] or {} - - table.insert(units[name], unit) - - unitSpies[name] = unitSpies[name] or {} - unitSpies[name][unit] = { RemoveSelf = spy.on(unit, "RemoveSelf") } - end - end - - before_each(function() - stub.new(Entities, "FindByName", function(_, startEnt, name) - local entIdx = startEnt and startEnt:GetEntityIndex() or 0 - - local unitIdx = m.findIndex(units[name], function(unit) - return unit:GetEntityIndex() > entIdx - end) - - return units[name][unitIdx] - end) - end) - - after_each(function() - -- selene: allow(incorrect_standard_library_use) - Entities.FindByName:revert() - end) - - it("removes spawned units by the hero", function() - CombosHero.teardown(player) - - for _, group in pairs(unitSpies) do - for unit, spies in pairs(group) do - assert.spy(spies.RemoveSelf).was.self.called_with() - assert.is_true(unit:IsNull()) - end - end - end) - end) - - describe("with soft reset", function() - it("purges the hero", function() - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - local spyHeroPurge = spy.on(hero, "Purge") - - CombosHero.teardown(player) - - assert.spy(spyHeroPurge).was.self.called_with(true, true, false, true, true) - end) - - it("heals the hero to max health", function() - local hero = create("dota_hero_invoker", { maxHealth = 1000.0, health = 301.25 }) - local player = create("dota_player", { id = 13, hero = hero }) - - assert.equal(301.25, hero:GetHealth()) - - CombosHero.teardown(player) - - assert.equal(1000.0, hero:GetHealth()) - end) - - it("gives the hero max mana", function() - local hero = create("dota_hero_invoker", { maxMana = 1000.0, mana = 301.25 }) - local player = create("dota_player", { id = 13, hero = hero }) - - assert.equal(301.25, hero:GetMana()) - - CombosHero.teardown(player) - - assert.equal(1000.0, hero:GetMana()) - end) - end) - - describe("with hard reset", function() - before_each(function() - stub.new(PlayerResource, "ReplaceHeroWith") - end) - - after_each(function() - -- selene: allow(incorrect_standard_library_use) - PlayerResource.ReplaceHeroWith:revert() - end) - - it("removes all hero's items", function() - local items = { "item_shivas_guard", "item_refresher" } - local hero = create("dota_hero_invoker", {}, { items = items }) - local player = create("dota_player", { id = 13, hero = hero }) - - CombosHero.teardown(player, { hardReset = true }) - - assert.same({}, hero.inventory) - end) - - it("resets hero abilities", function() - local abilities = { - [INVOKER.ABILITY_QUAS] = 7, - [INVOKER.ABILITY_WEX] = 4, - [INVOKER.ABILITY_EXORT] = 6, - [INVOKER.ABILITY_COLD_SNAP] = 1, - [INVOKER.ABILITY_SUN_STRIKE] = 1, - [INVOKER.ABILITY_TALENT_L10_RIGHT] = 1, - [INVOKER.ABILITY_TALENT_L10_LEFT] = 0, - [INVOKER.ABILITY_TALENT_L15_RIGHT] = 1, - [INVOKER.ABILITY_TALENT_L15_LEFT] = 0, - [INVOKER.ABILITY_TALENT_L20_RIGHT] = 1, - [INVOKER.ABILITY_TALENT_L20_LEFT] = 0, - [INVOKER.ABILITY_TALENT_L25_RIGHT] = 1, - [INVOKER.ABILITY_TALENT_L25_LEFT] = 0, - } - - local hero = create("dota_hero_invoker", {}, { abilities = abilities }) - local player = create("dota_player", { id = 13, hero = hero }) - - CombosHero.teardown(player, { hardReset = true }) - - for _, name in ipairs(INVOKER.ORB_ABILITIES) do - assert.equal(0, hero:FindAbilityByName(name):GetLevel()) - end - - for _, name in ipairs(INVOKER.TALENT_ABILITIES) do - assert.equal(0, hero:FindAbilityByName(name):GetLevel()) - end - - assert.equal(1, hero:FindAbilityByName(INVOKER.ABILITY_COLD_SNAP):GetLevel()) - assert.equal(1, hero:FindAbilityByName(INVOKER.ABILITY_SUN_STRIKE):GetLevel()) - assert.equal(1, hero:GetAbilityPoints()) - end) - - it("replaces hero with a new one", function() - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - local spyHeroRemoveSelf = spy.on(hero, "RemoveSelf") - - CombosHero.teardown(player, { hardReset = true }) - - assert.stub(PlayerResource.ReplaceHeroWith).was.self.called_with(13, INVOKER.UNIT_NAME, 0, 0) - - assert.spy(spyHeroRemoveSelf).was.self.called() - assert.is_true(hero:IsNull()) - end) - end) - end) - - describe(".refundPurchase", function() - it("refunds a purchase", function() - local hero = create("dota_hero_invoker") - local player = create("dota_player", { id = 13, hero = hero }) - local purchase = { item = "item_blink", cost = 1234.5 } - - hero:SetGold(0, true) - hero:SetGold(0, false) - - assert.equal(0, hero:GetGold()) - - CombosHero.refundPurchase(player, purchase) - - assert.equal(1234.5, hero:GetGold()) - end) - end) - - describe(".levelUp", function() - local abilities = { - [INVOKER.ABILITY_QUAS] = 1, - [INVOKER.ABILITY_WEX] = 1, - [INVOKER.ABILITY_EXORT] = 1, - [INVOKER.ABILITY_COLD_SNAP] = 1, - [INVOKER.ABILITY_SUN_STRIKE] = 1, - } - - local hero, player - - before_each(function() - hero = create("dota_hero_invoker", { level = 3, abilityPoints = 0 }, { abilities = abilities }) - player = create("dota_player", { id = 13, hero = hero }) - end) - - describe("with specific level option", function() - it("levels up the player hero to the specified level", function() - assert.equal(3, hero:GetLevel()) - assert.equal(0, hero:GetAbilityPoints()) - - CombosHero.levelUp(player, { level = 6 }) - - assert.equal(6, hero:GetLevel()) - assert.equal(3, hero:GetAbilityPoints()) - end) - end) - - describe("with empty level option", function() - it("levels up the player hero by one level", function() - assert.equal(3, hero:GetLevel()) - assert.equal(0, hero:GetAbilityPoints()) - - CombosHero.levelUp(player) - - assert.equal(4, hero:GetLevel()) - assert.equal(1, hero:GetAbilityPoints()) - end) - end) - - describe("with maxLevel option", function() - it("levels up the player hero, abilities and talents to max level", function() - assert.equal(3, hero:GetLevel()) - assert.equal(0, hero:GetAbilityPoints()) - - CombosHero.levelUp(player, { maxLevel = true }) - - assert.equal(LIMITS.MAX_HERO_LEVEL, hero:GetLevel()) - assert.equal(0, hero:GetAbilityPoints()) - - for _, name in ipairs(INVOKER.ORB_ABILITIES) do - local ability = hero:FindAbilityByName(name) - assert.equal(ability:GetMaxLevel(), ability:GetLevel()) - end - - for _, name in ipairs(INVOKER.TALENT_ABILITIES) do - local ability = hero:FindAbilityByName(name) - assert.equal(ability:GetMaxLevel(), ability:GetLevel()) - end - - assert.equal(1, hero:FindAbilityByName(INVOKER.ABILITY_COLD_SNAP):GetLevel()) - assert.equal(1, hero:FindAbilityByName(INVOKER.ABILITY_SUN_STRIKE):GetLevel()) - end) - end) - end) -end) diff --git a/spec/combos/sound_spec.lua b/spec/combos/sound_spec.lua deleted file mode 100644 index e8e2579..0000000 --- a/spec/combos/sound_spec.lua +++ /dev/null @@ -1,91 +0,0 @@ -local CombosSound = require("invokation.combos.sound") -local SoundEvents = require("invokation.dota2.sound_events") - -describe("combos.sound", function() - local player = CDOTAPlayer({}) - local entity = {} - local dummy = { entity = entity } - - local stubRandomInt - local spyEmitOnEntity - local spyEmitOnPlayer - local spySetMusicStatus - - before_each(function() - -- selene: allow(global_usage) - stubRandomInt = stub.new(_G, "RandomInt", 1) - spyEmitOnEntity = spy.on(SoundEvents, "EmitOnEntity") - spyEmitOnPlayer = spy.on(SoundEvents, "EmitOnPlayer") - spySetMusicStatus = spy.on(player, "SetMusicStatus") - end) - - after_each(function() - stubRandomInt:revert() - spyEmitOnEntity:revert() - spyEmitOnPlayer:revert() - spySetMusicStatus:revert() - end) - - describe(".emitRandomEventOnEntity", function() - it("emits random sound event on entity", function() - local events = { "a", "b", "c" } - - CombosSound.emitRandomEventOnEntity(entity, events) - - assert.stub(stubRandomInt).was.called_with(1, 3) - assert.spy(spyEmitOnEntity).was.called_with("a", entity) - end) - end) - - describe(".emitRandomEventOnPlayer", function() - it("emits random sound event on player", function() - local events = { "a", "b", "c" } - - CombosSound.emitRandomEventOnPlayer(player, events) - - assert.stub(stubRandomInt).was.called_with(1, 3) - assert.spy(spyEmitOnPlayer).was.called_with("a", player) - end) - end) - - describe(".onDummyCreate", function() - it("emits random dummy create sound event on dummy entity", function() - CombosSound.onDummyCreate(dummy) - - assert.stub(stubRandomInt).was.called_with(1, #SoundEvents.SNDEVTS_DUMMY_CREATE) - assert.spy(spyEmitOnEntity).was.called_with(SoundEvents.SNDEVTS_DUMMY_CREATE[1], dummy.entity) - end) - end) - - describe(".onComboStart", function() - it("sets the music status on the player", function() - CombosSound.onComboStart(player) - - assert.spy(spySetMusicStatus).was_called(1) - end) - end) - - describe(".onComboStop", function() - it("sets the music status on the player", function() - CombosSound.onComboStop(player) - - assert.spy(spySetMusicStatus).was_called(1) - end) - end) - - describe(".onComboStepError", function() - it("sets the music status on the player", function() - CombosSound.onComboStepError(player) - - assert.spy(spySetMusicStatus).was_called(1) - end) - end) - - describe(".onComboFinished", function() - it("sets the music status on the player", function() - CombosSound.onComboFinished(player) - - assert.spy(spySetMusicStatus).was_called(1) - end) - end) -end) diff --git a/spec/dota2/Ability_spec.lua b/spec/dota2/Ability_spec.lua deleted file mode 100644 index d904e4a..0000000 --- a/spec/dota2/Ability_spec.lua +++ /dev/null @@ -1,112 +0,0 @@ -local create = require("support.factory").create - -local Ability = require("invokation.dota2.Ability") - -local INVOKER = require("invokation.const.invoker") - -describe("dota2.Ability", function() - describe("constructor", function() - it("initializes attributes", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_QUAS, index = 13 }) - local ability = Ability(entity) - - assert.equal(INVOKER.ABILITY_QUAS, ability.name) - assert.equal(13, ability.index) - - entity = create("dota_ability", { name = INVOKER.ABILITY_SUN_STRIKE, index = 31 }) - ability = Ability(entity) - - assert.equal(INVOKER.ABILITY_SUN_STRIKE, ability.name) - assert.equal(31, ability.index) - - entity = create("dota_item", { name = "item_blink" }) - ability = Ability(entity) - - assert.equal("item_blink", ability.name) - assert.equal(nil, ability.index) - end) - end) - - describe("delegation", function() - it("delegates methods to underlying entity", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_QUAS, index = 13 }) - local ability = Ability(entity) - local delegated = { "GetDuration", "GetSpecialValueFor", "IsItem" } - - for _, method in ipairs(delegated) do - local spy = spy.on(entity, method) - - ability[method](ability) - - assert.spy(spy).was.called(1) - end - end) - end) - - describe("#IsOrbAbility", function() - describe("with item", function() - it("returns false", function() - local entity = create("dota_item", { name = "item_blink" }) - local ability = Ability(entity) - - assert.is_false(ability:IsOrbAbility()) - end) - end) - - describe("with non-orb ability", function() - it("returns false", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_SUN_STRIKE, index = 13 }) - local ability = Ability(entity) - - assert.is_false(ability:IsOrbAbility()) - end) - end) - - describe("with orb ability", function() - it("returns true", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_QUAS, index = 13 }) - local ability = Ability(entity) - - assert.is_true(ability:IsOrbAbility()) - end) - end) - end) - - describe("#IsInvocationAbility", function() - describe("with item", function() - it("returns false", function() - local entity = create("dota_item", { name = "item_blink" }) - local ability = Ability(entity) - - assert.is_false(ability:IsInvocationAbility()) - end) - end) - - describe("with non-orb ability", function() - it("returns false", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_SUN_STRIKE, index = 13 }) - local ability = Ability(entity) - - assert.is_false(ability:IsInvocationAbility()) - end) - end) - - describe("with orb ability", function() - it("returns true", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_QUAS, index = 13 }) - local ability = Ability(entity) - - assert.is_true(ability:IsInvocationAbility()) - end) - end) - - describe("with invoke ability", function() - it("returns true", function() - local entity = create("dota_ability", { name = INVOKER.ABILITY_INVOKE, index = 1 }) - local ability = Ability(entity) - - assert.is_true(ability:IsInvocationAbility()) - end) - end) - end) -end) diff --git a/spec/dota2/DamageInstance_spec.lua b/spec/dota2/DamageInstance_spec.lua deleted file mode 100644 index 829c017..0000000 --- a/spec/dota2/DamageInstance_spec.lua +++ /dev/null @@ -1,99 +0,0 @@ -local create = require("support.factory").create - -local Unit = require("invokation.dota2.Unit") -local Ability = require("invokation.dota2.Ability") -local DamageInstance = require("invokation.dota2.DamageInstance") - -local INVOKER = require("invokation.const.invoker") - -describe("dota2.DamageInstance", function() - describe("constructor", function() - it("initializes attributes", function() - local victimHero = create("dota_hero_invoker") - local victim = Unit(victimHero) - local attackerHero = create("dota_hero", { name = "npc_dota_hero_axe" }) - local attacker = Unit(attackerHero) - local inflictorAbility = create("dota_ability", { name = "axe_culling_blade" }) - local inflictor = Ability(inflictorAbility) - local dmg = DamageInstance(victim, 666, attacker, inflictor) - - assert.equal(victim, dmg.victim) - assert.equal(666, dmg.amount) - assert.equal(attacker, dmg.attacker) - assert.equal(inflictor, dmg.inflictor) - assert.equal(DOTA_DAMAGE_CATEGORY_SPELL, dmg.category) - end) - end) - - describe("#VictimName", function() - it("returns the victim's entity name", function() - local victimHero = create("dota_hero_invoker") - local victim = Unit(victimHero) - local attackerHero = create("dota_hero", { name = "npc_dota_hero_axe" }) - local attacker = Unit(attackerHero) - local inflictorAbility = create("dota_ability", { name = "axe_culling_blade" }) - local inflictor = Ability(inflictorAbility) - local dmg = DamageInstance(victim, 666, attacker, inflictor) - - assert.equal(INVOKER.UNIT_NAME, dmg:VictimName()) - end) - end) - - describe("#AttackerName", function() - it("returns the attacker's entity name", function() - local victimHero = create("dota_hero_invoker") - local victim = Unit(victimHero) - local dmg = DamageInstance(victim, 666, nil, nil) - - assert.is_nil(dmg:AttackerName()) - - local attackerHero = create("dota_hero", { name = "npc_dota_hero_axe" }) - local attacker = Unit(attackerHero) - local inflictorAbility = create("dota_ability", { name = "axe_culling_blade" }) - local inflictor = Ability(inflictorAbility) - - dmg = DamageInstance(victim, 666, attacker, inflictor) - - assert.equal("npc_dota_hero_axe", dmg:AttackerName()) - end) - end) - - describe("#AttackerPlayerOwner", function() - it("returns the attacker's player entity", function() - local victimHero = create("dota_hero_invoker") - local victim = Unit(victimHero) - local dmg = DamageInstance(victim, 666, nil, nil) - - assert.is_nil(dmg:AttackerPlayerOwner()) - - local player = create("dota_player") - local attackerHero = create("dota_hero", { name = "npc_dota_hero_axe", playerOwner = player }) - local attacker = Unit(attackerHero) - local inflictorAbility = create("dota_ability", { name = "axe_culling_blade" }) - local inflictor = Ability(inflictorAbility) - - dmg = DamageInstance(victim, 666, attacker, inflictor) - - assert.equal(player, dmg:AttackerPlayerOwner()) - end) - end) - - describe("#InflictorName", function() - it("returns the inflictor's ability name", function() - local victimHero = create("dota_hero_invoker") - local victim = Unit(victimHero) - local dmg = DamageInstance(victim, 666, nil, nil) - - assert.is_nil(dmg:InflictorName()) - - local attackerHero = create("dota_hero", { name = "npc_dota_hero_axe" }) - local attacker = Unit(attackerHero) - local inflictorAbility = create("dota_ability", { name = "axe_culling_blade" }) - local inflictor = Ability(inflictorAbility) - - dmg = DamageInstance(victim, 666, attacker, inflictor) - - assert.equal("axe_culling_blade", dmg:InflictorName()) - end) - end) -end) diff --git a/spec/dota2/DummyTarget_spec.lua b/spec/dota2/DummyTarget_spec.lua deleted file mode 100644 index 858a8ca..0000000 --- a/spec/dota2/DummyTarget_spec.lua +++ /dev/null @@ -1,164 +0,0 @@ -local create = require("support.factory").create - -local Units = require("invokation.dota2.units") -local DummyTarget = require("invokation.dota2.DummyTarget") - -describe("dota2.DummyTarget", function() - local function stubUnitsCreate() - local i = 0 - - stub.new(Units, "Create", function() - i = i + 1 - return create("dota_unit", { name = Units.DUMMY_TARGET, __test_index = i }) - end) - end - - local spawn = create("entity", { name = Units.DUMMY_TARGET_SPAWN }) - - before_each(function() - stub.new(Entities, "FindByName", function() - return spawn - end) - - stubUnitsCreate() - - stub.new(Units, "Destroy", function() - return nil - end) - end) - - after_each(function() - -- selene: allow(incorrect_standard_library_use) - Entities.FindByName:revert() - Units.Create:revert() - Units.Destroy:revert() - end) - - describe("constructor", function() - it("finds and sets the spawn point entity", function() - local dummy = DummyTarget({ spawn = false }) - - assert.equal(spawn, dummy.spawn) - end) - end) - - describe("#IsAlive", function() - it("returns true if the dummy unit exists", function() - local dummy = DummyTarget({ spawn = true }) - - assert.is_true(dummy:IsAlive()) - end) - - it("returns false if the dummy unit doesn't exist", function() - local dummy = DummyTarget({ spawn = false }) - - assert.is_false(dummy:IsAlive()) - end) - end) - - describe("#IsDead", function() - it("returns false if the dummy unit exists", function() - local dummy = DummyTarget({ spawn = true }) - - assert.is_false(dummy:IsDead()) - end) - - it("returns true if the dummy unit doesn't exist", function() - local dummy = DummyTarget({ spawn = false }) - - assert.is_true(dummy:IsDead()) - end) - end) - - describe("#Spawn", function() - it("does NOT spawn the dummy unit if it exists", function() - local dummy = DummyTarget({ spawn = true }) - - assert.not_nil(dummy.entity) - assert.equal(1, dummy.entity.__test_index) - - dummy:Spawn() - - assert.not_nil(dummy.entity) - assert.equal(1, dummy.entity.__test_index) - assert.spy(Units.Create).was.called(1) - assert.spy(Units.Create).was.called_with(Units.DUMMY_TARGET, { - location = spawn:GetAbsOrigin(), - team = DOTA_TEAM_BADGUYS, - }) - end) - - it("spawns the dummy unit if it doesn't exist", function() - local dummy = DummyTarget({ spawn = false }) - - assert.is_nil(dummy.entity) - - dummy:Spawn() - - assert.not_nil(dummy.entity) - assert.equal(1, dummy.entity.__test_index) - assert.spy(Units.Create).was.called(1) - assert.spy(Units.Create).was.called_with(Units.DUMMY_TARGET, { - location = spawn:GetAbsOrigin(), - team = DOTA_TEAM_BADGUYS, - }) - end) - end) - - describe("#Kill", function() - it("does NOT kill the dummy unit if it doesn't exist", function() - local dummy = DummyTarget({ spawn = false }) - - assert.is_nil(dummy.entity) - - dummy:Kill() - - assert.is_nil(dummy.entity) - assert.spy(Units.Destroy).was.not_called() - end) - - it("kills the dummy unit if it exists", function() - local dummy = DummyTarget({ spawn = true }) - - assert.not_nil(dummy.entity) - - dummy:Kill() - - assert.is_nil(dummy.entity) - assert.spy(Units.Destroy).was.called(1) - end) - end) - - describe("#Reset", function() - it("spawns the dummy unit if it doesn't exist", function() - local dummy = DummyTarget({ spawn = false }) - local killSpy = spy.on(dummy, "Kill") - local spawnSpy = spy.on(dummy, "Spawn") - - assert.is_nil(dummy.entity) - - dummy:Reset() - - assert.not_nil(dummy.entity) - assert.equal(1, dummy.entity.__test_index) - assert.spy(killSpy).was.called(1) - assert.spy(spawnSpy).was.called(1) - end) - - it("respawns the dummy unit if it exists", function() - local dummy = DummyTarget({ spawn = true }) - local killSpy = spy.on(dummy, "Kill") - local spawnSpy = spy.on(dummy, "Spawn") - - assert.not_nil(dummy.entity) - assert.equal(1, dummy.entity.__test_index) - - dummy:Reset() - - assert.not_nil(dummy.entity) - assert.equal(2, dummy.entity.__test_index) - assert.spy(killSpy).was.called(1) - assert.spy(spawnSpy).was.called(1) - end) - end) -end) diff --git a/spec/dota2/ability_spec.lua b/spec/dota2/ability_spec.lua new file mode 100644 index 0000000..5eee611 --- /dev/null +++ b/spec/dota2/ability_spec.lua @@ -0,0 +1,118 @@ +local assert = require("luassert") + +local F = require("support.factory") + +local Ability = require("invk.dota2.ability") +local INVOKER = require("invk.const.invoker") + +local AbilityName = INVOKER.AbilityName + +describe("inkv.dota2.Ability", function() + describe("constructor", function() + it("initializes attributes", function() + local entity = F.dota_ability({ name = AbilityName.QUAS, index = 13 }) + local ability = Ability:new(entity) + + assert.equal(AbilityName.QUAS, ability.name) + assert.equal(13, ability.index) + + entity = F.dota_ability({ name = AbilityName.SUN_STRIKE, index = 31 }) + ability = Ability:new(entity) + + assert.equal(AbilityName.SUN_STRIKE, ability.name) + assert.equal(31, ability.index) + + entity = F.dota_item({ name = "item_blink" }) + ability = Ability:new(entity) + + assert.equal("item_blink", ability.name) + assert.equal(nil, ability.index) + end) + end) + + describe("delegation", function() + it("delegates methods to underlying entity", function() + local entity = F.dota_ability({ name = AbilityName.QUAS, index = 13 }) + local ability = Ability:new(entity) + local delegated = { + ["duration"] = "GetDuration", + ["get_special_value_for"] = "GetSpecialValueFor", + } + + for ability_method, ent_method in pairs(delegated) do + local spy = spy.on(entity, ent_method) + + ability[ability_method](ability) + + assert.spy(spy).called(1) + end + end) + end) + + describe(":is_orb_ability", function() + describe("with item", function() + it("returns false", function() + local entity = F.dota_item({ name = "item_blink" }) + local ability = Ability:new(entity) + + assert.is_false(ability:is_orb_ability()) + end) + end) + + describe("with non-orb ability", function() + it("returns false", function() + local entity = F.dota_ability({ name = AbilityName.SUN_STRIKE, index = 13 }) + local ability = Ability:new(entity) + + assert.is_false(ability:is_orb_ability()) + end) + end) + + describe("with orb ability", function() + it("returns true", function() + local entity = F.dota_ability({ name = AbilityName.QUAS, index = 13 }) + local ability = Ability:new(entity) + + assert.is_true(ability:is_orb_ability()) + end) + end) + end) + + describe(":is_invocation_ability", function() + describe("with item", function() + it("returns false", function() + local entity = F.dota_item({ name = "item_blink" }) + local ability = Ability:new(entity) + + assert.is_false(ability:is_invocation_ability()) + end) + end) + + describe("with non-orb ability", function() + it("returns false", function() + local entity = F.dota_ability({ name = AbilityName.SUN_STRIKE, index = 13 }) + local ability = Ability:new(entity) + + assert.is_false(ability:is_invocation_ability()) + end) + end) + + describe("with orb ability", function() + it("returns true", function() + local entity = F.dota_ability({ name = AbilityName.QUAS, index = 13 }) + local ability = Ability:new(entity) + + assert.is_true(ability:is_invocation_ability()) + end) + end) + + describe("with invoke ability", function() + it("returns true", function() + local entity = F.dota_ability({ name = AbilityName.INVOKE, index = 1 }) + local ability = Ability:new(entity) + + assert.is_true(ability:is_invocation_ability()) + end) + end) + end) +end) diff --git a/spec/dota2/damage_instance_spec.lua b/spec/dota2/damage_instance_spec.lua new file mode 100644 index 0000000..44a2e5a --- /dev/null +++ b/spec/dota2/damage_instance_spec.lua @@ -0,0 +1,100 @@ +local assert = require("luassert") + +local F = require("support.factory") + +local Ability = require("invk.dota2.ability") +local DamageInstance = require("invk.dota2.damage_instance") +local INVOKER = require("invk.const.invoker") +local Unit = require("invk.dota2.unit") + +describe("invk.dota2.DamageInstance", function() + describe("constructor", function() + it("initializes attributes", function() + local victim_hero = F.dota_hero_invoker() + local victim = Unit:new(victim_hero) + local attacker_hero = F.dota_hero({ name = "npc_dota_hero_axe" }) + local attacker = Unit:new(attacker_hero) + local inflictor_ability = F.dota_ability({ name = "axe_culling_blade" }) + local inflictor = Ability:new(inflictor_ability) + local dmg = DamageInstance:new(victim, 666, attacker, inflictor) + + assert.equal(victim, dmg.victim) + assert.equal(666, dmg.amount) + assert.equal(attacker, dmg.attacker) + assert.equal(inflictor, dmg.inflictor) + assert.equal(DOTA_DAMAGE_CATEGORY_SPELL, dmg.category) + end) + end) + + describe(":victim_name", function() + it("returns the victim's entity name", function() + local victim_hero = F.dota_hero_invoker() + local victim = Unit:new(victim_hero) + local attacker_hero = F.dota_hero({ name = "npc_dota_hero_axe" }) + local attacker = Unit:new(attacker_hero) + local inflictor_ability = F.dota_ability({ name = "axe_culling_blade" }) + local inflictor = Ability:new(inflictor_ability) + local dmg = DamageInstance:new(victim, 666, attacker, inflictor) + + assert.equal(INVOKER.UNIT_NAME, dmg:victim_name()) + end) + end) + + describe(":attacker_name", function() + it("returns the attacker's entity name", function() + local victim_hero = F.dota_hero_invoker() + local victim = Unit:new(victim_hero) + local dmg = DamageInstance:new(victim, 666, nil, nil) + + assert.is_nil(dmg:attacker_name()) + + local attacker_hero = F.dota_hero({ name = "npc_dota_hero_axe" }) + local attacker = Unit:new(attacker_hero) + local inflictor_ability = F.dota_ability({ name = "axe_culling_blade" }) + local inflictor = Ability:new(inflictor_ability) + + dmg = DamageInstance:new(victim, 666, attacker, inflictor) + + assert.equal("npc_dota_hero_axe", dmg:attacker_name()) + end) + end) + + describe(":attacker_player_owner", function() + it("returns the attacker's player entity", function() + local victim_hero = F.dota_hero_invoker() + local victim = Unit:new(victim_hero) + local dmg = DamageInstance:new(victim, 666, nil, nil) + + assert.is_nil(dmg:attacker_player_owner()) + + local player = F.dota_player() + local attacker_hero = F.dota_hero({ name = "npc_dota_hero_axe", player_owner = player }) + local attacker = Unit:new(attacker_hero) + local inflictor_ability = F.dota_ability({ name = "axe_culling_blade" }) + local inflictor = Ability:new(inflictor_ability) + + dmg = DamageInstance:new(victim, 666, attacker, inflictor) + + assert.equal(player, dmg:attacker_player_owner()) + end) + end) + + describe(":inflictor_name", function() + it("returns the inflictor's ability name", function() + local victim_hero = F.dota_hero_invoker() + local victim = Unit:new(victim_hero) + local dmg = DamageInstance:new(victim, 666, nil, nil) + + assert.is_nil(dmg:inflictor_name()) + + local attacker_hero = F.dota_hero({ name = "npc_dota_hero_axe" }) + local attacker = Unit:new(attacker_hero) + local inflictor_ability = F.dota_ability({ name = "axe_culling_blade" }) + local inflictor = Ability:new(inflictor_ability) + + dmg = DamageInstance:new(victim, 666, attacker, inflictor) + + assert.equal("axe_culling_blade", dmg:inflictor_name()) + end) + end) +end) diff --git a/spec/dota2/dummy_target_spec.lua b/spec/dota2/dummy_target_spec.lua new file mode 100644 index 0000000..0910aff --- /dev/null +++ b/spec/dota2/dummy_target_spec.lua @@ -0,0 +1,169 @@ +local assert = require("luassert") + +local F = require("support.factory") +local Mock = require("support.mock") + +local DummyTarget = require("invk.dota2.dummy_target") +local UNITS = require("invk.const.units") +local units = require("invk.dota2.units") + +describe("invk.dota2.DummyTarget", function() + local mocks = Mock({ + ["units.create"] = function(self) + local i = 0 + + self:stub("units", units, "create", function() + i = i + 1 + + return F.dota_unit({ name = UNITS.DUMMY_TARGET, __test_index = i }) + end) + end, + }) + + local spawn = F.dota_entity({ name = UNITS.DUMMY_TARGET_SPAWN }) + + before_each(function() + mocks:stub("Entities", Entities, "FindByName", function() + return spawn + end) + + mocks:setup("units.create") + + mocks:stub("units", units, "destroy", function() + return nil + end) + end) + + after_each(function() + mocks:reset() + end) + + describe("constructor", function() + it("finds and sets the spawn point entity", function() + local dummy = DummyTarget:new({ spawn = false }) + + assert.equal(spawn, dummy.spawn_ent) + end) + end) + + describe(":is_alive", function() + it("returns true if the dummy unit exists", function() + local dummy = DummyTarget:new({ spawn = true }) + + assert.is_true(dummy:is_alive()) + end) + + it("returns false if the dummy unit doesn't exist", function() + local dummy = DummyTarget:new({ spawn = false }) + + assert.is_false(dummy:is_alive()) + end) + end) + + describe(":is_dead", function() + it("returns false if the dummy unit exists", function() + local dummy = DummyTarget:new({ spawn = true }) + + assert.is_false(dummy:is_dead()) + end) + + it("returns true if the dummy unit doesn't exist", function() + local dummy = DummyTarget:new({ spawn = false }) + + assert.is_true(dummy:is_dead()) + end) + end) + + describe(":spawn", function() + it("does NOT spawn the dummy unit if it exists", function() + local dummy = DummyTarget:new({ spawn = true }) + + assert.is_not_nil(dummy.entity) + assert.equal(1, dummy.entity.__test_index) + + dummy:spawn() + + assert.is_not_nil(dummy.entity) + assert.equal(1, dummy.entity.__test_index) + + mocks:assert("units", "create").called(1) + mocks:assert("units", "create").called_with(UNITS.DUMMY_TARGET, { + location = spawn:GetAbsOrigin(), + team = DOTA_TEAM_BADGUYS, + }) + end) + + it("spawns the dummy unit if it doesn't exist", function() + local dummy = DummyTarget:new({ spawn = false }) + + assert.is_nil(dummy.entity) + + dummy:spawn() + + assert.is_not_nil(dummy.entity) + assert.equal(1, dummy.entity.__test_index) + mocks:assert("units", "create").called(1) + mocks:assert("units", "create").called_with(UNITS.DUMMY_TARGET, { + location = spawn:GetAbsOrigin(), + team = DOTA_TEAM_BADGUYS, + }) + end) + end) + + describe(":kill", function() + it("does NOT kill the dummy unit if it doesn't exist", function() + local dummy = DummyTarget:new({ spawn = false }) + + assert.is_nil(dummy.entity) + + dummy:kill() + + assert.is_nil(dummy.entity) + mocks:assert("units", "destroy").called(0) + end) + + it("kills the dummy unit if it exists", function() + local dummy = DummyTarget:new({ spawn = true }) + + assert.is_not_nil(dummy.entity) + + dummy:kill() + + assert.is_nil(dummy.entity) + mocks:assert("units", "destroy").called(1) + end) + end) + + describe(":reset", function() + it("spawns the dummy unit if it doesn't exist", function() + local dummy = DummyTarget:new({ spawn = false }) + + mocks:spy("DummyTarget", dummy, { "kill", "spawn" }) + + assert.is_nil(dummy.entity) + + dummy:reset() + + assert.is_not_nil(dummy.entity) + assert.equal(1, dummy.entity.__test_index) + mocks:assert("DummyTarget", "kill").called(1) + mocks:assert("DummyTarget", "spawn").called(1) + end) + + it("respawns the dummy unit if it exists", function() + local dummy = DummyTarget:new({ spawn = true }) + + mocks:spy("DummyTarget", dummy, { "kill", "spawn" }) + + assert.is_not_nil(dummy.entity) + assert.equal(1, dummy.entity.__test_index) + + dummy:reset() + + assert.is_not_nil(dummy.entity) + assert.equal(2, dummy.entity.__test_index) + mocks:assert("DummyTarget", "kill").called(1) + mocks:assert("DummyTarget", "spawn").called(1) + end) + end) +end) diff --git a/spec/helper.lua b/spec/helper.lua index 30284e9..004285c 100644 --- a/spec/helper.lua +++ b/spec/helper.lua @@ -1,7 +1,7 @@ require("support.luassert_ext") +require("support.game_mode") require("support.dota2") -require("support.factories") -local Timers = require("invokation.dota2.timers") +local Timers = require("invk.dota2.timers") -Timers:Start() +Timers:start() diff --git a/spec/lang/delegation_spec.lua b/spec/lang/delegation_spec.lua deleted file mode 100644 index 9bbf138..0000000 --- a/spec/lang/delegation_spec.lua +++ /dev/null @@ -1,54 +0,0 @@ -local class = require("pl.class") -local delegation = require("invokation.lang.delegation") - -describe("delegation", function() - describe(".delegate", function() - local Engine = class() - - function Engine:start() - return "engine started" - end - - function Engine:shutdown() - return "engine stopped" - end - - local Car = class() - - function Car:_init(e) - self.engine = e - end - - delegation.delegate(Car, "engine", { "start", "shutdown" }) - - local engine, car - local spyStart, spyShutdown - - before_each(function() - engine = Engine() - car = Car(engine) - spyStart = spy.on(engine, "start") - spyShutdown = spy.on(engine, "shutdown") - end) - - after_each(function() - spyStart:revert() - spyShutdown:revert() - end) - - it("creates delegated methods in the target class object", function() - assert.is_function(Car.start) - assert.is_function(Car.shutdown) - assert.is_function(car.start) - assert.is_function(car.shutdown) - end) - - it("creates methods that delegate to the named attribute", function() - assert.equal("engine started", car:start()) - assert.equal("engine stopped", car:shutdown()) - - assert.spy(spyStart).was.called_with(engine) - assert.spy(spyShutdown).was.called_with(engine) - end) - end) -end) diff --git a/spec/lang/function_spec.lua b/spec/lang/function_spec.lua index 0cd3b44..c59b6be 100644 --- a/spec/lang/function_spec.lua +++ b/spec/lang/function_spec.lua @@ -1,30 +1,38 @@ -local func = require("invokation.lang.function") +local assert = require("luassert") -describe("function", function() +local Mock = require("support.mock") + +local func = require("invk.lang.function") + +describe("invk.lang.function", function() describe(".lookupbyname", function() it("creates a wrapper function that performs method lookup by name", function() + local mocks = Mock() local t = {} t.greet = function(name) return "Greetings, " .. name end - local greetSpy = spy.on(t, "greet") + mocks:spy("t", t, "greet") + local fn = func.lookupbyname(t, "greet") assert.is_function(fn) - assert.not_equal(t.greet, fn) + assert.are_not_equal(t.greet, fn) assert.equal("Greetings, Alice", fn("Alice")) - assert.spy(greetSpy).was.called_with("Alice") + mocks:assert("t", "greet").called_with("Alice") + + mocks:reset() t.greet = function(name) return "Welcome, " .. name end - greetSpy = spy.on(t, "greet") + mocks:spy("t", t, "greet") assert.equal("Welcome, Bob", fn("Bob")) - assert.spy(greetSpy).was.called_with("Bob") + mocks:assert("t", "greet").called_with("Bob") end) end) end) diff --git a/spec/lang/random_spec.lua b/spec/lang/random_spec.lua index ededce7..f275960 100644 --- a/spec/lang/random_spec.lua +++ b/spec/lang/random_spec.lua @@ -1,40 +1,40 @@ -local rand = require("invokation.lang.random") +local Mock = require("support.mock") -describe("function", function() +local rand = require("invk.lang.random") + +describe("invk.lang.random", function() describe(".seed", function() - local spyMathRandomSeed + local mocks = Mock() before_each(function() - spyMathRandomSeed = spy.on(math, "randomseed") + mocks:spy("math", math, "randomseed") end) after_each(function() - spyMathRandomSeed:revert() + mocks:revert("math", "randomseed") end) it("seeds `math`s random with the given value", function() rand.seed(13) - assert.spy(spyMathRandomSeed).was.called_with(13) + mocks:assert("math", "randomseed").called_with(13) end) describe("with default value", function() - local stubTime - before_each(function() -- selene: allow(global_usage) - stubTime = stub.new(_G, "Time", 31) + mocks:stub("_G", _G, "Time", 31) end) after_each(function() - stubTime:revert() + mocks:revert("_G", "Time") end) it("seeds `math`s random with a default value", function() rand.seed() - assert.stub(stubTime).was_called(1) - assert.spy(spyMathRandomSeed).was.called_with(31) + mocks:assert("_G", "Time").called(1) + mocks:assert("math", "randomseed").called_with(31) end) end) end) diff --git a/spec/support/combo/helpers.lua b/spec/support/combo/helpers.lua new file mode 100644 index 0000000..9c3b585 --- /dev/null +++ b/spec/support/combo/helpers.lua @@ -0,0 +1,13 @@ +local m = require("moses") + +local M = {} + +--- @param steps invk.combo.ComboStep[] +--- @return integer[] +function M.steps_ids(steps) + return m.map(steps, function(s) + return s.id + end) +end + +return M diff --git a/spec/support/dota2/CBaseAnimating.lua b/spec/support/dota2/CBaseAnimating.lua deleted file mode 100644 index b8f069a..0000000 --- a/spec/support/dota2/CBaseAnimating.lua +++ /dev/null @@ -1,8 +0,0 @@ -local class = require("pl.class") - --- selene: allow(incorrect_standard_library_use) -CBaseAnimating = class(CBaseEntity) - -function CBaseAnimating:_init(attributes) - self:super(attributes or {}) -end diff --git a/spec/support/dota2/CBaseEntity.lua b/spec/support/dota2/CBaseEntity.lua index 8081b59..d368b3f 100644 --- a/spec/support/dota2/CBaseEntity.lua +++ b/spec/support/dota2/CBaseEntity.lua @@ -1,30 +1,39 @@ -local m = require("moses") local class = require("pl.class") -local Factory = require("support.factory") - --- selene: allow(incorrect_standard_library_use) -CBaseEntity = class() - -CBaseEntity.entIdx = 0 +local m = require("moses") +local F = require("support.factory") + +--- @class support.dota2.CBaseEntity : CBaseEntity +--- @field name string +--- @field classname string +--- @field entindex EntityIndex +--- @field team DOTATeam_t +--- @field origin Vector +--- @field removed boolean +--- @field alive boolean +local CBaseEntity = class() + +--- @class support.dota2.CBaseEntity_attributes +--- @field name string +--- @field classname? string +--- @field entindex? EntityIndex +--- @field team? DOTATeam_t +--- @field origin? Vector +--- @field removed? boolean +--- @field alive? boolean + +--- @param attributes support.dota2.CBaseEntity_attributes function CBaseEntity:_init(attributes) - m.extend(self, attributes or {}) + attributes.classname = attributes.classname or attributes.name + attributes.entindex = attributes.entindex or test_NextEntIndex() + attributes.team = attributes.team or DOTA_TEAM_NOTEAM + attributes.origin = attributes.origin or F.vector({ 0, 0, 0 }) + attributes.removed = attributes.removed == nil and false or attributes.removed + attributes.alive = attributes.alive == nil and true or attributes.alive - if self.entindex == nil then - CBaseEntity.entIdx = CBaseEntity.entIdx + 1 - self.entindex = CBaseEntity.entIdx - end + m.extend(self, attributes) - self.team = self.team or DOTA_TEAM_NOTEAM - self.origin = self.origin or Factory.create("vector", { 0, 0, 0 }) - - if self.removed == nil then - self.removed = false - end - - if self.alive == nil then - self.alive = true - end + test_SetEntity(self.entindex, self) end function CBaseEntity:GetEntityIndex() @@ -75,5 +84,7 @@ function CBaseEntity:GetTeamNumber() return self.team end -function CBaseEntity:StopSound(_soundEvent) end +function CBaseEntity:StopSound(_event) end function CBaseEntity:SetThink() end + +return CBaseEntity diff --git a/spec/support/dota2/CBaseFlex.lua b/spec/support/dota2/CBaseFlex.lua deleted file mode 100644 index 5130821..0000000 --- a/spec/support/dota2/CBaseFlex.lua +++ /dev/null @@ -1,8 +0,0 @@ -local class = require("pl.class") - --- selene: allow(incorrect_standard_library_use) -CBaseFlex = class(CBaseAnimating) - -function CBaseFlex:_init(attributes) - self:super(attributes or {}) -end diff --git a/spec/support/dota2/CBasePlayer.lua b/spec/support/dota2/CBasePlayer.lua deleted file mode 100644 index 59bbe43..0000000 --- a/spec/support/dota2/CBasePlayer.lua +++ /dev/null @@ -1,8 +0,0 @@ -local class = require("pl.class") - --- selene: allow(incorrect_standard_library_use) -CBasePlayer = class(CBaseAnimating) - -function CBasePlayer:_init(attributes) - self:super(attributes or {}) -end diff --git a/spec/support/dota2/CDOTABaseAbility.lua b/spec/support/dota2/CDOTABaseAbility.lua index ca42020..ecc1aed 100644 --- a/spec/support/dota2/CDOTABaseAbility.lua +++ b/spec/support/dota2/CDOTABaseAbility.lua @@ -1,13 +1,36 @@ -local m = require("moses") local class = require("pl.class") +local m = require("moses") --- selene: allow(incorrect_standard_library_use) -CDOTABaseAbility = class(CBaseEntity) - -local DEFAULTS = { level = 0, MaxLevel = 1 } - +local CBaseEntity = require("support.dota2.CBaseEntity") + +--- @class support.dota2.CDOTABaseAbility : support.dota2.CBaseEntity, CDOTABaseAbility +--- @field index integer +--- @field is_item boolean +--- @field level integer +--- @field special { [string]: any } +--- @field AbilityBehavior string +--- @field AbilityDuration number +--- @field MaxLevel integer +local CDOTABaseAbility = class(CBaseEntity) + +--- @class (partial) support.dota2.CDOTABaseAbility_attributes : support.dota2.CBaseEntity_attributes +--- @field index? integer +--- @field is_item? boolean +--- @field level? integer +--- @field special? { [string]: any } +--- @field AbilityBehavior? string +--- @field AbilityDuration? number +--- @field MaxLevel? integer + +--- @type support.dota2.CDOTABaseAbility_attributes +local ATTRIBUTES = { + level = 0, + MaxLevel = 1, +} + +--- @param attributes support.dota2.CDOTABaseAbility_attributes function CDOTABaseAbility:_init(attributes) - self:super(m.extend({}, DEFAULTS, attributes or {})) + self:super(m.extend({}, ATTRIBUTES, attributes or {})) end function CDOTABaseAbility:GetAbilityName() @@ -38,13 +61,27 @@ function CDOTABaseAbility:SetLevel(level) self.level = level end +function CDOTABaseAbility:IsItem() + return self.is_item +end + function CDOTABaseAbility:UpgradeAbility(_supressSpeech) - if self:CanAbilityBeUpgraded() then + if self:CanAbilityBeUpgraded() == ABILITY_CAN_BE_UPGRADED then self:SetLevel(self:GetLevel() + 1) end end function CDOTABaseAbility:CanAbilityBeUpgraded() + if self.level == self.MaxLevel then + return ABILITY_CANNOT_BE_UPGRADED_AT_MAX + end + + if type(self.AbilityBehavior) ~= "string" then + -- error(string.format("CDOTABaseAbility: 'AbilityBehavior' is not set (name=%q)", self.name)) + -- hack: talent abilities + return ABILITY_CAN_BE_UPGRADED + end + if self.AbilityBehavior:match("DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE") then return ABILITY_NOT_LEARNABLE end @@ -53,10 +90,6 @@ function CDOTABaseAbility:CanAbilityBeUpgraded() return ABILITY_CANNOT_BE_UPGRADED_NOT_UPGRADABLE end - if self.level == self.MaxLevel then - return ABILITY_CANNOT_BE_UPGRADED_AT_MAX - end - return ABILITY_CAN_BE_UPGRADED end @@ -65,3 +98,5 @@ function CDOTABaseAbility:GetSpecialValueFor(key) end function CDOTABaseAbility:EndCooldown() end + +return CDOTABaseAbility diff --git a/spec/support/dota2/CDOTABaseGameMode.lua b/spec/support/dota2/CDOTABaseGameMode.lua index 62f2614..10e7f24 100644 --- a/spec/support/dota2/CDOTABaseGameMode.lua +++ b/spec/support/dota2/CDOTABaseGameMode.lua @@ -1,4 +1,12 @@ local class = require("pl.class") --- selene: allow(incorrect_standard_library_use) -CDOTABaseGameMode = class(CBaseEntity) +local CBaseEntity = require("support.dota2.CBaseEntity") + +--- @class support.dota2.CDOTABaseGameMode : support.dota2.CBaseEntity, CDOTABaseGameMode +local CDOTABaseGameMode = class(CBaseEntity) + +function CDOTABaseGameMode:_init() + self:super({ name = "CDOTABaseGameMode" }) +end + +return CDOTABaseGameMode diff --git a/spec/support/dota2/CDOTAPlayer.lua b/spec/support/dota2/CDOTAPlayer.lua deleted file mode 100644 index f132853..0000000 --- a/spec/support/dota2/CDOTAPlayer.lua +++ /dev/null @@ -1,18 +0,0 @@ -local class = require("pl.class") - --- selene: allow(incorrect_standard_library_use) -CDOTAPlayer = class(CBasePlayer) - -function CDOTAPlayer:_init(attributes) - self:super(attributes or {}) -end - -function CDOTAPlayer:GetPlayerID() - return self.id -end - -function CDOTAPlayer:GetAssignedHero() - return self.hero -end - -function CDOTAPlayer:SetMusicStatus(_status, _intensity) end diff --git a/spec/support/dota2/CDOTAPlayerController.lua b/spec/support/dota2/CDOTAPlayerController.lua new file mode 100644 index 0000000..cb52058 --- /dev/null +++ b/spec/support/dota2/CDOTAPlayerController.lua @@ -0,0 +1,36 @@ +local class = require("pl.class") +local m = require("moses") + +local CBaseEntity = require("support.dota2.CBaseEntity") + +--- @class support.dota2.CDOTAPlayerController : support.dota2.CBaseEntity, CDOTAPlayerController +--- @field player_id PlayerID +--- @field hero support.dota2.CDOTA_BaseNPC_Hero +local CDOTAPlayerController = class(CBaseEntity) + +--- @class support.dota2.CDOTAPlayerController_attributes : support.dota2.CBaseEntity_attributes +--- @field name? string +--- @field player_id? PlayerID +--- @field hero support.dota2.CDOTA_BaseNPC_Hero + +--- @type support.dota2.CDOTAPlayerController_attributes +local ATTRIBUTES = { + name = "dota_player", + player_id = 13, +} + +function CDOTAPlayerController:_init(attributes) + self:super(m.extend(ATTRIBUTES, attributes)) +end + +function CDOTAPlayerController:GetPlayerID() + return self.player_id +end + +function CDOTAPlayerController:GetAssignedHero() + return self.hero +end + +function CDOTAPlayerController:SetMusicStatus(_status, _intensity) end + +return CDOTAPlayerController diff --git a/spec/support/dota2/CDOTA_BaseNPC.lua b/spec/support/dota2/CDOTA_BaseNPC.lua index bbc6014..64d51f0 100644 --- a/spec/support/dota2/CDOTA_BaseNPC.lua +++ b/spec/support/dota2/CDOTA_BaseNPC.lua @@ -1,25 +1,90 @@ -local m = require("moses") local class = require("pl.class") -local Factory = require("support.factory") - -local INVENTORY = require("invokation.const.inventory") - --- selene: allow(incorrect_standard_library_use) -CDOTA_BaseNPC = class(CBaseFlex) - -local DEFAULTS = { hasInventory = false, level = 1, maxHealth = 0, health = 0, maxMana = 0, mana = 0 } +local m = require("moses") +local CBaseEntity = require("support.dota2.CBaseEntity") +local F = require("support.factory") + +local INVENTORY = require("invk.const.inventory") + +--- @class support.dota2.CDOTA_BaseNPC : support.dota2.CBaseEntity, CDOTA_BaseNPC +--- @field level integer +--- @field max_health integer +--- @field health integer +--- @field max_mana integer +--- @field mana integer +--- @field abilities { n: integer, [integer]: support.dota2.CDOTABaseAbility } +--- @field talent_ability_start integer +--- @field talent_ability_end integer +--- @field has_inventory boolean +--- @field inventory { [DOTAScriptInventorySlot_t]: support.dota2.CDOTA_Item } +--- @field player_owner support.dota2.CDOTAPlayerController +local CDOTA_BaseNPC = class(CBaseEntity) + +--- @class (partial) support.dota2.CDOTA_BaseNPC_attributes : support.dota2.CBaseEntity_attributes +--- @field has_inventory? boolean +--- @field level? integer +--- @field max_health? integer +--- @field health? integer +--- @field max_mana? integer +--- @field mana? integer +--- @field [string] any + +--- @type support.dota2.CDOTA_BaseNPC_attributes +local ATTRIBUTES = { + has_inventory = false, + level = 1, + max_health = 1, + health = 1, + max_mana = 1, + mana = 1, +} + +local ABILITY_KEY_PATT = "^Ability(%d+)$" + +--- @param attributes support.dota2.CDOTA_BaseNPC_attributes function CDOTA_BaseNPC:_init(attributes) - local baseAttributes = { abilities = {}, inventory = {} } - self:super(m.extend(baseAttributes, DEFAULTS, attributes or {})) + --- @type support.dota2.CDOTA_BaseNPC_attributes + local attrs = m.extend({}, ATTRIBUTES, attributes) + + self:super(attrs) + + self.abilities = { n = 0 } + self.inventory = {} + self.talent_ability_start = 0 + self.talent_ability_end = 0 + + for key, value in pairs(attrs) do + if key == "AbilityTalentStart" then + self.talent_ability_start = value + else + local index_str = key:match(ABILITY_KEY_PATT) + local index = tonumber(index_str) --[[@as integer?]] + + if index and type(value) == "string" then + if value == "" then + self.talent_ability_end = index - 1 + else + self.abilities[index] = self:create_ability(value, index) + + if index > self.abilities.n then + self.abilities.n = index + end + end + end + end + end end function CDOTA_BaseNPC:GetUnitName() return self:GetName() end +function CDOTA_BaseNPC:IsHero() + return self:GetName():match("^npc_dota_hero_") ~= nil +end + function CDOTA_BaseNPC:GetPlayerOwner() - return self.playerOwner + return self.player_owner end function CDOTA_BaseNPC:ForceKill(reincarnate) @@ -31,12 +96,12 @@ function CDOTA_BaseNPC:GetLevel() end -- not part of Dota2's scripting API -function CDOTA_BaseNPC:SetLevel(level) +function CDOTA_BaseNPC:set_level(level) self.level = level end function CDOTA_BaseNPC:GetMaxHealth() - return self.maxHealth + return self.max_health end function CDOTA_BaseNPC:GetHealth() @@ -44,12 +109,13 @@ function CDOTA_BaseNPC:GetHealth() end function CDOTA_BaseNPC:Heal(amount, _source) - local health = self.health + amount - self.health = health > self.maxHealth and self.maxHealth or health + local health = self.health + amount --[[@as integer]] + + self.health = health > self.max_health and self.max_health or health end function CDOTA_BaseNPC:GetMaxMana() - return self.maxMana + return self.max_mana end function CDOTA_BaseNPC:GetMana() @@ -57,12 +123,13 @@ function CDOTA_BaseNPC:GetMana() end function CDOTA_BaseNPC:GiveMana(amount) - local mana = self.mana + amount - self.mana = mana > self.maxMana and self.maxMana or mana + local mana = self.mana + amount --[[@as integer]] + + self.mana = mana > self.max_mana and self.max_mana or mana end function CDOTA_BaseNPC:GetAbilityCount() - return 24 + return self.abilities.n end function CDOTA_BaseNPC:GetAbilityByIndex(i) @@ -72,6 +139,7 @@ end function CDOTA_BaseNPC:FindAbilityByName(name) for i = 1, self:GetAbilityCount() do local ability = self.abilities[i] + if ability ~= nil and ability:GetAbilityName() == name then return ability end @@ -80,6 +148,23 @@ function CDOTA_BaseNPC:FindAbilityByName(name) return nil end +--- @param name string +--- @param index integer +--- @return CDOTABaseAbility +function CDOTA_BaseNPC:create_ability(name, index) + local options = {} + + if self:IsHero() then + options.hero = self:GetUnitName() + end + + local ability = F.dota_ability({ name = name }, options) + + ability:SetAbilityIndex(index) + + return ability +end + function CDOTA_BaseNPC:AddAbility(name) local ability = self:FindAbilityByName(name) @@ -87,20 +172,24 @@ function CDOTA_BaseNPC:AddAbility(name) return ability end - ability = Factory.create("dota_ability", { name = name }) + local index = self.abilities.n + 1 + + ability = self:create_ability(name, index) - table.insert(self.abilities, ability) - ability:SetAbilityIndex(#self.abilities) + self.abilities[index] = ability + self.abilities.n = index return ability end function CDOTA_BaseNPC:HasInventory() - return self.hasInventory + return self.has_inventory end -- not part of Dota2's scripting API -function CDOTA_BaseNPC:findInventorySlot(predicate) +--- @param predicate fun(item: support.dota2.CDOTA_Item?, slot: DOTAScriptInventorySlot_t): boolean +--- @return DOTAScriptInventorySlot_t? +function CDOTA_BaseNPC:find_inventory_slot(predicate) if not self:HasInventory() then return nil end @@ -115,28 +204,30 @@ function CDOTA_BaseNPC:findInventorySlot(predicate) end -- not part of Dota2's scripting API -function CDOTA_BaseNPC:findFreeInventorySlot() - return self:findInventorySlot(function(item) - return item == nil +--- @return DOTAScriptInventorySlot_t? +function CDOTA_BaseNPC:find_free_inventory_slot() + return self:find_inventory_slot(function(i) + return i == nil end) end -- not part of Dota2's scripting API -function CDOTA_BaseNPC:findItemSlot(item) - return self:findInventorySlot(function(it) - return it ~= nil and (it:GetEntityIndex() == item:GetEntityIndex()) +--- @return DOTAScriptInventorySlot_t? +function CDOTA_BaseNPC:find_item_slot(item) + return self:find_inventory_slot(function(i) + return i ~= nil and (i:GetEntityIndex() == item:GetEntityIndex()) end) end -- not part of Dota2's scripting API -function CDOTA_BaseNPC:findItemSlotByName(name) - return self:findInventorySlot(function(it) - return it ~= nil and (it:GetAbilityName() == name) +function CDOTA_BaseNPC:find_item_slot_by_name(name) + return self:find_inventory_slot(function(i) + return i ~= nil and (i:GetAbilityName() == name) end) end function CDOTA_BaseNPC:HasItemInInventory(name) - return self:findItemSlotByName(name) ~= nil + return self:find_item_slot_by_name(name) ~= nil end function CDOTA_BaseNPC:GetItemInSlot(slot) @@ -152,13 +243,13 @@ function CDOTA_BaseNPC:AddItemByName(name) return nil end - local slot = self:findFreeInventorySlot() + local slot = self:find_free_inventory_slot() if slot == nil then return nil end - self.inventory[slot] = CDOTA_Item({ name = name }) + self.inventory[slot] = F.dota_item({ name = name }) return self.inventory[slot] end @@ -168,18 +259,23 @@ function CDOTA_BaseNPC:RemoveItem(item) return end - local slot = self:findItemSlot(item) + local slot = self:find_item_slot(item) if slot ~= nil then self.inventory[slot] = nil end - - return slot end -function CDOTA_BaseNPC:SetIdleAcquire(value) - self.idleAcquire = value +function CDOTA_BaseNPC:Hold() end +function CDOTA_BaseNPC:Purge( + _removeBuffs, + _removeDebuffs, + _frameOnly, + _removeStuns, + _removeExceptions +) end -function CDOTA_BaseNPC:Hold() end -function CDOTA_BaseNPC:Purge(_removeBuffs, _removeDebuffs, _frameOnly, _removeStuns, _removeExceptions) end +function CDOTA_BaseNPC:SetIdleAcquire(_value) end + +return CDOTA_BaseNPC diff --git a/spec/support/dota2/CDOTA_BaseNPC_Hero.lua b/spec/support/dota2/CDOTA_BaseNPC_Hero.lua index 4d5e1ad..19ed51b 100644 --- a/spec/support/dota2/CDOTA_BaseNPC_Hero.lua +++ b/spec/support/dota2/CDOTA_BaseNPC_Hero.lua @@ -1,21 +1,32 @@ -local m = require("moses") local class = require("pl.class") +local m = require("moses") -local HeroKeyValues = require("invokation.dota2.kv.HeroKeyValues") +local CDOTA_BaseNPC = require("support.dota2.CDOTA_BaseNPC") -local LIMITS = require("invokation.const.limits") +local LIMITS = require("invk.const.limits") --- selene: allow(incorrect_standard_library_use) -CDOTA_BaseNPC_Hero = class(CDOTA_BaseNPC) +--- @class support.dota2.CDOTA_BaseNPC_Hero : support.dota2.CDOTA_BaseNPC, CDOTA_BaseNPC_Hero +--- @field ability_points integer +--- @field gold_reliable integer +--- @field gold_unreliable integer +local CDOTA_BaseNPC_Hero = class(CDOTA_BaseNPC) -local ATTRIBUTES = { hasInventory = true } -local DEFAULTS = { abilityPoints = 1, goldReliable = 0, goldUnreliable = 0 } +--- @class (partial) support.dota2.CDOTA_BaseNPC_Hero_attributes : support.dota2.CDOTA_BaseNPC_attributes +--- @field ability_points? integer +--- @field gold_reliable? integer +--- @field gold_unreliable? integer -function CDOTA_BaseNPC_Hero:_init(attributes) - attributes = m.extend({}, ATTRIBUTES, DEFAULTS, attributes or {}) +--- @type support.dota2.CDOTA_BaseNPC_Hero_attributes +local ATTRIBUTES = { + has_inventory = true, + ability_points = 1, + gold_reliable = 0, + gold_unreliable = 0, +} - self:super(attributes) - self.__attributes = attributes +--- @param attributes support.dota2.CDOTA_BaseNPC_Hero_attributes +function CDOTA_BaseNPC_Hero:_init(attributes) + self:super(m.extend({}, ATTRIBUTES, attributes)) end function CDOTA_BaseNPC_Hero:HeroLevelUp(_playEffects) @@ -23,62 +34,76 @@ function CDOTA_BaseNPC_Hero:HeroLevelUp(_playEffects) return end - self:SetLevel(self:GetLevel() + 1) + self:set_level(self:GetLevel() + 1) if self:GetLevel() == LIMITS.MAX_HERO_LEVEL then - self:upgradeAllTalents() + self:max_level() else self:SetAbilityPoints(self:GetAbilityPoints() + 1) end end function CDOTA_BaseNPC_Hero:GetGold() - return self.goldReliable + self.goldUnreliable + return self.gold_reliable + self.gold_unreliable end function CDOTA_BaseNPC_Hero:SetGold(amount, isReliable) if isReliable then - self.goldReliable = amount + self.gold_reliable = amount else - self.goldUnreliable = amount + self.gold_unreliable = amount end end function CDOTA_BaseNPC_Hero:ModifyGold(amount, isReliable, _reason) if isReliable then - self.goldReliable = self.goldReliable + amount + self.gold_reliable = self.gold_reliable + amount else - self.goldUnreliable = self.goldUnreliable + amount + self.gold_unreliable = self.gold_unreliable + amount end return self:GetGold() end function CDOTA_BaseNPC_Hero:GetAbilityPoints() - return self.abilityPoints + return self.ability_points end function CDOTA_BaseNPC_Hero:SetAbilityPoints(points) - self.abilityPoints = points + self.ability_points = points end +--- @param ability CDOTABaseAbility function CDOTA_BaseNPC_Hero:UpgradeAbility(ability) - if self:GetAbilityPoints() > 0 then + if self:GetAbilityPoints() > 0 and ability:CanAbilityBeUpgraded() == ABILITY_CAN_BE_UPGRADED then ability:UpgradeAbility(false) self:SetAbilityPoints(self:GetAbilityPoints() - 1) end end -- not part of Dota2's scripting API -function CDOTA_BaseNPC_Hero:upgradeAllTalents() - local kv = HeroKeyValues(self:GetName(), self.__attributes) - local talents = kv:Talents() +function CDOTA_BaseNPC_Hero:max_level() + local extra_points = LIMITS.MAX_HERO_LEVEL - self:GetLevel() - 1 - for _, value in pairs(talents) do - local ability = self:FindAbilityByName(value) + if extra_points > 0 then + self:SetAbilityPoints(self:GetAbilityPoints() + extra_points) + end + + self:set_level(LIMITS.MAX_HERO_LEVEL) - if ability ~= nil then - self:UpgradeAbility(ability) + for i = 1, self:GetAbilityCount() do + local ability = self:GetAbilityByIndex(i) + + if ability then + while + self:GetAbilityPoints() > 0 + and ability:CanAbilityBeUpgraded() == ABILITY_CAN_BE_UPGRADED + and ability:GetLevel() < ability:GetMaxLevel() + do + self:UpgradeAbility(ability) + end end end end + +return CDOTA_BaseNPC_Hero diff --git a/spec/support/dota2/CDOTA_Item.lua b/spec/support/dota2/CDOTA_Item.lua index c421ae6..d9db984 100644 --- a/spec/support/dota2/CDOTA_Item.lua +++ b/spec/support/dota2/CDOTA_Item.lua @@ -1,10 +1,19 @@ local class = require("pl.class") --- selene: allow(incorrect_standard_library_use) -CDOTA_Item = class(CDOTABaseAbility) +local CDOTABaseAbility = require("support.dota2.CDOTABaseAbility") +--- @class support.dota2.CDOTA_Item : support.dota2.CDOTABaseAbility, CDOTA_Item +--- @field slot DOTAScriptInventorySlot_t +--- @field purchaser support.dota2.CDOTA_BaseNPC_Hero +local CDOTA_Item = class(CDOTABaseAbility) + +--- @class support.dota2.CDOTA_Item_attributes : support.dota2.CDOTABaseAbility_attributes +--- @field slot? DOTAScriptInventorySlot_t +--- @field purchaser? support.dota2.CDOTA_BaseNPC_Hero + +--- @param attributes support.dota2.CDOTA_Item_attributes function CDOTA_Item:_init(attributes) - self:super(attributes or {}) + self:super(attributes) end function CDOTA_Item:GetItemSlot() @@ -14,3 +23,5 @@ end function CDOTA_Item:GetPurchaser() return self.purchaser end + +return CDOTA_Item diff --git a/spec/support/dota2/CustomGameEventManager.lua b/spec/support/dota2/CustomGameEventManager.lua index cb614b9..007d840 100644 --- a/spec/support/dota2/CustomGameEventManager.lua +++ b/spec/support/dota2/CustomGameEventManager.lua @@ -1,4 +1,3 @@ --- selene: allow(incorrect_standard_library_use) CustomGameEventManager = {} function CustomGameEventManager:RegisterListener(_event, _callback) end diff --git a/spec/support/dota2/Entities.lua b/spec/support/dota2/Entities.lua index 36513dd..9fa31f2 100644 --- a/spec/support/dota2/Entities.lua +++ b/spec/support/dota2/Entities.lua @@ -1,4 +1,3 @@ --- selene: allow(incorrect_standard_library_use) Entities = {} function Entities:FindByName(_startEnt, _name) diff --git a/spec/support/dota2/EntityFramework.lua b/spec/support/dota2/EntityFramework.lua index 1db0afb..15a27e8 100644 --- a/spec/support/dota2/EntityFramework.lua +++ b/spec/support/dota2/EntityFramework.lua @@ -1,4 +1,3 @@ --- selene: allow(incorrect_standard_library_use) EntityFramework = {} function EntityFramework:CreateEntity(_className, ent) diff --git a/spec/support/dota2/GameRules.lua b/spec/support/dota2/GameRules.lua index bc5e63f..f0f9387 100644 --- a/spec/support/dota2/GameRules.lua +++ b/spec/support/dota2/GameRules.lua @@ -1,12 +1,13 @@ --- selene: allow(incorrect_standard_library_use) +local CDOTABaseGameMode = require("support.dota2.CDOTABaseGameMode") + GameRules = {} function GameRules:GetGameModeEntity() - if self.gameMode == nil then - self.gameMode = CDOTABaseGameMode() + if self.game_mode == nil then + self.game_mode = CDOTABaseGameMode() end - return self.gameMode + return self.game_mode end function GameRules:GetGameTime() diff --git a/spec/support/dota2/PlayerResource.lua b/spec/support/dota2/PlayerResource.lua index dfacf69..324fbcd 100644 --- a/spec/support/dota2/PlayerResource.lua +++ b/spec/support/dota2/PlayerResource.lua @@ -1,12 +1,11 @@ --- selene: allow(incorrect_standard_library_use) PlayerResource = {} -function PlayerResource:GetSteamAccountID(playerId) - return playerId +function PlayerResource:GetSteamAccountID(player_id) + return player_id end -function PlayerResource:GetSteamID(playerId) - return playerId +function PlayerResource:GetSteamID(player_id) + return player_id end -function PlayerResource:ReplaceHeroWith(_playerId, _heroName, _gold, _xp) end +function PlayerResource:ReplaceHeroWith(_player_id, _hero_name, _gold, _xp) end diff --git a/spec/support/dota2/Vector.lua b/spec/support/dota2/Vector.lua index b262ed3..02732ff 100644 --- a/spec/support/dota2/Vector.lua +++ b/spec/support/dota2/Vector.lua @@ -1,8 +1,11 @@ local class = require("pl.class") --- selene: allow(incorrect_standard_library_use) +--- @class support.dota2.Vector : Vector Vector = class() +--- @param x number +--- @param y number +--- @param z number function Vector:_init(x, y, z) self.x = x self.y = y diff --git a/spec/support/dota2/clock.lua b/spec/support/dota2/clock.lua new file mode 100644 index 0000000..f596380 --- /dev/null +++ b/spec/support/dota2/clock.lua @@ -0,0 +1,46 @@ +local assert = require("luassert") +local class = require("pl.class") +local spy = require("luassert.spy") + +--- @class support.dota2.MockClock +--- @field tick integer +--- @field paused boolean +--- @field spy luassert.spy +local M = class() + +--- @param tick? integer +--- @param paused? boolean +function M:_init(tick, paused) + self.tick = tick or 0 + self.paused = paused == nil and false or paused + self.spy = spy.on(self, "__call") +end + +--- @return integer +function M:__call() + if not self.paused then + self.tick = self.tick + 1 + end + + return self.tick +end + +function M:pause() + self.paused = true +end + +function M:unpause() + self.paused = false +end + +function M:reset() + self.tick = 0 + self.spy:clear() +end + +--- @return luassert.spy.assert +function M:assert() + return assert.spy(self.spy) +end + +return M diff --git a/spec/support/dota2/enum.lua b/spec/support/dota2/enum.lua index 45017fb..d538e12 100644 --- a/spec/support/dota2/enum.lua +++ b/spec/support/dota2/enum.lua @@ -43,7 +43,8 @@ DOTA_STASH_SLOT_3 = 11 DOTA_STASH_SLOT_4 = 12 DOTA_STASH_SLOT_5 = 13 DOTA_STASH_SLOT_6 = 14 -DOTA_ITEM_NEUTRAL_SLOT = 16 +DOTA_ITEM_NEUTRAL_ACTIVE_SLOT = 16 +DOTA_ITEM_NEUTRAL_PASSIVE_SLOT = 17 ABILITY_TYPE_ATTRIBUTES = 1 ABILITY_TYPE_BASIC = 2 diff --git a/spec/support/dota2/global.lua b/spec/support/dota2/global.lua index 5023e34..f50d697 100644 --- a/spec/support/dota2/global.lua +++ b/spec/support/dota2/global.lua @@ -1,14 +1,34 @@ +--# selene: allow(global_usage) + local m = require("moses") + local Factory = require("support.factory") local Fixtures = require("support.fixtures") +--- @type { [EntityIndex]: support.dota2.CBaseEntity } +local ENTITIES = {} + +--- @type EntityIndex +local __ent_index = 0 + +function test_NextEntIndex() + __ent_index = __ent_index + 1 + + return __ent_index +end + +--- @param index EntityIndex +--- @param ent support.dota2.CBaseEntity +function test_SetEntity(index, ent) + ENTITIES[index] = ent +end + function IsInToolsMode() return false end function UniqueString(base) - base = base or "" - return m.uniqueId(base .. "%d") + return m.uniqueId((base or "") .. "%d") end function DoUniqueString(base) @@ -35,12 +55,18 @@ function LoadKeyValues(filename) return Fixtures.require(filename) end +--- @param idx EntityIndex +--- @return CBaseEntity +function EntIndexToHScript(idx) + return ENTITIES[idx] +end + function CreateUnitByName(name, location, _findClearSpace, npcOwner, unitOwner, teamNumber) - return Factory.create("dota_unit", { + return Factory.dota_unit({ name = name, origin = location, owner = unitOwner, - playerOwner = npcOwner, + player_owner = npcOwner, team = teamNumber, }) end @@ -54,3 +80,8 @@ function EmitAnnouncerSound(_event) end function EmitAnnouncerSoundForPlayer(_event, _playerId) end function EmitAnnouncerSoundForTeam(_event, _team) end function EmitAnnouncerSoundForTeamOnLocation(_event, _team, _location) end + +--- @param hero_ent support.dota2.CDOTA_BaseNPC_Hero +function HeroMaxLevel(hero_ent) + hero_ent:max_level() +end diff --git a/spec/support/dota2/helpers.lua b/spec/support/dota2/helpers.lua new file mode 100644 index 0000000..f5f471d --- /dev/null +++ b/spec/support/dota2/helpers.lua @@ -0,0 +1,12 @@ +local M = {} + +--- @param hero CDOTA_BaseNPC_Hero +--- @param name string +function M.require_ability(hero, name) + local message = string.format("could not find ability %q", name) + local ability = assert(hero:FindAbilityByName(name), message) + + return ability +end + +return M diff --git a/spec/support/dota2/init.lua b/spec/support/dota2/init.lua index 81825ab..b0e38d8 100644 --- a/spec/support/dota2/init.lua +++ b/spec/support/dota2/init.lua @@ -1,33 +1,13 @@ --- globals - --- selene: allow(incorrect_standard_library_use) bit = require("bit32") require("support.dota2.enum") require("support.dota2.global") --- models - require("support.dota2.Vector") -require("support.dota2.CBaseEntity") -require("support.dota2.CBaseAnimating") -require("support.dota2.CBaseFlex") -require("support.dota2.CDOTABaseGameMode") -require("support.dota2.CDOTA_BaseNPC") -require("support.dota2.CDOTA_BaseNPC_Hero") -require("support.dota2.CDOTABaseAbility") -require("support.dota2.CDOTA_Item") -require("support.dota2.CBasePlayer") -require("support.dota2.CDOTAPlayer") - --- controllers - require("support.dota2.CustomGameEventManager") require("support.dota2.Entities") require("support.dota2.GameRules") require("support.dota2.PlayerResource") --- core libs - require("support.dota2.EntityFramework") diff --git a/spec/support/factories/ability.lua b/spec/support/factories/ability.lua deleted file mode 100644 index 8c4e586..0000000 --- a/spec/support/factories/ability.lua +++ /dev/null @@ -1,6 +0,0 @@ -local Factory = require("support.factory") -local Ability = require("invokation.dota2.Ability") - -Factory.define("ability", function(attributes) - return Ability(Factory.create("dota_ability", attributes)) -end) diff --git a/spec/support/factories/dota_ability.lua b/spec/support/factories/dota_ability.lua deleted file mode 100644 index 0503fe2..0000000 --- a/spec/support/factories/dota_ability.lua +++ /dev/null @@ -1,11 +0,0 @@ -local m = require("moses") -local Factory = require("support.factory") - -local ABILITIES = require("invokation.const.abilities") - -Factory.define("dota_ability", function(attributes) - attributes = attributes or {} - attributes = m.extend({}, ABILITIES.KEY_VALUES[attributes.name] or {}, attributes) - - return CDOTABaseAbility(attributes) -end) diff --git a/spec/support/factories/dota_hero.lua b/spec/support/factories/dota_hero.lua deleted file mode 100644 index ed34391..0000000 --- a/spec/support/factories/dota_hero.lua +++ /dev/null @@ -1,58 +0,0 @@ -local m = require("moses") -local Factory = require("support.factory") -local HeroKeyValues = require("invokation.dota2.kv.HeroKeyValues") - -local UNITS = require("invokation.const.units") -local HEROES = require("invokation.const.heroes") - -Factory.define("dota_hero", function(attributes, options) - attributes = attributes or {} - - local kvData = HEROES.KEY_VALUES[attributes.name] or {} - - attributes = m.extend({}, kvData, attributes) - options = options or {} - - local kv = HeroKeyValues(attributes.name, attributes) - local hero = CDOTA_BaseNPC_Hero(attributes, { kv = kv }) - - if m.isTable(options.gold) then - if m.isNumber(options.gold.reliable) then - hero:ModifyGold(options.gold.reliable, true, 0) - end - - if m.isNumber(options.gold.unreliable) then - hero:ModifyGold(options.gold.unreliable, false, 0) - end - elseif m.isNumber(options.gold) then - hero:ModifyGold(options.gold, true, 0) - end - - if m.isArray(options.items) then - for _, name in ipairs(options.items) do - hero:AddItemByName(name) - end - end - - for _, name in ipairs(kv:Abilities()) do - hero:AddAbility(name) - end - - if m.isArray(options.abilities) then - for _, name in ipairs(options.abilities) do - hero:AddAbility(name) - end - elseif m.isTable(options.abilities) then - for name, level in pairs(options.abilities) do - local ability = hero:AddAbility(name) - ability:SetLevel(level) - end - end - - return hero -end) - -Factory.define("dota_hero_invoker", function(attributes, options) - attributes = m.extend({}, { name = UNITS.INVOKER }, attributes or {}) - return Factory.create("dota_hero", attributes, options) -end) diff --git a/spec/support/factories/dota_item.lua b/spec/support/factories/dota_item.lua deleted file mode 100644 index 8843bd5..0000000 --- a/spec/support/factories/dota_item.lua +++ /dev/null @@ -1,8 +0,0 @@ -local m = require("moses") -local Factory = require("support.factory") - -local KEY_VALUES = LoadKeyValues("scripts/npc/items.txt") - -Factory.define("dota_item", function(attributes) - return CDOTA_Item(m.extend({}, KEY_VALUES[attributes.name] or {}, attributes)) -end) diff --git a/spec/support/factories/dota_player.lua b/spec/support/factories/dota_player.lua deleted file mode 100644 index 5af2f43..0000000 --- a/spec/support/factories/dota_player.lua +++ /dev/null @@ -1,5 +0,0 @@ -local Factory = require("support.factory") - -Factory.define("dota_player", function(attributes) - return CDOTAPlayer(attributes) -end) diff --git a/spec/support/factories/dota_unit.lua b/spec/support/factories/dota_unit.lua deleted file mode 100644 index bf82bdb..0000000 --- a/spec/support/factories/dota_unit.lua +++ /dev/null @@ -1,5 +0,0 @@ -local Factory = require("support.factory") - -Factory.define("dota_unit", function(attributes) - return CDOTA_BaseNPC(attributes) -end) diff --git a/spec/support/factories/entity.lua b/spec/support/factories/entity.lua deleted file mode 100644 index 3f74404..0000000 --- a/spec/support/factories/entity.lua +++ /dev/null @@ -1,5 +0,0 @@ -local Factory = require("support.factory") - -Factory.define("entity", function(attributes) - return CBaseEntity(attributes) -end) diff --git a/spec/support/factories/hero.lua b/spec/support/factories/hero.lua deleted file mode 100644 index 6fc7ba5..0000000 --- a/spec/support/factories/hero.lua +++ /dev/null @@ -1,10 +0,0 @@ -local Factory = require("support.factory") -local Unit = require("invokation.dota2.Unit") - -Factory.define("hero", function(attributes, options) - return Unit(Factory.create("dota_hero", attributes, options)) -end) - -Factory.define("hero_invoker", function(attributes, options) - return Unit(Factory.create("dota_hero_invoker", attributes, options)) -end) diff --git a/spec/support/factories/init.lua b/spec/support/factories/init.lua deleted file mode 100644 index 4cdfd0a..0000000 --- a/spec/support/factories/init.lua +++ /dev/null @@ -1,12 +0,0 @@ -require("support.factories.vector") -require("support.factories.entity") -require("support.factories.dota_player") -require("support.factories.dota_ability") -require("support.factories.dota_item") -require("support.factories.dota_unit") -require("support.factories.dota_hero") -require("support.factories.player") -require("support.factories.ability") -require("support.factories.item") -require("support.factories.unit") -require("support.factories.hero") diff --git a/spec/support/factories/item.lua b/spec/support/factories/item.lua deleted file mode 100644 index 55073c2..0000000 --- a/spec/support/factories/item.lua +++ /dev/null @@ -1,6 +0,0 @@ -local Factory = require("support.factory") -local Ability = require("invokation.dota2.Ability") - -Factory.define("item", function(attributes) - return Ability(Factory.create("dota_item", attributes)) -end) diff --git a/spec/support/factories/player.lua b/spec/support/factories/player.lua deleted file mode 100644 index ffaf28e..0000000 --- a/spec/support/factories/player.lua +++ /dev/null @@ -1,6 +0,0 @@ -local Factory = require("support.factory") -local Player = require("invokation.dota2.Player") - -Factory.define("player", function(attributes) - return Player(Factory.create("dota_player", attributes)) -end) diff --git a/spec/support/factories/unit.lua b/spec/support/factories/unit.lua deleted file mode 100644 index 9c12ba9..0000000 --- a/spec/support/factories/unit.lua +++ /dev/null @@ -1,6 +0,0 @@ -local Factory = require("support.factory") -local Unit = require("invokation.dota2.Unit") - -Factory.define("unit", function(attributes) - return Unit(Factory.create("dota_unit", attributes)) -end) diff --git a/spec/support/factories/vector.lua b/spec/support/factories/vector.lua deleted file mode 100644 index cb01c55..0000000 --- a/spec/support/factories/vector.lua +++ /dev/null @@ -1,14 +0,0 @@ -local m = require("moses") -local Factory = require("support.factory") - -Factory.define("vector", function(attributes) - local coordinates - - if m.isArray(attributes) then - coordinates = attributes - else - coordinates = { attributes.x, attributes.y, attributes.z } - end - - return Vector(unpack(coordinates)) -end) diff --git a/spec/support/factory.lua b/spec/support/factory.lua deleted file mode 100644 index 5e6919d..0000000 --- a/spec/support/factory.lua +++ /dev/null @@ -1,19 +0,0 @@ -local M = { definitions = {} } - -local ERRF_NOT_DEFINED = "Factory %q not defined" - -function M.define(name, definition) - M.definitions[name] = definition -end - -function M.create(name, ...) - local factory = M.definitions[name] - - if factory == nil then - error(ERRF_NOT_DEFINED:format(name)) - end - - return factory(...) -end - -return M diff --git a/spec/support/factory/ability.lua b/spec/support/factory/ability.lua new file mode 100644 index 0000000..61df1a0 --- /dev/null +++ b/spec/support/factory/ability.lua @@ -0,0 +1,10 @@ +local Ability = require("invk.dota2.ability") + +--- @param attributes support.dota2.CDOTABaseAbility_attributes +--- @param options? support.factory.dota_ability.Options +--- @return invk.dota2.Ability +return function(attributes, options) + local F = require("support.factory") + + return Ability:new(F.dota_ability(attributes, options)) +end diff --git a/spec/support/factory/dota_ability.lua b/spec/support/factory/dota_ability.lua new file mode 100644 index 0000000..d2bc0bd --- /dev/null +++ b/spec/support/factory/dota_ability.lua @@ -0,0 +1,22 @@ +local m = require("moses") + +local CDOTABaseAbility = require("support.dota2.CDOTABaseAbility") + +--- @class support.factory.dota_ability.Options +--- @field hero? string + +--- @param attributes support.dota2.CDOTABaseAbility_attributes +--- @param options? support.factory.dota_ability.Options +--- @return support.dota2.CDOTABaseAbility +return function(attributes, options) + local opts = options or {} + + if opts.hero then + local kv_path = string.format("scripts/npc/heroes/%s.txt", opts.hero) + local kv = LoadKeyValues(kv_path) + + attributes = m.extend(attributes, kv[attributes.name] or {}) + end + + return CDOTABaseAbility(attributes) +end diff --git a/spec/support/factory/dota_entity.lua b/spec/support/factory/dota_entity.lua new file mode 100644 index 0000000..2dcbb78 --- /dev/null +++ b/spec/support/factory/dota_entity.lua @@ -0,0 +1,7 @@ +local CBaseEntity = require("support.dota2.CBaseEntity") + +--- @param attributes support.dota2.CBaseEntity_attributes +--- @return support.dota2.CBaseEntity +return function(attributes) + return CBaseEntity(attributes) +end diff --git a/spec/support/factory/dota_hero.lua b/spec/support/factory/dota_hero.lua new file mode 100644 index 0000000..6a0c463 --- /dev/null +++ b/spec/support/factory/dota_hero.lua @@ -0,0 +1,44 @@ +local m = require("moses") + +local CDOTA_BaseNPC_Hero = require("support.dota2.CDOTA_BaseNPC_Hero") + +--- @class support.factory.dota_hero.Options +--- @field gold? integer +--- @field items? string[] +--- @field abilities? string[] | { [string]: integer } + +--- @param attributes support.dota2.CDOTA_BaseNPC_Hero_attributes +--- @param options? support.factory.dota_hero.Options +--- @return support.dota2.CDOTA_BaseNPC_Hero +return function(attributes, options) + local opts = options or {} + local kv = LoadKeyValues("scripts/npc/npc_heroes.txt") + local attrs = m.extend({}, kv[attributes.name] or {}, attributes) + local hero = CDOTA_BaseNPC_Hero(attrs) + + if m.isNumber(opts.gold) then + hero:ModifyGold(opts.gold, true, 0) + end + + if opts.items then + for _, name in ipairs(opts.items) do + hero:AddItemByName(name) + end + end + + if opts.abilities then + if m.isArray(opts.abilities) then + for _, name in ipairs(opts.abilities) do + hero:AddAbility(name) + end + elseif m.isTable(opts.abilities) then + for name, level in pairs(opts.abilities) do + local ability = hero:AddAbility(name) + + ability:SetLevel(level) + end + end + end + + return hero +end diff --git a/spec/support/factory/dota_hero_invoker.lua b/spec/support/factory/dota_hero_invoker.lua new file mode 100644 index 0000000..fcd4543 --- /dev/null +++ b/spec/support/factory/dota_hero_invoker.lua @@ -0,0 +1,17 @@ +local m = require("moses") + +local UNITS = require("invk.const.units") + +--- @class support.factory.dota_hero_invoker.Attributes : support.dota2.CDOTA_BaseNPC_Hero_attributes +--- @field name? string + +--- @param attributes? support.factory.dota_hero_invoker.Attributes +--- @param options? support.factory.dota_hero.Options +--- @return support.dota2.CDOTA_BaseNPC_Hero +return function(attributes, options) + local F = require("support.factory") + + attributes = m.extend({}, { name = UNITS.INVOKER }, attributes or {}) + + return F.dota_hero(attributes, options) +end diff --git a/spec/support/factory/dota_item.lua b/spec/support/factory/dota_item.lua new file mode 100644 index 0000000..986f6f2 --- /dev/null +++ b/spec/support/factory/dota_item.lua @@ -0,0 +1,11 @@ +local m = require("moses") + +local CDOTA_Item = require("support.dota2.CDOTA_Item") + +--- @param attributes support.dota2.CDOTA_Item_attributes +--- @return support.dota2.CDOTA_Item +return function(attributes) + local kv = LoadKeyValues("scripts/npc/items.txt") + + return CDOTA_Item(m.extend({}, kv[attributes.name] or {}, attributes)) +end diff --git a/spec/support/factory/dota_player.lua b/spec/support/factory/dota_player.lua new file mode 100644 index 0000000..84dc3c7 --- /dev/null +++ b/spec/support/factory/dota_player.lua @@ -0,0 +1,17 @@ +local CDOTAPlayerController = require("support.dota2.CDOTAPlayerController") + +--- @class support.factory.dota_player.Attributes : support.dota2.CDOTAPlayerController_attributes +--- @field hero? support.dota2.CDOTA_BaseNPC_Hero + +--- @param attributes? support.factory.dota_player.Attributes +--- @return support.dota2.CDOTAPlayerController +return function(attributes) + local F = require("support.factory") + + local attrs = attributes or {} + + attrs.player_id = attrs.player_id or 13 + attrs.hero = attrs.hero or F.dota_hero_invoker() + + return CDOTAPlayerController(attrs) +end diff --git a/spec/support/factory/dota_unit.lua b/spec/support/factory/dota_unit.lua new file mode 100644 index 0000000..a4277f1 --- /dev/null +++ b/spec/support/factory/dota_unit.lua @@ -0,0 +1,7 @@ +local CDOTA_BaseNPC = require("support.dota2.CDOTA_BaseNPC") + +--- @param attributes support.dota2.CDOTA_BaseNPC_attributes +--- @return support.dota2.CDOTA_BaseNPC +return function(attributes) + return CDOTA_BaseNPC(attributes) +end diff --git a/spec/support/factory/hero.lua b/spec/support/factory/hero.lua new file mode 100644 index 0000000..0b1d546 --- /dev/null +++ b/spec/support/factory/hero.lua @@ -0,0 +1,10 @@ +local Unit = require("invk.dota2.unit") + +--- @param attributes support.dota2.CDOTA_BaseNPC_Hero_attributes +--- @param options? support.factory.dota_hero.Options +--- @return invk.dota2.Unit +return function(attributes, options) + local F = require("support.factory") + + return Unit:new(F.dota_hero(attributes, options)) +end diff --git a/spec/support/factory/hero_invoker.lua b/spec/support/factory/hero_invoker.lua new file mode 100644 index 0000000..fdad5aa --- /dev/null +++ b/spec/support/factory/hero_invoker.lua @@ -0,0 +1,10 @@ +local Unit = require("invk.dota2.unit") + +--- @param attributes? support.dota2.CDOTA_BaseNPC_Hero_attributes +--- @param options? support.factory.dota_hero.Options +--- @return invk.dota2.Unit +return function(attributes, options) + local F = require("support.factory") + + return Unit:new(F.dota_hero_invoker(attributes, options)) +end diff --git a/spec/support/factory/init.lua b/spec/support/factory/init.lua new file mode 100644 index 0000000..bbf030f --- /dev/null +++ b/spec/support/factory/init.lua @@ -0,0 +1,26 @@ +--- @class support.Factory +--- @field vector fun(attrs: support.factory.VectorAttributes): support.dota2.Vector +--- @field dota_entity fun(attributes: support.dota2.CBaseEntity_attributes): support.dota2.CBaseEntity +--- @field dota_player fun(attributes?: support.dota2.CDOTAPlayerController_attributes): support.dota2.CDOTAPlayerController +--- @field dota_ability fun(attributes: support.dota2.CDOTABaseAbility_attributes, options?: support.factory.dota_ability.Options): support.dota2.CDOTABaseAbility +--- @field dota_item fun(attributes: support.dota2.CDOTA_Item_attributes): support.dota2.CDOTA_Item +--- @field dota_unit fun(attributes: support.dota2.CDOTA_BaseNPC_attributes): support.dota2.CDOTA_BaseNPC +--- @field dota_hero fun(attributes: support.dota2.CDOTA_BaseNPC_Hero_attributes, options?: support.factory.dota_hero.Options): support.dota2.CDOTA_BaseNPC_Hero +--- @field dota_hero_invoker fun(attributes?: support.factory.dota_hero_invoker.Attributes, options?: support.factory.dota_hero.Options): support.dota2.CDOTA_BaseNPC_Hero +--- @field player fun(attributes?: support.dota2.CDOTAPlayerController_attributes): invk.dota2.Player +--- @field ability fun(attributes: support.dota2.CDOTABaseAbility_attributes, options?: support.factory.dota_ability.Options): invk.dota2.Ability +--- @field item fun(attributes: support.dota2.CDOTA_Item_attributes): invk.dota2.Ability +--- @field unit fun(attributes: support.dota2.CDOTA_BaseNPC_attributes): invk.dota2.Unit +--- @field hero fun(attributes: support.dota2.CDOTA_BaseNPC_Hero_attributes, options?: support.factory.dota_hero.Options): invk.dota2.Unit +--- @field hero_invoker fun(attributes?: support.factory.dota_hero_invoker.Attributes, options?: support.factory.dota_hero.Options): invk.dota2.Unit +local M = setmetatable({}, { + __index = function(t, name) + local factory = require("support.factory." .. name) + + t[name] = factory + + return factory + end, +}) + +return M diff --git a/spec/support/factory/item.lua b/spec/support/factory/item.lua new file mode 100644 index 0000000..b8af7bd --- /dev/null +++ b/spec/support/factory/item.lua @@ -0,0 +1,9 @@ +local Ability = require("invk.dota2.ability") + +--- @param attributes support.dota2.CDOTA_Item_attributes +--- @return invk.dota2.Ability +return function(attributes) + local F = require("support.factory") + + return Ability:new(F.dota_item(attributes)) +end diff --git a/spec/support/factory/player.lua b/spec/support/factory/player.lua new file mode 100644 index 0000000..e84776a --- /dev/null +++ b/spec/support/factory/player.lua @@ -0,0 +1,9 @@ +local Player = require("invk.dota2.player") + +--- @param attributes? support.factory.dota_player.Attributes +--- @return invk.dota2.Player +return function(attributes) + local F = require("support.factory") + + return Player:new(F.dota_player(attributes)) +end diff --git a/spec/support/factory/unit.lua b/spec/support/factory/unit.lua new file mode 100644 index 0000000..8571ab1 --- /dev/null +++ b/spec/support/factory/unit.lua @@ -0,0 +1,9 @@ +local Unit = require("invk.dota2.unit") + +--- @param attributes support.dota2.CDOTA_BaseNPC_attributes +--- @return invk.dota2.Unit +return function(attributes) + local F = require("support.factory") + + return Unit:new(F.dota_unit(attributes)) +end diff --git a/spec/support/factory/vector.lua b/spec/support/factory/vector.lua new file mode 100644 index 0000000..d94f73a --- /dev/null +++ b/spec/support/factory/vector.lua @@ -0,0 +1,7 @@ +--- @alias support.factory.VectorAttributes { [1]: number, [2]: number, [3]: number } + +--- @param attributes support.factory.VectorAttributes +--- @return Vector +return function(attributes) + return Vector(unpack(attributes)) +end diff --git a/spec/support/fixtures.lua b/spec/support/fixtures/init.lua similarity index 99% rename from spec/support/fixtures.lua rename to spec/support/fixtures/init.lua index f3c0d48..c21205a 100644 --- a/spec/support/fixtures.lua +++ b/spec/support/fixtures/init.lua @@ -1,5 +1,6 @@ local file = require("pl.file") local path = require("pl.path") + local source = require("support.source") local M = {} diff --git a/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_axe_txt.lua b/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_axe_txt.lua new file mode 100644 index 0000000..a564707 --- /dev/null +++ b/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_axe_txt.lua @@ -0,0 +1 @@ +return {} diff --git a/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_invoker_txt.lua b/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_invoker_txt.lua index a596f08..f7ca4c3 100644 --- a/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_invoker_txt.lua +++ b/spec/support/fixtures/scripts/npc/heroes/npc_dota_hero_invoker_txt.lua @@ -1,483 +1,1083 @@ -return { - invoker_quas = { - ID = 5370, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE", - SpellDispellableType = "SPELL_DISPELLABLE_NO", - MaxLevel = 7, - AbilityCooldown = 0, - AbilityManaCost = 0, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { var_type = "FIELD_FLOAT", health_regen_per_instance = "1 3 5 7 9 11 13" }, +local M = { + ["invoker_quas"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL | DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["AbilityCooldown"] = 0, + ["AbilityManaCost"] = 0, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["HasScepterUpgrade"] = 1, + ["MaxLevel"] = 7, + ["AbilityValues"] = { + ["max_level"] = { + ["value"] = 7, + ["special_bonus_scepter"] = "+1", + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = "+1", + ["special_bonus_unique_invoker_facet_orb_level"] = "+1", + }, + }, + ["hp_regen_per_instance"] = { + ["value"] = "1 2 3 4 5 6 7 8 9 10", + ["special_bonus_unique_invoker_13"] = "x2", + }, + ["upgrade_at_level"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_quas_focus"] = 6, + }, + ["strength_bonus"] = 1, + ["scepter_bonus_levels"] = { + ["value"] = 1, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = 0, + }, + }, + ["facet_bonus_levels"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_unique_invoker_facet_orb_level"] = "+1", + }, + }, }, }, - invoker_wex = { - ID = 5371, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE", - SpellDispellableType = "SPELL_DISPELLABLE_NO", - MaxLevel = 7, - AbilityCooldown = 0, - AbilityManaCost = 0, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { var_type = "FIELD_INTEGER", attack_speed_per_instance = "2 4 6 8 10 12 14" }, - ["02"] = { var_type = "FIELD_INTEGER", move_speed_per_instance = "1 2 3 4 5 6 7" }, + ["invoker_wex"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL | DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["AbilityCooldown"] = 0, + ["AbilityManaCost"] = 0, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["HasScepterUpgrade"] = 1, + ["MaxLevel"] = 7, + ["AbilityValues"] = { + ["max_level"] = { + ["value"] = 7, + ["special_bonus_scepter"] = "+1", + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = "+1", + ["special_bonus_unique_invoker_facet_orb_level"] = "+1", + }, + }, + ["move_speed_per_instance"] = { + ["value"] = "0.6 1.2 1.8 2.4 3.0 3.6 4.2 4.8 5.4 6.0", + ["special_bonus_unique_invoker_13"] = "x2", + }, + ["attack_speed_per_instance"] = { + ["value"] = "1 2 3 4 5 6 7 8 9 10", + ["special_bonus_unique_invoker_13"] = "x2", + }, + ["upgrade_at_level"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_wex_focus"] = 6, + }, + ["agility_bonus"] = 1, + ["scepter_bonus_levels"] = { + ["value"] = 1, + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = 0, + }, + }, + ["facet_bonus_levels"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_unique_invoker_facet_orb_level"] = "+1", + }, + }, }, }, - invoker_exort = { - ID = 5372, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE", - SpellDispellableType = "SPELL_DISPELLABLE_NO", - MaxLevel = 7, - AbilityCooldown = 0, - AbilityManaCost = 0, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { var_type = "FIELD_INTEGER", bonus_damage_per_instance = "2 6 10 14 18 22 26" }, + ["invoker_exort"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL | DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["AbilityCooldown"] = 0, + ["AbilityManaCost"] = 0, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["HasScepterUpgrade"] = 1, + ["MaxLevel"] = 7, + ["AbilityValues"] = { + ["max_level"] = { + ["value"] = 7, + ["special_bonus_scepter"] = "+1", + ["special_bonus_facet_invoker_exort_focus"] = { + ["value"] = "+1", + ["special_bonus_unique_invoker_facet_orb_level"] = "+1", + }, + }, + ["bonus_damage_per_instance"] = { + ["value"] = "2 4 6 8 10 12 14 16 18 20", + ["special_bonus_unique_invoker_13"] = "x2", + ["CalculateSpellDamageTooltip"] = 0, + ["DamageTypeTooltip"] = "DAMAGE_TYPE_PHYSICAL", + }, + ["upgrade_at_level"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_exort_focus"] = 6, + }, + ["intelligence_bonus"] = 1, + ["scepter_bonus_levels"] = { + ["value"] = 1, + ["special_bonus_facet_invoker_exort_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = 0, + }, + }, + ["facet_bonus_levels"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_exort_focus"] = { + ["value"] = 0, + ["special_bonus_unique_invoker_facet_orb_level"] = "+1", + }, + }, }, }, - invoker_empty1 = { - ID = 5373, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE", - MaxLevel = 0, - AbilityCastAnimation = "ACT_INVALID", + ["invoker_empty1"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE", + ["MaxLevel"] = 0, + ["AbilityCastAnimation"] = "ACT_INVALID", }, - invoker_empty2 = { - ID = 5374, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE", - MaxLevel = 0, - AbilityCastAnimation = "ACT_INVALID", + ["invoker_empty2"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE", + ["MaxLevel"] = 0, + ["AbilityCastAnimation"] = "ACT_INVALID", }, - invoker_invoke = { - ID = 5375, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - AbilityType = "DOTA_ABILITY_TYPE_ULTIMATE", - MaxLevel = 1, - RequiredLevel = 1, - AbilitySound = "Hero_Invoker.Invoke", - HasScepterUpgrade = 1, - AbilityCooldown = 6, - AbilityManaCost = 0, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { var_type = "FIELD_INTEGER", max_invoked_spells = 2 }, - ["02"] = { var_type = "FIELD_FLOAT", cooldown_scepter = 2, RequiresScepter = 1 }, - ["03"] = { var_type = "FIELD_INTEGER", mana_cost_scepter = 0 }, + ["invoker_invoke"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL | DOTA_ABILITY_BEHAVIOR_IGNORE_INVISIBLE", + ["AbilityType"] = "ABILITY_TYPE_ULTIMATE", + ["MaxLevel"] = 1, + ["Innate"] = 1, + ["AbilitySound"] = "Hero_Invoker.Invoke", + ["AbilityCooldown"] = 7, + ["AbilityManaCost"] = 0, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["max_invoked_spells"] = 2, + ["cooldown_reduction_per_orb"] = 0.3, }, }, - invoker_cold_snap = { - ID = 5376, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - SpellDispellableType = "SPELL_DISPELLABLE_YES", - MaxLevel = 1, - HotKeyOverride = "Y", - FightRecapLevel = 1, - AbilitySound = "Hero_Invoker.ColdSnap", - AbilityUnitTargetTeam = "DOTA_UNIT_TARGET_TEAM_ENEMY", - AbilityUnitTargetType = "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC", - AbilityUnitDamageType = "DAMAGE_TYPE_MAGICAL", - AbilityCastRange = 1000, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 20, - AbilityManaCost = 100, - AbilityModifierSupportValue = 0.15, - AbilitySpecial = { - ["01"] = { - var_type = "FIELD_FLOAT", - duration = "3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5", - levelkey = "quaslevel", - LinkedSpecialBonus = "special_bonus_unique_invoker_7", - }, - ["02"] = { var_type = "FIELD_FLOAT", freeze_duration = 0.4 }, - ["03"] = { - var_type = "FIELD_FLOAT", - freeze_cooldown = "0.77 0.74 0.71 0.69 0.66 0.63 0.60 0.57", - levelkey = "quaslevel", - }, - ["04"] = { - var_type = "FIELD_FLOAT", - freeze_damage = "8 16 24 32 40 48 56 64", - levelkey = "quaslevel", - }, - ["05"] = { var_type = "FIELD_FLOAT", damage_trigger = 10.0 }, + ["invoker_attribute_bonus"] = { + ["AbilityType"] = "ABILITY_TYPE_ATTRIBUTES", + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_PASSIVE", + ["MaxLevel"] = 1, + ["LevelsBetweenUpgrades"] = 1, + ["RequiredLevel"] = 25, + ["AbilityValues"] = { + ["attribute_bonus_per_level"] = 6, }, }, - invoker_ghost_walk = { - ID = 5381, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - SpellDispellableType = "SPELL_DISPELLABLE_NO", - MaxLevel = 1, - HotKeyOverride = "V", - AbilitySound = "Hero_Invoker.GhostWalk", - AbilityCooldown = 45, - AbilityManaCost = 200, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { var_type = "FIELD_FLOAT", duration = 100.0 }, - ["02"] = { var_type = "FIELD_INTEGER", area_of_effect = 400 }, - ["03"] = { - var_type = "FIELD_INTEGER", - enemy_slow = "-20 -25 -30 -35 -40 -45 -50 -55", - levelkey = "quaslevel", - }, - ["04"] = { - var_type = "FIELD_INTEGER", - self_slow = "-30 -20 -10 0 10 20 30 40", - levelkey = "wexlevel", - }, - ["05"] = { var_type = "FIELD_FLOAT", aura_fade_time = 2.0 }, + ["invoker_cold_snap"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "Y", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.ColdSnap", + ["AbilityUnitTargetTeam"] = "DOTA_UNIT_TARGET_TEAM_ENEMY", + ["AbilityUnitTargetType"] = "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["AbilityCastRange"] = 1000, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 100, + ["AbilityModifierSupportValue"] = 0.15, + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 18, + ["special_bonus_unique_invoker_9"] = -5, + }, + ["duration"] = { + ["value"] = "3.0 3.4 3.8 4.2 4.6 5.0 5.4 5.8 6.2 6.6", + ["levelkey"] = "quaslevel", + }, + ["freeze_duration"] = 0.4, + ["freeze_cooldown"] = { + ["value"] = "0.80 0.77 0.74 0.71 0.68 0.65 0.62 0.59 0.56 0.53", + ["levelkey"] = "quaslevel", + }, + ["freeze_damage"] = { + ["value"] = "28 36 44 52 60 68 76 84 92 100", + ["levelkey"] = "quaslevel", + }, + ["freeze_heal"] = { + ["value"] = 0, + ["special_bonus_unique_invoker_cold_snap_heal"] = 1, + }, + ["damage_trigger"] = 10, }, }, - invoker_tornado = { - ID = 5382, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - SpellDispellableType = "SPELL_DISPELLABLE_YES", - MaxLevel = 1, - HotKeyOverride = "X", - AbilityUnitDamageType = "DAMAGE_TYPE_MAGICAL", - AbilitySound = "Hero_Invoker.Tornado", - AbilityCastRange = 2000, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 30, - AbilityManaCost = 150, - AbilitySpecial = { - ["01"] = { - var_type = "FIELD_INTEGER", - travel_distance = "800 1200 1600 2000 2400 2800 3200 3600", - levelkey = "wexlevel", - }, - ["02"] = { var_type = "FIELD_INTEGER", travel_speed = 1000 }, - ["03"] = { var_type = "FIELD_INTEGER", area_of_effect = 200 }, - ["04"] = { var_type = "FIELD_INTEGER", vision_distance = 200 }, - ["05"] = { var_type = "FIELD_FLOAT", end_vision_duration = 1.75 }, - ["06"] = { - var_type = "FIELD_FLOAT", - lift_duration = "0.8 1.1 1.4 1.7 2.0 2.3 2.6 2.9", - LinkedSpecialBonus = "special_bonus_unique_invoker_8", - levelkey = "quaslevel", - }, - ["07"] = { var_type = "FIELD_FLOAT", base_damage = 70 }, - ["08"] = { var_type = "FIELD_FLOAT", quas_damage = "0 0 0 0 0 0 0", levelkey = "quaslevel" }, - ["09"] = { - var_type = "FIELD_FLOAT", - wex_damage = "45 90 135 180 225 270 315 360", - levelkey = "wexlevel", + ["invoker_ghost_walk"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "V", + ["AbilitySound"] = "Hero_Invoker.GhostWalk", + ["HasShardUpgrade"] = 1, + ["ShardRequiredFacet"] = "invoker_quas_focus", + ["AbilityManaCost"] = 175, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 32, + }, + ["duration"] = 60, + ["area_of_effect"] = { + ["value"] = 450, + ["affected_by_aoe_increase"] = 1, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_shard"] = "+150", + }, + }, + ["enemy_slow"] = { + ["value"] = "-20 -25 -30 -35 -40 -45 -50 -55 -60 -65", + ["levelkey"] = "quaslevel", + }, + ["self_slow"] = { + ["value"] = "-20 -15 -10 -5 0 5 10 15 20 25", + ["levelkey"] = "wexlevel", + }, + ["aura_fade_time"] = 2, + ["health_regen"] = { + ["value"] = "2 4 6 8 10 12 14 16 18 20", + ["levelkey"] = "quaslevel", + }, + ["mana_regen"] = { + ["value"] = "2 4 6 8 10 12 14 16 18 20", + ["levelkey"] = "wexlevel", + }, + ["apply_ice_wall_debuff"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_shard"] = "+1", + }, }, }, }, - invoker_emp = { - ID = 5383, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - MaxLevel = 1, - HotKeyOverride = "C", - AbilityUnitDamageType = "DAMAGE_TYPE_MAGICAL", - AbilitySound = "Hero_Invoker.EMP.Charge", - AbilityCastRange = 950, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 30, - AbilityManaCost = 125, - AbilitySpecial = { - ["01"] = { var_type = "FIELD_FLOAT", delay = 2.9, levelkey = "wexlevel" }, - ["02"] = { var_type = "FIELD_INTEGER", area_of_effect = 675 }, - ["03"] = { - var_type = "FIELD_INTEGER", - mana_burned = "100 175 250 325 400 475 550 625", - levelkey = "wexlevel", - }, - ["04"] = { var_type = "FIELD_INTEGER", damage_per_mana_pct = 60 }, + ["invoker_tornado"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES | DOTA_ABILITY_BEHAVIOR_OVERSHOOT", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "X", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["AbilitySound"] = "Hero_Invoker.Tornado", + ["HasScepterUpgrade"] = 1, + ["ScepterRequiredFacet"] = "invoker_wex_focus", + ["AbilityCastRange"] = 2000, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 140, + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 27, + ["special_bonus_unique_invoker_3"] = -4, + }, + ["travel_distance"] = { + ["value"] = "1500 1800 2100 2400 2700 3000 3300 3600 3900 4200", + ["levelkey"] = "wexlevel", + }, + ["travel_speed"] = 1000, + ["area_of_effect"] = { + ["value"] = 200, + ["affected_by_aoe_increase"] = 1, + }, + ["vision_distance"] = { + ["value"] = 200, + ["affected_by_aoe_increase"] = 1, + }, + ["end_vision_duration"] = 1.75, + ["lift_duration"] = { + ["value"] = "1.2 1.4 1.6 1.8 2 2.2 2.4 2.6 2.8 3.0", + ["levelkey"] = "quaslevel", + }, + ["base_damage"] = { + ["value"] = 50, + ["CalculateSpellDamageTooltip"] = 1, + }, + ["quas_damage"] = { + ["value"] = "0 0 0 0 0 0 0 0 0", + ["levelkey"] = "quaslevel", + }, + ["wex_damage"] = { + ["value"] = "45 90 135 180 225 270 315 360 405 450", + ["levelkey"] = "wexlevel", + }, + ["twister_distance_interval"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "+300", + }, + }, + ["twister_radius"] = { + ["value"] = 150, + ["affected_by_aoe_increase"] = 1, + }, + ["twister_damage"] = { + ["value"] = 0, + ["levelkey"] = "wexlevel", + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "60 70 80 90 100 110 120 130 140 150", + }, + }, + ["twister_duration"] = { + ["value"] = 0, + ["levelkey"] = "quaslevel", + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "3.2 3.4 3.6 3.8 4.0 4.2 4.4 4.6 4.8 5.0", + }, + }, + ["twister_tick_rate"] = { + ["value"] = 0.25, + }, }, }, - invoker_alacrity = { - ID = 5384, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - MaxLevel = 1, - HotKeyOverride = "Z", - AbilitySound = "Hero_Invoker.Alacrity", - AbilityUnitTargetTeam = "DOTA_UNIT_TARGET_TEAM_FRIENDLY", - AbilityUnitTargetType = "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_CREEP", - SpellImmunityType = "SPELL_IMMUNITY_ALLIES_YES", - SpellDispellableType = "SPELL_DISPELLABLE_YES", - AbilityCastRange = 650, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 17, - AbilityManaCost = 60, - AbilitySpecial = { - ["01"] = { - var_type = "FIELD_INTEGER", - bonus_attack_speed = "10 25 40 55 70 85 100 115", - levelkey = "wexlevel", - LinkedSpecialBonus = "special_bonus_unique_invoker_5", - }, - ["02"] = { - var_type = "FIELD_INTEGER", - bonus_damage = "10 25 40 55 70 85 100 115", - levelkey = "exortlevel", - LinkedSpecialBonus = "special_bonus_unique_invoker_5", - }, - ["03"] = { var_type = "FIELD_FLOAT", duration = 9 }, + ["invoker_emp"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "C", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["AbilitySound"] = "Hero_Invoker.EMP.Charge", + ["HasShardUpgrade"] = 1, + ["ShardRequiredFacet"] = "invoker_wex_focus", + ["AbilityCastRange"] = 950, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 27, + ["AbilityManaCost"] = 125, + ["AbilityValues"] = { + ["delay"] = { + ["value"] = 2.9, + ["levelkey"] = "wexlevel", + }, + ["area_of_effect"] = { + ["value"] = 675, + ["affected_by_aoe_increase"] = 1, + }, + ["mana_burned"] = { + ["value"] = "100 175 250 325 400 475 550 625 700 775", + ["levelkey"] = "wexlevel", + }, + ["damage_per_mana_pct"] = { + ["value"] = 60, + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_shard"] = "+50%", + }, + }, + ["drag_speed"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_wex_focus"] = { + ["value"] = 0, + ["special_bonus_shard"] = "+150", + }, + }, + ["self_mana_restore_pct"] = 25, + ["damage_barriers"] = { + ["value"] = 0, + }, }, }, - invoker_chaos_meteor = { - ID = 5385, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - MaxLevel = 1, - HotKeyOverride = "D", - AbilityUnitDamageType = "DAMAGE_TYPE_MAGICAL", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - SpellDispellableType = "SPELL_DISPELLABLE_YES", - FightRecapLevel = 1, - AbilitySound = "Hero_Invoker.ChaosMeteor.Impact", - AbilityCastRange = 700, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 55, - AbilityManaCost = 200, - AbilityModifierSupportValue = 0.0, - AbilitySpecial = { - ["01"] = { var_type = "FIELD_FLOAT", land_time = 1.3 }, - ["02"] = { var_type = "FIELD_INTEGER", area_of_effect = 275 }, - ["03"] = { - var_type = "FIELD_INTEGER", - travel_distance = "465 615 780 930 1095 1245 1410 1575", - levelkey = "wexlevel", - }, - ["04"] = { var_type = "FIELD_INTEGER", travel_speed = 300 }, - ["05"] = { var_type = "FIELD_FLOAT", damage_interval = 0.5, CalculateSpellDamageTooltip = 0 }, - ["06"] = { var_type = "FIELD_INTEGER", vision_distance = 500 }, - ["07"] = { var_type = "FIELD_FLOAT", end_vision_duration = 3.0 }, - ["08"] = { - var_type = "FIELD_FLOAT", - main_damage = "57.5 75 92.5 110 127.5 145 162.5 180", - LinkedSpecialBonus = "special_bonus_unique_invoker_6", - levelkey = "exortlevel", - }, - ["09"] = { var_type = "FIELD_FLOAT", burn_duration = 3.0 }, - ["10"] = { - var_type = "FIELD_FLOAT", - burn_dps = "11.5 15 18.5 22 25.5 29 32.5 36", - levelkey = "exortlevel", - CalculateSpellDamageTooltip = 1, + ["invoker_alacrity"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "Z", + ["AbilitySound"] = "Hero_Invoker.Alacrity", + ["AbilityUnitTargetTeam"] = "DOTA_UNIT_TARGET_TEAM_FRIENDLY", + ["AbilityUnitTargetType"] = "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_CREEP", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_PHYSICAL", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ALLIES_YES", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["AbilityCastRange"] = 650, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 15, + ["AbilityManaCost"] = 90, + ["AbilityValues"] = { + ["bonus_attack_speed"] = { + ["value"] = "10 22 34 46 58 70 82 94 106 118", + ["levelkey"] = "wexlevel", + ["special_bonus_unique_invoker_5"] = "+35", + }, + ["bonus_damage"] = { + ["value"] = "10 22 34 46 58 70 82 94 106 118", + ["levelkey"] = "exortlevel", + ["special_bonus_unique_invoker_5"] = "+35", + ["CalculateSpellDamageTooltip"] = 0, + }, + ["bonus_attack_range"] = { + ["value"] = 0, + ["levelkey"] = "wexlevel", }, + ["duration"] = 9, }, }, - invoker_sun_strike = { - ID = 5386, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - MaxLevel = 1, - HotKeyOverride = "T", - AbilityUnitDamageType = "DAMAGE_TYPE_PURE", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_YES", - FightRecapLevel = 1, - AbilitySound = "Hero_Invoker.SunStrike.Charge", - AbilityCastRange = 0, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 25, - AbilityManaCost = 175, - AbilitySpecial = { - ["01"] = { var_type = "FIELD_FLOAT", delay = 1.7 }, - ["02"] = { var_type = "FIELD_INTEGER", area_of_effect = 175 }, - ["03"] = { - var_type = "FIELD_FLOAT", - damage = "100 162.5 225 287.5 350 412.5 475 537.5", - levelkey = "exortlevel", - }, - ["04"] = { var_type = "FIELD_INTEGER", vision_distance = 400 }, - ["05"] = { var_type = "FIELD_FLOAT", vision_duration = 4.0 }, + ["invoker_chaos_meteor"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "D", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.ChaosMeteor.Impact", + ["AbilityCastRange"] = 700, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 200, + ["AbilityModifierSupportValue"] = 0, + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 50, + }, + ["land_time"] = 1.3, + ["area_of_effect"] = { + ["value"] = 275, + ["affected_by_aoe_increase"] = 1, + ["special_bonus_unique_invoker_chaos_meteor_size"] = "+25", + }, + ["travel_distance"] = { + ["value"] = "465 615 780 930 1095 1245 1410 1575 1725 1890", + ["levelkey"] = "wexlevel", + }, + ["travel_speed"] = { + ["value"] = 300, + }, + ["damage_interval"] = { + ["value"] = 0.5, + ["CalculateSpellDamageTooltip"] = 0, + ["DamageTypeTooltip"] = "DAMAGE_TYPE_NONE", + }, + ["vision_distance"] = { + ["value"] = 500, + ["affected_by_aoe_increase"] = 1, + }, + ["end_vision_duration"] = 3, + ["main_damage"] = { + ["value"] = "55 80 105 130 155 180 205 220 235 250", + ["levelkey"] = "exortlevel", + }, + ["burn_duration"] = 3, + ["burn_dps"] = { + ["value"] = "10 15 20 25 30 35 40 45 50 55", + ["levelkey"] = "exortlevel", + ["CalculateSpellDamageTooltip"] = 1, + ["DamageTypeTooltip"] = "DAMAGE_TYPE_MAGICAL", + }, + ["meteor_count"] = { + ["value"] = 1, + ["special_bonus_unique_invoker_additional_chaos_meteors"] = "+2", + }, + ["stun_duration"] = { + ["value"] = 0, + }, }, }, - invoker_forge_spirit = { - ID = 5387, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - MaxLevel = 1, - HotKeyOverride = "F", - AbilitySound = "Hero_Invoker.ForgeSpirit", - AbilityCooldown = 30, - AbilityManaCost = 75, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { - var_type = "FIELD_FLOAT", - spirit_damage = "22 32 42 52 62 72 82 92", - levelkey = "exortlevel", - }, - ["02"] = { - var_type = "FIELD_INTEGER", - spirit_mana = "100 150 200 250 300 350 400 450", - levelkey = "exortlevel", - }, - ["03"] = { - var_type = "FIELD_INTEGER", - spirit_armor = "0 1 2 3 4 5 6 7", - levelkey = "exortlevel", - }, - ["04"] = { - var_type = "FIELD_FLOAT", - spirit_attack_range = "300 365 430 495 560 625 690 755", - levelkey = "quaslevel", - }, - ["05"] = { - var_type = "FIELD_INTEGER", - spirit_hp = "300 400 500 600 700 800 900 1000", - levelkey = "quaslevel", - }, - ["06"] = { - var_type = "FIELD_FLOAT", - spirit_duration = "20 30 40 50 60 70 80 90", - levelkey = "quaslevel", + ["invoker_sun_strike"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "T", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_PURE", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_YES", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.SunStrike.Charge", + ["HasScepterUpgrade"] = 1, + ["HasShardUpgrade"] = 1, + ["ShardRequiredFacet"] = "invoker_exort_focus", + ["ScepterRequiredFacet"] = "invoker_exort_focus", + ["AbilityCastRange"] = 0, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 175, + ["AbilityValues"] = { + ["delay"] = 1.7, + ["area_of_effect"] = { + ["value"] = 175, + ["affected_by_aoe_increase"] = 1, + }, + ["AbilityCooldown"] = { + ["value"] = 23, + ["special_bonus_unique_invoker_11"] = -4, + }, + ["damage"] = { + ["value"] = "175 225 275 325 375 425 475 525 575 625", + ["levelkey"] = "exortlevel", + }, + ["vision_distance"] = { + ["value"] = 400, + ["affected_by_aoe_increase"] = 1, + }, + ["vision_duration"] = 4, + ["cataclysm_count"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_exort_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "+2", + }, + }, + ["cataclysm_cooldown"] = { + ["value"] = 90, + }, + ["cataclysm_min_range"] = { + ["value"] = 90, + }, + ["cataclysm_max_range"] = { + ["value"] = 180, + }, + ["cataclysm_damage_pct"] = { + ["value"] = 75, + }, + ["create_forged_spirit_on_hero_damage"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_exort_focus"] = { + ["value"] = 0, + ["special_bonus_shard"] = "+1", + }, }, }, }, - invoker_ice_wall = { - ID = 5389, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - SpellDispellableType = "SPELL_DISPELLABLE_NO", - MaxLevel = 1, - HotKeyOverride = "G", - AbilityUnitDamageType = "DAMAGE_TYPE_MAGICAL", - FightRecapLevel = 1, - AbilitySound = "Hero_Invoker.IceWall.Cast", - AbilityCooldown = 25, - AbilityManaCost = 175, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilitySpecial = { - ["01"] = { - var_type = "FIELD_FLOAT", - duration = "3.0 4.5 6.0 7.5 9.0 10.5 12.0 13.5", - levelkey = "quaslevel", - }, - ["02"] = { - var_type = "FIELD_INTEGER", - slow = "-20 -40 -60 -80 -100 -120 -140 -160", - levelkey = "quaslevel", - }, - ["03"] = { var_type = "FIELD_FLOAT", slow_duration = 2.0 }, - ["04"] = { - var_type = "FIELD_FLOAT", - damage_per_second = "6 12 18 24 30 36 42 48", - levelkey = "exortlevel", - }, - ["05"] = { var_type = "FIELD_INTEGER", wall_place_distance = 200 }, - ["06"] = { var_type = "FIELD_INTEGER", num_wall_elements = 15 }, - ["07"] = { var_type = "FIELD_INTEGER", wall_element_spacing = 80 }, - ["08"] = { var_type = "FIELD_INTEGER", wall_element_radius = 105 }, + ["invoker_forge_spirit"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "F", + ["AbilitySound"] = "Hero_Invoker.ForgeSpirit", + ["AbilityCooldown"] = 27, + ["AbilityManaCost"] = 75, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["spirit_damage"] = { + ["value"] = "20 30 40 50 60 70 80 90 100 110", + ["levelkey"] = "exortlevel", + }, + ["spirit_mana"] = { + ["value"] = "100 150 200 250 300 350 400 450 500 550", + ["levelkey"] = "exortlevel", + }, + ["spirit_armor"] = { + ["value"] = "0 1 2 3 4 5 6 7 8 9", + ["levelkey"] = "exortlevel", + }, + ["spirit_attack_range"] = { + ["value"] = "305 360 415 470 525 580 635 690 745 800", + ["levelkey"] = "quaslevel", + }, + ["spirit_hp"] = { + ["value"] = "300 400 500 600 700 800 900 1000 1100 1200", + ["levelkey"] = "quaslevel", + }, + ["spirit_duration"] = { + ["value"] = "24 30 36 42 48 54 60 66 72 78", + ["levelkey"] = "quaslevel", + }, + ["armor_per_attack"] = { + ["value"] = "0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7", + ["levelkey"] = "exortlevel", + }, + ["extra_spirit_count_quas"] = { + ["value"] = "1 1 1 2 2 2 2 3 3 3", + ["levelkey"] = "quaslevel", + }, + ["extra_spirit_count_exort"] = { + ["value"] = "1 1 1 2 2 2 2 3 3 3", + ["levelkey"] = "exortlevel", + }, }, }, - invoker_deafening_blast = { - ID = 5390, - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", - SpellImmunityType = "SPELL_IMMUNITY_ENEMIES_NO", - SpellDispellableType = "SPELL_DISPELLABLE_NO", - MaxLevel = 1, - HotKeyOverride = "B", - AbilityUnitDamageType = "DAMAGE_TYPE_MAGICAL", - FightRecapLevel = 1, - AbilitySound = "Hero_Invoker.DeafeningBlast", - AbilityCastRange = 1000, - AbilityCastPoint = 0.05, - AbilityCastAnimation = "ACT_INVALID", - AbilityCooldown = 40, - AbilityManaCost = 300, - AbilityModifierSupportValue = 0.5, - AbilitySpecial = { - ["01"] = { var_type = "FIELD_INTEGER", travel_distance = 1000 }, - ["02"] = { var_type = "FIELD_INTEGER", travel_speed = 1100 }, - ["03"] = { var_type = "FIELD_INTEGER", radius_start = 175 }, - ["04"] = { var_type = "FIELD_INTEGER", radius_end = 225 }, - ["05"] = { var_type = "FIELD_FLOAT", end_vision_duration = 1.75 }, - ["06"] = { - var_type = "FIELD_FLOAT", - damage = "40 80 120 160 200 240 280 320", - levelkey = "exortlevel", - }, - ["07"] = { - var_type = "FIELD_FLOAT", - knockback_duration = "0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0", - levelkey = "quaslevel", - }, - ["08"] = { - var_type = "FIELD_FLOAT", - disarm_duration = "1.25 2.0 2.75 3.5 4.25 5.0 5.75 6.5", - levelkey = "wexlevel", + ["forged_spirit_melting_strike"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 8, + ["AbilityValues"] = { + ["armor_removed"] = "0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7", + ["max_armor_removed"] = 20, + ["duration"] = 5, + }, + ["AbilityCastAnimation"] = "ACT_DOTA_CAST_ABILITY_1", + }, + ["invoker_ice_wall"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "G", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.IceWall.Cast", + ["HasScepterUpgrade"] = 1, + ["ScepterRequiredFacet"] = "invoker_quas_focus", + ["AbilityCooldown"] = 23, + ["AbilityManaCost"] = 125, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["duration"] = { + ["value"] = "3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0", + ["levelkey"] = "quaslevel", + }, + ["slow"] = { + ["value"] = "-20 -40 -60 -80 -100 -120 -140 -160 -180 -200", + ["levelkey"] = "quaslevel", + }, + ["slow_duration"] = 2, + ["damage_per_second"] = { + ["value"] = "30 35 40 45 50 55 60 65 70 75", + ["levelkey"] = "exortlevel", + ["special_bonus_unique_invoker_ice_wall_dps"] = "+50", + }, + ["tick_interval"] = 0.5, + ["wall_place_distance"] = 200, + ["wall_total_length"] = { + ["value"] = 1200, + ["affected_by_aoe_increase"] = 1, + }, + ["wall_width"] = { + ["value"] = 105, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "+45", + }, + ["affected_by_aoe_increase"] = 1, + }, + ["vector_cast_range"] = { + ["value"] = 0, + ["special_bonus_unique_invoker_glacier"] = 600, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = 600, + }, + }, + ["glacier_formation_delay"] = 1.3, + ["glacier_formation_speed"] = 600, + ["root_delay"] = { + ["value"] = 0, + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = 2.5, + }, + }, + ["root_duration"] = { + ["value"] = 0, + ["levelkey"] = "quaslevel", + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5", + }, + }, + ["root_damage"] = { + ["value"] = 0, + ["levelkey"] = "quaslevel", + ["special_bonus_facet_invoker_quas_focus"] = { + ["value"] = 0, + ["special_bonus_scepter"] = "100 125 150 175 200 225 250 275 300 325", + }, }, }, }, - special_bonus_unique_invoker_1 = { - ID = 6097, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 2 } }, + ["invoker_deafening_blast"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_HIDDEN | DOTA_ABILITY_BEHAVIOR_NOT_LEARNABLE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING | DOTA_ABILITY_BEHAVIOR_SHOW_IN_GUIDES", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 1, + ["HotKeyOverride"] = "B", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.DeafeningBlast", + ["AbilityCastRange"] = 1000, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 36, + ["AbilityManaCost"] = 250, + ["AbilityModifierSupportValue"] = 0.5, + ["AbilityValues"] = { + ["travel_distance"] = { + ["value"] = 1000, + ["affected_by_aoe_increase"] = 1, + }, + ["travel_speed"] = 1100, + ["radius_start"] = { + ["value"] = 175, + ["affected_by_aoe_increase"] = 1, + }, + ["radius_end"] = { + ["value"] = 225, + ["affected_by_aoe_increase"] = 1, + }, + ["end_vision_duration"] = 1.75, + ["damage"] = { + ["value"] = "70 110 150 190 230 270 310 350 390 430", + ["levelkey"] = "exortlevel", + }, + ["knockback_duration"] = { + ["value"] = "1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0", + ["levelkey"] = "quaslevel", + }, + ["disarm_duration"] = { + ["value"] = "1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0", + ["levelkey"] = "wexlevel", + }, + ["radial_count"] = { + ["value"] = 1, + ["special_bonus_unique_invoker_2"] = "+11", + }, + }, }, - special_bonus_unique_invoker_2 = { - ID = 6098, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 0 } }, + ["invoker_mastermind"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_INNATE_UI | DOTA_ABILITY_BEHAVIOR_SKIP_FOR_KEYBINDS", + ["MaxLevel"] = 1, + ["Innate"] = 1, + ["AbilityValues"] = { + ["xp_on_deny_percent"] = 25, + }, }, - special_bonus_unique_invoker_3 = { - ID = 6099, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 16 } }, + ["invoker_cold_snap_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "Y", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.ColdSnap", + ["AbilityUnitTargetTeam"] = "DOTA_UNIT_TARGET_TEAM_ENEMY", + ["AbilityUnitTargetType"] = "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_BASIC", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["AbilityCastRange"] = 1000, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 90, + ["AbilityModifierSupportValue"] = 0.15, + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 20, + ["special_bonus_unique_invoker_9"] = -5, + }, + ["duration"] = { + ["value"] = "3.5 4.3 5.1 6.0", + }, + ["freeze_duration"] = 0.4, + ["freeze_cooldown"] = "0.8 0.75 0.70 0.65", + ["freeze_damage"] = "16 30 43 56", + ["damage_trigger"] = 10, + }, }, - special_bonus_unique_invoker_4 = { - ID = 6656, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { - ["01"] = { var_type = "FIELD_INTEGER", value = 2 }, - ["02"] = { var_type = "FIELD_INTEGER", cooldown = 90 }, - ["03"] = { var_type = "FIELD_INTEGER", min_range = 160 }, - ["04"] = { var_type = "FIELD_INTEGER", max_range = 200 }, + ["invoker_ghost_walk_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE | DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "V", + ["AbilitySound"] = "Hero_Invoker.GhostWalk", + ["AbilityManaCost"] = 200, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 45, + }, + ["duration"] = 100, + ["area_of_effect"] = { + ["value"] = 400, + ["affected_by_aoe_increase"] = 1, + }, + ["enemy_slow"] = "-20 -30 -40 -50", + ["self_slow"] = "-15 -5 5 15", + ["aura_fade_time"] = 2, }, }, - special_bonus_unique_invoker_5 = { - ID = 6657, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 50 } }, + ["invoker_tornado_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "X", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["AbilitySound"] = "Hero_Invoker.Tornado", + ["AbilityCastRange"] = 2000, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 140, + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 30, + ["special_bonus_unique_invoker_3"] = -4, + }, + ["travel_distance"] = "1200 1865 2530 3200", + ["travel_speed"] = 1000, + ["area_of_effect"] = { + ["value"] = 200, + ["affected_by_aoe_increase"] = 1, + }, + ["vision_distance"] = { + ["value"] = 200, + ["affected_by_aoe_increase"] = 1, + }, + ["end_vision_duration"] = 1.75, + ["lift_duration"] = { + ["value"] = "1.1 1.6 2.1 2.6", + }, + ["base_damage"] = 70, + ["quas_damage"] = "0 0 0 0", + ["wex_damage"] = "90 165 240 315", + }, }, - special_bonus_unique_invoker_6 = { - ID = 6811, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 40 } }, + ["invoker_emp_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "C", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["AbilitySound"] = "Hero_Invoker.EMP.Charge", + ["HasShardUpgrade"] = 1, + ["AbilityCastRange"] = 950, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 30, + ["AbilityManaCost"] = 125, + ["AbilityValues"] = { + ["delay"] = { + ["value"] = 2.9, + }, + ["area_of_effect"] = { + ["value"] = 675, + ["affected_by_aoe_increase"] = 1, + }, + ["mana_burned"] = { + ["value"] = "100 250 400 550", + }, + ["damage_per_mana_pct"] = { + ["value"] = 60, + ["special_bonus_shard"] = "+50%", + }, + ["shard_drag_speed"] = { + ["special_bonus_shard"] = 175, + }, + ["self_mana_restore_pct"] = 25, + }, }, - special_bonus_unique_invoker_7 = { - ID = 7016, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_FLOAT", value = 2.5 } }, + ["invoker_alacrity_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_UNIT_TARGET | DOTA_ABILITY_BEHAVIOR_DONT_RESUME_ATTACK | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "Z", + ["AbilitySound"] = "Hero_Invoker.Alacrity", + ["AbilityUnitTargetTeam"] = "DOTA_UNIT_TARGET_TEAM_FRIENDLY", + ["AbilityUnitTargetType"] = "DOTA_UNIT_TARGET_HERO | DOTA_UNIT_TARGET_CREEP", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ALLIES_YES", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["AbilityCastRange"] = 650, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 17, + ["AbilityManaCost"] = 90, + ["AbilityValues"] = { + ["bonus_attack_speed"] = { + ["value"] = "22 42 62 82", + ["special_bonus_unique_invoker_5"] = "+35", + }, + ["bonus_damage"] = { + ["value"] = "22 42 62 82", + ["special_bonus_unique_invoker_5"] = "+35", + }, + ["duration"] = 9, + }, }, - special_bonus_unique_invoker_8 = { - ID = 7017, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_FLOAT", value = 1.25 } }, + ["invoker_sun_strike_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "T", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_PURE", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_YES", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.SunStrike.Charge", + ["HasScepterUpgrade"] = 1, + ["AbilityCastRange"] = 0, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 25, + ["AbilityManaCost"] = 175, + ["AbilityValues"] = { + ["delay"] = 1.7, + ["area_of_effect"] = { + ["value"] = 175, + ["affected_by_aoe_increase"] = 1, + }, + ["damage"] = "162 266 370 475", + ["vision_distance"] = 400, + ["vision_duration"] = 4, + ["cataclysm_count"] = { + ["special_bonus_scepter"] = "+2", + }, + ["cataclysm_cooldown"] = { + ["special_bonus_scepter"] = 100, + }, + ["cataclysm_min_range"] = { + ["special_bonus_scepter"] = 160, + }, + ["cataclysm_max_range"] = { + ["special_bonus_scepter"] = 200, + }, + }, }, - special_bonus_unique_invoker_9 = { - ID = 7148, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 15 } }, + ["invoker_forge_spirit_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "F", + ["AbilitySound"] = "Hero_Invoker.ForgeSpirit", + ["AbilityCooldown"] = 30, + ["AbilityManaCost"] = 75, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["spirit_damage"] = "32 49 66 82", + ["spirit_mana"] = "150 233 316 400", + ["spirit_armor"] = "1 2 4 6", + ["spirit_attack_range"] = "365 470 580 690", + ["spirit_hp"] = "400 566 733 900", + ["spirit_duration"] = "30 47 63 80", + ["spirit_count"] = { + ["value"] = 1, + }, + ["spirit_attack_speed"] = { + ["special_bonus_unique_invoker_11"] = "+50", + }, + }, }, - special_bonus_unique_invoker_10 = { - ID = 7390, - AbilityType = "DOTA_ABILITY_TYPE_ATTRIBUTES", - AbilityBehavior = "DOTA_ABILITY_BEHAVIOR_PASSIVE", - AbilitySpecial = { ["01"] = { var_type = "FIELD_INTEGER", value = 30 } }, + ["invoker_chaos_meteor_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "D", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_YES", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.ChaosMeteor.Impact", + ["AbilityCastRange"] = 700, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityManaCost"] = 200, + ["AbilityModifierSupportValue"] = 0, + ["AbilityValues"] = { + ["AbilityCooldown"] = { + ["value"] = 55, + }, + ["land_time"] = 1.3, + ["area_of_effect"] = { + ["value"] = 275, + ["affected_by_aoe_increase"] = 1, + }, + ["travel_distance"] = { + ["value"] = "615 880 1145 1410", + }, + ["travel_speed"] = 300, + ["damage_interval"] = { + ["value"] = 0.5, + ["CalculateSpellDamageTooltip"] = 0, + ["DamageTypeTooltip"] = "DAMAGE_TYPE_NONE", + }, + ["vision_distance"] = { + ["value"] = 500, + ["affected_by_aoe_increase"] = 1, + }, + ["end_vision_duration"] = 3, + ["main_damage"] = { + ["value"] = "71 103 134 166", + }, + ["burn_duration"] = 3, + ["burn_dps"] = { + ["value"] = "14 20 26.5 32.5", + ["CalculateSpellDamageTooltip"] = 1, + ["DamageTypeTooltip"] = "DAMAGE_TYPE_MAGICAL", + }, + ["meteor_count"] = { + ["value"] = 1, + ["special_bonus_unique_invoker_additional_chaos_meteors"] = "+2", + }, + }, + }, + ["invoker_ice_wall_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "G", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.IceWall.Cast", + ["AbilityCooldown"] = 25, + ["AbilityManaCost"] = 125, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityValues"] = { + ["duration"] = "3.0 6.0 9.0 12.0", + ["slow"] = "-20 -80 -140 -200", + ["slow_duration"] = 2, + ["damage_per_second"] = { + ["value"] = "30 45 60 75", + ["special_bonus_unique_invoker_ice_wall_dps"] = "+50", + }, + ["tick_interval"] = 0.5, + ["wall_place_distance"] = 200, + ["wall_total_length"] = { + ["value"] = 1200, + ["affected_by_aoe_increase"] = 1, + }, + ["wall_width"] = { + ["value"] = 105, + ["affected_by_aoe_increase"] = 1, + }, + ["vector_cast_range"] = { + ["value"] = 0, + ["special_bonus_unique_invoker_glacier"] = 600, + }, + ["glacier_formation_delay"] = 1.3, + ["glacier_formation_speed"] = 600, + }, + }, + ["invoker_deafening_blast_ad"] = { + ["AbilityBehavior"] = "DOTA_ABILITY_BEHAVIOR_POINT | DOTA_ABILITY_BEHAVIOR_IGNORE_BACKSWING", + ["SpellImmunityType"] = "SPELL_IMMUNITY_ENEMIES_NO", + ["SpellDispellableType"] = "SPELL_DISPELLABLE_NO", + ["MaxLevel"] = 4, + ["HotKeyOverride"] = "B", + ["AbilityUnitDamageType"] = "DAMAGE_TYPE_MAGICAL", + ["FightRecapLevel"] = 1, + ["AbilitySound"] = "Hero_Invoker.DeafeningBlast", + ["AbilityCastRange"] = 1000, + ["AbilityCastPoint"] = 0.05, + ["AbilityCastAnimation"] = "ACT_INVALID", + ["AbilityCooldown"] = 40, + ["AbilityManaCost"] = 250, + ["AbilityModifierSupportValue"] = 0.5, + ["AbilityValues"] = { + ["travel_distance"] = 1000, + ["travel_speed"] = 1100, + ["radius_start"] = { + ["value"] = 175, + ["affected_by_aoe_increase"] = 1, + }, + ["radius_end"] = { + ["value"] = 225, + ["affected_by_aoe_increase"] = 1, + }, + ["end_vision_duration"] = 1.75, + ["damage"] = "60 127 293 260", + ["knockback_duration"] = "0.4 0.74 1.06 1.4", + ["disarm_duration"] = "2.0 3.25 4.5 5.75", + ["radial_count"] = { + ["value"] = 1, + ["special_bonus_unique_invoker_2"] = "+11", + }, + }, }, } + +return M diff --git a/spec/support/fixtures/scripts/npc/npc_heroes_txt.lua b/spec/support/fixtures/scripts/npc/npc_heroes_txt.lua index b8dbf0c..e97c5d6 100644 --- a/spec/support/fixtures/scripts/npc/npc_heroes_txt.lua +++ b/spec/support/fixtures/scripts/npc/npc_heroes_txt.lua @@ -1,67 +1,55 @@ return { + npc_dota_hero_axe = { + AbilityTalentStart = 1, + }, npc_dota_hero_invoker = { - Model = "models/heroes/invoker/invoker.vmdl", - Persona = { - ["1"] = { - name = "npc_dota_hero_invoker_persona1", - Model = "models/heroes/invoker_kid/invoker_kid.vmdl", + ["HeroID"] = 74, + + ["Ability1"] = "invoker_quas", + ["Ability2"] = "invoker_wex", + ["Ability3"] = "invoker_exort", + ["Ability4"] = "invoker_empty1", + ["Ability5"] = "invoker_empty2", + ["Ability6"] = "invoker_invoke", + ["Ability7"] = "invoker_cold_snap", + ["Ability8"] = "invoker_ghost_walk", + ["Ability9"] = "invoker_tornado", + ["Ability10"] = "invoker_emp", + ["Ability11"] = "invoker_alacrity", + ["Ability12"] = "invoker_chaos_meteor", + ["Ability13"] = "invoker_sun_strike", + ["Ability14"] = "invoker_forge_spirit", + ["Ability15"] = "invoker_ice_wall", + ["Ability16"] = "invoker_deafening_blast", + + ["AbilityTalentStart"] = 17, + + ["Ability17"] = "special_bonus_unique_invoker_ice_wall_dps", + ["Ability18"] = "special_bonus_unique_invoker_3", + ["Ability19"] = "special_bonus_unique_invoker_facet_orb_level", + ["Ability20"] = "special_bonus_unique_invoker_9", + ["Ability21"] = "special_bonus_unique_invoker_additional_chaos_meteors", + ["Ability22"] = "special_bonus_unique_invoker_5", + ["Ability23"] = "special_bonus_unique_invoker_2", + ["Ability24"] = "special_bonus_unique_invoker_13", + ["Ability25"] = "", + + ["Facets"] = { + ["invoker_quas_focus"] = { + ["Icon"] = "invoker_quas", + ["Color"] = "Blue", + ["GradientID"] = 0, + }, + ["invoker_wex_focus"] = { + ["Icon"] = "invoker_wex", + ["Color"] = "Purple", + ["GradientID"] = 0, + }, + ["invoker_exort_focus"] = { + ["Icon"] = "invoker_exort", + ["Color"] = "Yellow", + ["GradientID"] = 0, }, }, - Enabled = 1, - HeroUnlockOrder = 3, - Role = "Carry,Nuker,Disabler,Escape,Pusher", - Rolelevels = "1,3,2,1,1", - Complexity = 3, - Team = "Bad", - HeroID = 74, - ModelScale = 0.740000, - LoadoutScale = 0.800000, - CMEnabled = 1, - workshop_guide_name = "Invoker", - GibType = "default", - Ability1 = "invoker_quas", - Ability2 = "invoker_wex", - Ability3 = "invoker_exort", - Ability4 = "invoker_empty1", - Ability5 = "invoker_empty2", - Ability6 = "invoker_invoke", - Ability7 = "invoker_cold_snap", - Ability8 = "invoker_ghost_walk", - Ability9 = "invoker_tornado", - Ability10 = "invoker_emp", - Ability11 = "invoker_alacrity", - Ability12 = "invoker_chaos_meteor", - Ability13 = "invoker_sun_strike", - Ability14 = "invoker_forge_spirit", - Ability15 = "invoker_ice_wall", - Ability16 = "invoker_deafening_blast", - Ability17 = "special_bonus_unique_invoker_10", - Ability18 = "special_bonus_unique_invoker_6", - Ability19 = "special_bonus_unique_invoker_1", - Ability20 = "special_bonus_unique_invoker_9", - Ability21 = "special_bonus_unique_invoker_4", - Ability22 = "special_bonus_unique_invoker_5", - Ability23 = "special_bonus_unique_invoker_2", - Ability24 = "special_bonus_unique_invoker_3", - AbilityTalentStart = 17, - AbilityDraftDisabled = 1, - ArmorPhysical = 0, - AttackCapabilities = "DOTA_UNIT_CAP_RANGED_ATTACK", - AttackDamageMin = 27, - AttackDamageMax = 33, - AttackRate = 1.700000, - AttackAnimationPoint = 0.400000, - AttackAcquisitionRange = 800, - AttackRange = 600, - ProjectileSpeed = 900, - AttributePrimary = "DOTA_ATTRIBUTE_INTELLECT", - AttributeBaseStrength = 18, - AttributeStrengthGain = 2.400000, - AttributeBaseAgility = 14, - AttributeAgilityGain = 1.900000, - AttributeBaseIntelligence = 15, - AttributeIntelligenceGain = 4.600000, - MovementSpeed = 280, - MovementTurnRate = 0.500000, }, } diff --git a/spec/support/game_mode.lua b/spec/support/game_mode.lua new file mode 100644 index 0000000..fc14d60 --- /dev/null +++ b/spec/support/game_mode.lua @@ -0,0 +1,2 @@ +require("invk.lang.global") +require("compat53") diff --git a/spec/support/mock.lua b/spec/support/mock.lua new file mode 100644 index 0000000..af1bf1d --- /dev/null +++ b/spec/support/mock.lua @@ -0,0 +1,124 @@ +local assert = require("luassert") +local class = require("pl.class") +local spy = require("luassert.spy") +local stub = require("luassert.stub") + +--- @alias support.mock.Factory fun(mock: support.Mock): luassert.spy +--- @alias support.mock.Factories { [string]: support.mock.Factory } + +--- @class support.Mock +--- @field private _spies { [string]: { [string]: luassert.spy } } +--- @field private _factories support.mock.Factories +--- @overload fun(factories?: support.mock.Factories): support.Mock +local Mock = class() + +--- @param factories? support.mock.Factories +function Mock:_init(factories) + self._spies = {} + self._factories = factories or {} +end + +--- @param name string +function Mock:setup(name) + self._factories[name](self) +end + +--- @param name string +--- @param t table +--- @param key string +--- @param ... any +function Mock:stub(name, t, key, ...) + self._spies[name] = self._spies[name] or {} + self._spies[name][key] = stub.new(t, key, ...) +end + +--- @private +--- @param name string +--- @param t table +--- @param key string +function Mock:_spy(name, t, key) + self._spies[name] = self._spies[name] or {} + self._spies[name][key] = spy.on(t, key) +end + +--- @param name string +--- @param t table +--- @param key string | string[] +function Mock:spy(name, t, key) + if type(key) == "table" then + for _, k in ipairs(key) do + self:_spy(name, t, k) + end + else + self:_spy(name, t, key) + end +end + +--- @param name string +--- @param key string +--- @return luassert.spy.assert +function Mock:assert(name, key) + return assert.spy(self._spies[name][key]) +end + +--- @private +--- @param name string +--- @param key string +function Mock:_clear(name, key) + self._spies[name][key]:clear() +end + +--- @param name string +--- @param ... string +function Mock:clear(name, ...) + if select("#", ...) == 0 then + for key, _ in pairs(self._spies[name]) do + self:_clear(name, key) + end + else + for _, key in ipairs({ ... }) do + self:_clear(name, key) + end + end +end + +--- @private +--- @param name string +--- @param key string +function Mock:_revert(name, key) + self._spies[name][key]:revert() +end + +--- @param name string +--- @param ... string +function Mock:revert(name, ...) + if select("#", ...) == 0 then + for key, _ in pairs(self._spies[name]) do + self:_revert(name, key) + end + else + for _, key in ipairs({ ... }) do + self:_revert(name, key) + end + end +end + +--- @param name? string +--- @param ... string +function Mock:reset(name, ...) + if name then + self:clear(name, ...) + self:revert(name, ...) + + self._spies[name] = {} + else + for n, _ in pairs(self._spies) do + self:clear(n) + self:revert(n) + end + + self._spies = {} + end +end + +return Mock From 910391dcda51054dcae49b04879ab8b35d44961b Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:16:05 -0300 Subject: [PATCH 05/29] chore: update ignore files --- .gitignore | 15 +++++++++------ .ignore | 5 +++-- .styluaignore | 5 +++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index a5ebe30..cab0b7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,20 @@ # project + /.env* /tmp/* !/tmp/.keep + # lua -/.lua-version -/.luarocks -/lua -/lua_modules -/luarocks + +/.lux + # javascript/typescript -/.node-version + /node_modules +*.tsbuildinfo + # game + /content/panorama/scripts/* /game/* !/game/resource diff --git a/.ignore b/.ignore index 9071b6b..da25ef7 100644 --- a/.ignore +++ b/.ignore @@ -1,5 +1,6 @@ -game/scripts/vscripts/pl -game/scripts/vscripts/moses.lua +game/scripts/vscripts/compat53 game/scripts/vscripts/fsm.lua +game/scripts/vscripts/inspect.lua +game/scripts/vscripts/middleclass.lua images tmp diff --git a/.styluaignore b/.styluaignore index 0446851..4ee9b02 100644 --- a/.styluaignore +++ b/.styluaignore @@ -1,3 +1,4 @@ +/game/scripts/vscripts/compat53/** /game/scripts/vscripts/fsm.lua -/game/scripts/vscripts/moses.lua -/game/scripts/vscripts/pl/** +/game/scripts/vscripts/inspect.lua +/game/scripts/vscripts/middleclass.lua From 29adf3bdc4016fee4973e362487b8658e9364eb2 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:16:14 -0300 Subject: [PATCH 06/29] chore: update luacov config --- .luacov | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.luacov b/.luacov index 7ead1ff..664c92c 100644 --- a/.luacov +++ b/.luacov @@ -41,7 +41,7 @@ return { -- } include = { "game/scripts/vscripts/addon_game_mode$", - "game/scripts/vscripts/invokation%/.+$", + "game/scripts/vscripts/invk%/.+$", }, --- Lua patterns for files to exclude when reporting. From 850daadf389a0cfb3835895c453f6b8364e2176c Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:26:36 -0300 Subject: [PATCH 07/29] chore: remove luacov --- .busted | 1 - .emmyrc.json | 2 -- .luacov | 70 ---------------------------------------------------- lux.lock | 44 --------------------------------- lux.toml | 1 - 5 files changed, 118 deletions(-) delete mode 100644 .luacov diff --git a/.busted b/.busted index 58a5bf6..a5fdf5b 100644 --- a/.busted +++ b/.busted @@ -20,7 +20,6 @@ return { }, _all = { verbose = true, - coverage = true, helper = "./spec/helper.lua", lpath = lpath, }, diff --git a/.emmyrc.json b/.emmyrc.json index eeaab14..7e112e1 100644 --- a/.emmyrc.json +++ b/.emmyrc.json @@ -30,7 +30,6 @@ "game/scripts/vscripts/middleclass.lua", ".lux/jit/test_dependencies/jit/01a3c364614bddff7370223a5a9c4580f8e62d144384148444c518ec5367a59b-mediator_lua@1.1.2-0/src", ".lux/jit/test_dependencies/jit/092886a00e3c7cb9cb944528116da6ce7d5e4a25b9d198735ac1b1307f77dca5-bit32@5.3.5-1/src", - ".lux/jit/test_dependencies/jit/117a52658298bf0e7dc607718e5e39ef93468c41c45dcf8650d7986d93e19341-luacov@0.16.0-1/src", ".lux/jit/test_dependencies/jit/287e827f4a088d41bba04af5f61a13614346c16fe8150eb7c4246e67d6fd163e-lua-term@0.8-1/src", ".lux/jit/test_dependencies/jit/316ac0b30e04e86a253d64886f3b110bd0508267474e6b58a3b973bd6857dbf4-penlight@1.14.0-3/src", ".lux/jit/test_dependencies/jit/455cd98d50c6191a9685cffcda4ce783efbb957934625e134c39f43bd5df6818-luassert@1.9.0-1/src", @@ -44,7 +43,6 @@ ".lux/jit/test_dependencies/jit/a6c5176043cb3de56336b7de119443dbb3d9e024be1d50e06289ad4b4959a2da-lua_cliargs@3.0.2-1/src", ".lux/jit/test_dependencies/jit/c82b26bea8099fcea79b4e243145c4cf2597abdde010248e02fcd273e490e1bb-penlight@1.14.0-3/src", ".lux/jit/test_dependencies/jit/d792a2d7b67521e3af5c323f99f9c5b20625b649826613bdf93854482c22dd1b-moses@2.1.0-1/src", - ".lux/jit/test_dependencies/jit/e496d4ec14c0feec0b3eac3f622f59eb3777d6e63b24469fdb464841e6ab4e63-datafile@0.11-1/src", ".lux/jit/test_dependencies/jit/e4f17b9e67313bbd5e90f425672fc8998dd0bfa43335f7c57ed2de7a799e07a6-dkjson@2.8-1/src" ] } diff --git a/.luacov b/.luacov deleted file mode 100644 index 664c92c..0000000 --- a/.luacov +++ /dev/null @@ -1,70 +0,0 @@ --- vim: ft=lua - -return { - --- Filename to store collected stats. Default: "luacov.stats.out". - statsfile = "tmp/luacov.stats.txt", - - --- Filename to store report. Default: "luacov.report.out". - reportfile = "tmp/luacov.report.txt", - - --- Enable saving coverage data after every `savestepsize` lines? - -- Setting this flag to `true` in config is equivalent to running LuaCov - -- using `luacov.tick` module. Default: false. - tick = false, - - --- Stats file updating frequency for `luacov.tick`. - -- The lower this value - the more frequently results will be written out to the stats file. - -- You may want to reduce this value (to, for example, 2) to avoid losing coverage data in - -- case your program may terminate without triggering luacov exit hooks that are supposed - -- to save the data. Default: 100. - savestepsize = 100, - - --- Run reporter on completion? Default: false. - runreport = true, - - --- Delete stats file after reporting? Default: false. - deletestats = true, - - --- Process Lua code loaded from raw strings? - -- That is, when the 'source' field in the debug info - -- does not start with '@'. Default: false. - codefromstrings = false, - - --- Lua patterns for files to include when reporting. - -- All will be included if nothing is listed. - -- Do not include the '.lua' extension. Path separator is always '/'. - -- Overruled by `exclude`. - -- @usage - -- include = { - -- "mymodule$", -- the main module - -- "mymodule%/.+$", -- and everything namespaced underneath it - -- } - include = { - "game/scripts/vscripts/addon_game_mode$", - "game/scripts/vscripts/invk%/.+$", - }, - - --- Lua patterns for files to exclude when reporting. - -- Nothing will be excluded if nothing is listed. - -- Do not include the '.lua' extension. Path separator is always '/'. - -- Overrules `include`. - exclude = {}, - - --- Table mapping names of modules to be included to their filenames. - -- Has no effect if empty. - -- Real filenames mentioned here will be used for reporting - -- even if the modules have been installed elsewhere. - -- Module name can contain '*' wildcard to match groups of modules, - -- in this case corresponding path will be used as a prefix directory - -- where modules from the group are located. - -- @usage - -- modules = { - -- ["some_rock"] = "src/some_rock.lua", - -- ["some_rock.*"] = "src" - -- } - modules = {}, - - --- Enable including untested files in report. - -- Default: false. - includeuntestedfiles = false, -} diff --git a/lux.lock b/lux.lock index 6d6572a..9271f8b 100644 --- a/lux.lock +++ b/lux.lock @@ -38,30 +38,6 @@ "source": "sha256-q53sd82FUQL+xw5rILdegS2xqZ4/KAMMWzTcD+uIyD0=" } }, - "117a52658298bf0e7dc607718e5e39ef93468c41c45dcf8650d7986d93e19341": { - "name": "luacov", - "version": "0.16.0-1", - "pinned": false, - "opt": false, - "dependencies": [ - "e496d4ec14c0feec0b3eac3f622f59eb3777d6e63b24469fdb464841e6ab4e63" - ], - "constraint": ">=0.16.0, <0.17.0", - "binaries": [ - "luacov", - "luacov" - ], - "source": "luarocks_rockspec+https://luarocks.org/", - "source_url": { - "type": "git", - "url": "https://github.com/lunarmodules/luacov.git", - "ref": "v0.16.0" - }, - "hashes": { - "rockspec": "sha256-fbdS+kCvyMlE1qUZTDm+sGwroa1NCR0YFSR00a4pwPo=", - "source": "sha256-GoJqiFyXH4chQ/k/qBPttnh/V4vUSfR2Lg8rt3CPKoY=" - } - }, "287e827f4a088d41bba04af5f61a13614346c16fe8150eb7c4246e67d6fd163e": { "name": "lua-term", "version": "0.8-1", @@ -330,25 +306,6 @@ "source": "sha256-koGDl+3kjV0EkeeTsmc5zuVoljT7s47Et8w8JoPfv1g=" } }, - "e496d4ec14c0feec0b3eac3f622f59eb3777d6e63b24469fdb464841e6ab4e63": { - "name": "datafile", - "version": "0.11-1", - "pinned": false, - "opt": false, - "dependencies": [], - "constraint": null, - "binaries": [], - "source": "luarocks_rockspec+https://luarocks.org/", - "source_url": { - "type": "git", - "url": "https://github.com/hishamhm/datafile.git", - "ref": "v0.11" - }, - "hashes": { - "rockspec": "sha256-2DDuPfJZustlH90MsItOvpTv2+weKIyFE2SwPxX2ICY=", - "source": "sha256-aHdxFJ2IB9v9UMK7vqk7tUA0rLmfvRd0nzhc9JO8AlQ=" - } - }, "e4f17b9e67313bbd5e90f425672fc8998dd0bfa43335f7c57ed2de7a799e07a6": { "name": "dkjson", "version": "2.8-1", @@ -370,7 +327,6 @@ }, "entrypoints": [ "092886a00e3c7cb9cb944528116da6ce7d5e4a25b9d198735ac1b1307f77dca5", - "117a52658298bf0e7dc607718e5e39ef93468c41c45dcf8650d7986d93e19341", "672112d42de52914cd6daaac8a86cf906f80360bd81d6ad0a1df51224d74e9d4", "8a29d183b38f69620275ab4765d677ada24ff5f96f48d2018d0ee7bcd8ad057e", "9a3c8a33388fd17cf44291697753b48efba841849e4a92dc37c4f7a4c6877c86", diff --git a/lux.toml b/lux.toml index d034085..24e1978 100644 --- a/lux.toml +++ b/lux.toml @@ -17,7 +17,6 @@ bit32 = "~> 5.3" busted = "~> 2.2" busted-htest = "~> 1.0" compat53 = "~> 0.14" -luacov = "~> 0.16" moses = "~> 2.1" penlight = "~> 1.14" From 40567496bd34afaceacb9aeed8a50513d3f72fac Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:26:44 -0300 Subject: [PATCH 08/29] chore: remove vscode config --- .vscode/extensions.json | 12 ----- .vscode/settings.json | 18 -------- .vscode/tasks.json | 99 ----------------------------------------- 3 files changed, 129 deletions(-) delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 3bb8657..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "recommendations": [ - "JohnnyMorganz.stylua", - "Kampfkarren.selene-vscode", - "biomejs.biome", - "esbenp.prettier-vscode", - "geekidos.vdf", - "redhat.vscode-xml", - "stylelint.vscode-stylelint", - "sumneko.lua" - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 530720b..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "files.associations": { - "**/game/**/*.txt": "vdf", - "**/content/materials/**/*.txt": "vdf" - }, - - "search.exclude": { - "**/.luarocks": true, - "**/lua_modules": true, - "**/node_modules": true - }, - - "css.validate": false, - "vim.textwidth": 100, - "prettier.printWidth": 100, - "yaml.format.printWidth": 100, - "typescript.tsdk": "node_modules/typescript/lib" -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 0f23bc1..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Clean", - "type": "shell", - "command": "make clean", - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - }, - { - "label": "Install", - "type": "shell", - "command": "make install", - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - }, - { - "label": "Build", - "type": "shell", - "command": "make build", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - }, - { - "label": "Build (Force)", - "type": "shell", - "command": "make build", - "options": { - "env": { - "FORCE_BUILD": "1" - } - }, - "group": "build", - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": true, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - }, - { - "label": "Launch Game", - "type": "shell", - "command": "make launch-game", - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "never", - "focus": false, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - }, - { - "label": "Launch Tools", - "type": "shell", - "command": "make launch-tools", - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "never", - "focus": false, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - } - ] -} From 270b0003d9afa90641e6609c1d192be79c42f68c Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:26:58 -0300 Subject: [PATCH 09/29] build: update tasks to use lux --- Taskfile.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index 1e6a284..e674319 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -10,6 +10,7 @@ vars: TASKS_SRC_PATH: "src/tasks" TASKS_ENTRYPOINT: "{{ .TASKS_SRC_PATH }}/main.ts" TASKS_DEBUG_FLAGS: '{{ empty .DEBUG | ternary "" "--debug" }}' + LX_ARGS: "--lua-version jit" tasks: default: @@ -82,7 +83,7 @@ tasks: test:vscripts: desc: Test vscripts - cmd: luarocks test + cmd: lx {{ .LX_ARGS }} test -- {{ .CLI_ARGS }} format:panorama: desc: Format all panorama files From 0a2c6810fbf9d955050d2cf95a46e82e1c598736 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:27:16 -0300 Subject: [PATCH 10/29] chore: update biome config --- biome.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/biome.json b/biome.json index ffe6f92..a9e95e1 100644 --- a/biome.json +++ b/biome.json @@ -21,13 +21,11 @@ "useSimplifiedLogicExpression": "warn" }, "correctness": { - "noConstantMathMinMaxClamp": "warn", "noNewSymbol": "error", "noUndeclaredVariables": "error", "noUnusedImports": "warn", "noUnusedPrivateClassMembers": "warn", - "noUnusedVariables": "warn", - "useArrayLiterals": "warn" + "noUnusedVariables": "warn" }, "style": { "noDefaultExport": "warn", From ab2da6f508fdc8b1298429749ef388790e88a857 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 09:27:38 -0300 Subject: [PATCH 11/29] chore: update javascript dependencies --- bun.lockb | Bin 90360 -> 102200 bytes package.json | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bun.lockb b/bun.lockb index f1c4b9ab62fce669b3043bdd717a6d1d72240ecd..5b42def789c9fa05c0d254af40d972dc469f7b30 100755 GIT binary patch delta 16964 zcmeHvXINB8)As2h4vK&xFo24pfPo>(fFMZ>FsOh5%%F^d2qgQBP?rdE%N0drOq zUDLW|S21GFS=WR)toglb!tOlbeSUo3cU|9~=Um=XT~*!H)z#H~&dj0x^PtJDC8jgw zjkbF|`F5}4^pB6tBNcztN^Z+jCpQ*O7uyWHFAqFdJ>>G*=}e%j8k?0=+o*FDwspiE zNrWwg7J`uH=!`Ovg;a!aDsO56)kkz2n*HKV%ekJTw1O4fx4aGxHj6Uxqs0_3W6y4_) z>*xefay$#v4m3$eIqXnKhoxr?&dtseKKW_+j-UvsI`23NR;X~A8akWcTZvos%hCLA{!&*H_giErpx|Umg5bP;&GID9urJmdZ0XJyX>;OP-aIsS@@> zPLWO-JR++P+LeGOhcbo?P~`|Af}qNxIY<>E0<{syRSnPeOj8Z-lRY3i2MxLe2|`sg zSOrQQ>64+CAKzmlSI-F6PDXZCADS9rSWe2ofg=Q=0CMVgBD$dQ-2kNk@5UsMne?o_ z1Je7Y<&Hu<@;h4Re;6p$%MR7H-v&y7S7m1RPalxpTLqrbwBm0Q(Kd?oAG4 zhieUHre~!OOc^|QH+XX7pB?I}liNjV2OtHdnSTLF_4V{MvW>=Xu1oLo7TN)5(_Jm( zb%r5I$GcJ5j)$eC_em23p=@W7PZG*9Gc-@#Z?xj89wTWJmVADo@lH+_Jr z5IjYqAqGVCQ?qkbSx9IX-2gG~12SOO2t3uxZ3C)CVHXPI;TvCVO56h_hl--LhR%bh zDX@#t(&OMMgbTpaNHvB)Z|eA8p(lImKx=?50wsrX&^hINAFM*p{(}XVSS(zcOKEJ` zGqaZx^Q8^)nlzrM>b>Hs1#>a0jQ@1=kA7B*vs-nnXqGwK(KC2nc^9M??2_%T=09*inKW4`>i2%JyPBGcps@KxpQ&zFLl=Ygsp5aI^V{TueI>t zYpc}d*Q&Jl-nX$$m~&#_(u#nx$o*&D_6+k}XWsvM?N?Us#Cdf>&z5YwZrAkS$95Hu zKKo@nbTyLjq^facrB&-2F)5F?Ys?Q=nU|Sc$J+6WR{qiyBqLHe&jcz3yUC}xg_*cH z3qo&x+BR4^86~WvJjUZ|E7(aM?H(qP*5ZZkp(Z`BX-4uQ_h6H9l$!C=)q|zRwFLpe z&698&TLp{ZQ#`_?(;*`hM!cfBLV65boW@{7|v6AO!H!*1^)zD3L`8pJlC(ZU+~xwNXQ1!s>$4_!5B`Cd0vX({y?PrLI~FGKIv`m0Ng*noM^U zgjfm`yUwS0hDihJ3j(q}&z#%TR7gjI>jthq`DytM9E}T^EZFl3Yt1}ZdNt5S42uza z`8cb_JUl>Z4q-b@Uzii=7I2-xnW2$FYT~BVnP~>!0bBrd=DZ?EA)Nv)5*%g=<2ngW z8^{Wo!qUuL5U>^JVf71`ig0cBA&~Zk6hZ-kl53^QA*GhaB<42WTIp>_<8^f#Xk0}i zNxg7WqUgapOlTi)SfzOu+{Q*>xe;7*aHd-8zFIq9Aq|F;Aj8!8Elk*s_Q0Wx8b`B6% znL>IV9L=o2XL%^3wQw`m#DventUG(-rUo7658M!No&Ms=!O@&)bxuBl(Ecy3|37fM z!L|KMXNpy<{ELe>;JkRaZyQOvA20L`m6-eUa^FyC0uq3hF?zuOX8Q9OzfkEz2%|K@ z_!e< zaN4AvC09ru2JrHxp;A|c)*Px}mb!r>bDI2-&H_g(U$a?APAYhLK&bRPgyb6*Ii^kt zSG2npH6H_xnrk)yX&E?ee@JNQD{%Nnrcu)!`9ke9yO%^2#0vvMrDYJ3X@OTXP)I+4 zqhSlQe@dIe5v?%bEy}*7 z;M#ygl%oP!Ft-Q}mD0`I zqH4|yLqesCA=FMIMkl$^oLe*xmC7KYcG@*F9Go_q6oAvN? zrJPb`3OHIanpu^e)#vS;gs4z)DwjyE&pxA5}ClZxAC0m_|f^mO?5x>Jr&lQz2O%!wcJlN*=}V za*#SoZV??S>7e8>(V-?q*hr%IX_sJ0g_4&?kCn({c}z^GL>0>mL6*nzauA_ynT0aJ zhzVt#+L|6k--X%PS zYdW|LhOU1{$*~&%8Mq11MU)KOCI*)wrFwS&(%%Es^zl!W>Urt(-a0)|D*E7qyi_nuC0!_J6oI70MU;v` z_#i{UI=LYwd2^lIkQzfC0XeB6b^8CEYWvqzq?~Du24px|*U*rXC+1arr8FW#J#`gRK&ftT9qmI5E<;Kk^wr6UQu{O=Pn3%3I{x2L zQuWu>Q)lQZ8d4Gs(8-BX2U(yb%GS|=I(d$cAFQLfpmhB^N=sz4POqbO8Ub}MR;M6p zUN%N~NAlm@24VT{Zu8&W=D)km|D)Ze`oHcrd_>pWaB1@39u_x$tXNs#KJem;gKewK zZ@KgBk)|hn5{7iYY3rQYu5-r1k#*f}K5wvUaeU(K#g+96i)L?VQ@r!boj0Oo#rrbP zZl$$(WmhHl7-`9GjZm^4yy3`1eidBNNG0pVuYsF9%91x9rDQ35%BVyhINFj|g6qSB zMkn$o;1-WoG8KOcZvGfc-gb)5 zG592}HPJzxd*g7sLvt^+o&QS%qcN{~T(=l=A>($8I;oYeY#Z68v7#`~<89%lOgc?dPAfFWF`5w_iN9VH-Ee~@NS%8>~0m@zkE)9!03Bf%!hc(Dfh=Foy!awu%KaF{`T+N zn)^DtS?#O-Xys*D=AdzhZJv+p_@n#j)TbBxSGS*i;9A4BHAaPU&q)sI_#x98RX=ku zq4-s{dBR1jUiMczJl{CXtukTT{$PWS(4%`<;ZuBCl7DCVDY2@ zaly|G>`tWbC;H3y{P70$&URiHdt=LqxC611&%~Vx^y=o=?^44<9WtCg{d!{Y?Pq~2 z@@{YRJhHUa9}CTDk6bs#9RRKQ~I4c*K-Tcb~JE!ilN;{ zxgBeswrh9Espw5v4U?M>GI~3yZOu$Gy2WLtyx+HQ^~>se;tCXlo)!Q6ZnZ3YdEz&p zd}Za&t8*5N+3y*$Iy8Ehf#E_!!{aj&u6~?TZy|xl_X&&ZuWI0VKECtEtctbkX0$t}t|Qic^0mPFxkt)c*P0`W#S1@L zO!4RECQ5I&;)@F%)ZtmrT4(g0UaQyk=ZEG!AD+CtOgKHh@duXjwz4k{&m?mvW zbFt<=@bs}=)eAlXJV`5G>NiLrAz--NnEZOg=A&bhY%=waB%jijm@F#DU6mM@7ZydAW zEpI#3K|P`TL!XO>;h6UG5|(V< zp^BNBwdIPc#__&!CDo!gUA79AEimwIhM{*d^|rEVR>n=BtXP+tY+3zYr1zdb zS_V!ydBNE+XrQPC)szVo&C`)*e<$lmrc|AA2;qY|JBPw{5!mRQJ(2_ z)IVp9$uM8P0}p>+-Z1e~?TC%nw~hKmEx)^WrmIb1QIt=U^--G+TALWXJX*0~GQV5( zLg&Xl3XB6{8()v z>f3kdGA|~w)b3=PpPAydtveP^yVf>e=o+#rB`Rg>%g@&)JJrbB`k+Mexzx+`)vXl2 z3ZC#RI{M{v-lNDt?GpWC)f1~rD;yUWFPin@viU1fB|H^t4ST*kt+VY@-5~xOHmBF?ss! z`JoTbC&((B41C$7)zPH(OV!y|qInNlYWCDYzZ~y2)4q|_W!p(t>z()OJnoOYA=gfE z%jpj4kVZ2ThXqQD18wTIca=X_H^7 z?Kvr#b+2xCq4|qDF1=;(k2CF^OQ!_wURV$-S^Bx#$1JOBV4-kDuDe#LPov(`~b2P*D*ZH*4AXWnhn0e{}=Nw*x;*GExb zTDlg*{^(Y`-@v;ChTd70+)ikDt&yTtfvKbO`3{NKJ5|nzxb@qv``%N_E;SrHq^Eyc zGtXoj84I2M*=oP}v(W42VFS)&6mVh3kM~{I92~+kXE?+T*n9I*pR%7l9YdyU{(f?) zhiTH7QDH`3yjAa~^~)c7WmQ4yGi zBsa-s=)2MVZn$k}{m8SG+rgHty{u=~y6QhwmaBU0{>dn#(~r*$^23_#{4;gplDZFO z-rQTxPtSDV%?p%lDW6h+XX;saiY`#9ml<|)d3UWBS?|Bhh?y1i*<*Kp%J5~56Rx}T z*%vb2^4iQ%af@1R8sLA|t#$Ls(^>^INejM|xU2o8%a&2UCJ5)R8^^C(j-Ml#U`%hd zh2@5J_ix^9ai_D?;aJAmmF@OPPFZxk@aW182k&BEb)8G@g>90(zGgT}I_+styS;bU zX7Vt;p!yX9*20ZEEvttKjhIT>DIXgIG;?;rl-CN5t6-2BoXV;oMNT^g|L z*AVkHej{tXXfpll8ijeAAy3+r6=!DE>gL;Q?_2n)g5bTkDvO=jIQ$7<;T}(ul(aAyxNvbImdPvwX?0#rZ+QyN$c?f%_$2 zzVqgS#8Fi%dc&jS;j=DubWEu|TKl7pv5*Iws|@Y_()pge{k$FvN)C;;IFMszt+wlU zShlKid-V9W_SX-;ZCdO6r(v~PZ5H>$$y!Q=yy$G|)O5|L)^|4zj9K0D(cQDbwKb8@ zhIqB1;nB10F5JJmN6{xi61~@KW7s%X7nxe|{$|jaq^Dd7tvy zJFUIO{CCy%+PYsoVWqKc^_?At)0YAKGp9(bF*Llylui0sZ1YF|S?*h!Cn>`w)am$o zUG__6Qn{{jl;YaCvUhwox})73mUJuBwkl1|PKl5n* zgERGt-iLh2sdwId+W1$=m%`=R#}92ztTQw`*LuqS54~@78Mt8Q$i~mC&#hHDAMh=` z)1YVGLFe^$DVgD zjAa}6xc z5x9NaXBNH*gPS``$@cSm;3hA!yB> zyaL?tRTy8flHK6riZQ;`7$3M>+-DKS2X5{nCA-7#ft$Pr<6Ep`_xP;E7~fiq58MMD zu>|7-w`z%!J>qY`&0mM{Emg8V__C!K-+GL%M9H4=_!5k7eO11_B$hqrY#GM40pnYy zWR-j?xTK93-*P2;#Z#6ive$e!KHqSg6^ZOEPsisweh{DUxol-3`@jd`^CLfj&riJW zszmlDAA!%$yaJzJc*E6+>?GiNJWXwVfr5@!22} z#-D*0F&??Dv&5M3g&-!3zXdU6JZ61oi5cU|LCo>D4uwiQuU3&r8Bf^ISz^KXdXOrN zOEz|vRAsy?h^4mL>;3j+wwuh&Ola{M<87f=SzM_L!(YT0^W+`ol0cU-d8x0K58t$i zNa&689OAMr_E+X9JbL5BYX zsBujoNhkZPli7jNTPW)6i%w<_O0U4Ev#&at184z2oqYqS4|;>wm<;1;{{tUXb_AvX z)ZiyTGADq(8Ip_yBy$Gn3mMgCI+=Mj(!lBJjAy@Y>r1al=*3YUFb)_GOaMjz?@*7T zLQ(hx&>%kxyxLp46zZ1xz>5_DuW|+Y4Zs9212{Kp8+2M6*dVPbsz# zCrh$`YydU_n}E&07Jlz_WAz@C_5!~G`+(no{lI*HCX`+a zWdM}Y^y(=Spm$%XfC`8NS^!Z%OQ03t4A28b9l!;kw}GKR7!VH7_cdA$7WCHC5(O*3 z8mJD~0<;`P03(4>>^#BJz2G9bX3Cs`#?)t7)-Sa4) z11f+lAR8D63;;RkBjm0svY)?tl}v^LLKwi!d+< zNCcvR7C>*Py8t0TLtr9glYk815|9K$0nMPJ{4Yeg3eXMc4x9qwfdpU>^t4mVLb(r+ zj52Kqv;o90Az8D+CqU7a6rl7*l@=~7R9cv{5NY8}HmDN>*>v!<&ZYuQz!!l|14tfD z6OJp%f!0xjAj$)2044JxfaaePoN|E{G_`5~P=3%3G=f*YcPgv;VJ1`OfTiG5 z&}ob`))b%@&=cqZBm=zxcYtD*3ecE|PXqb^Dxfcr4)g~y0h&yjRGNpn0Hx?~9mpN5 zL$$`&1z>0aiNHKy2#^a52D$=s0S-{GDT6u!6eF70KtKUdc2X=&0e^rd))(*rD9(+5 zd|(_v6Q2jD>6cCy6zTvLz*s;Ai~)=R+7&GUbAa^K0cXGoa0TiCWRNDBjE@IAfhIs9 zfK=B^98D%oAWbAqXiI>WSqN|b(M(P5%?9QGZUCGT^dX_J&~(x?8UagyMZi*^1Xu^G z1=awofmOgtU$r55ODXCU67T23!Iz z0>^+&z)@fW0Gpc4@E1_Bvj?F1yMWC=8L$(eHX8xbk(~Igz!n-V#jzA1Bk)Mr4p2m> zF;(0R><4}W_5lZh0{~^)A;1PW3>*PY0KWsrfpXvia2}w}&H$%?lfY@Zka4qGMiwngFkXmp~;D3%ml}1Mh&hIuK9O^#%9}`~YY^h$ql}(ikuTNKdjVDC=_q z_Y=y6FhPm}%`=El6(8OHeMQY)qpvrawslIkM{3!m@zyM8h^C$!!8L;ZD<_c|2#e0=5-5bnnL4^MF@=xG;aoN z|Mf=r#}Aq|K5~BYYnl@p_8C0bGdD-2x;4RM*}@^)vNfIg$h~>HZ}zqPX_T5XG%%q5 zLwijPKe-PKE{8p#4m$YVYFW^hMMguRA*%sA85hVRN1=N5Z5f$`@mh>kZv>I=@|9@zsKj5T41wlhV)G#>xkthAR2(l)D zo8ygGe$znQyasDhTUfdM$fX@uX0(AGqo7>LOwIC4P03BEowl)7!%Lo@Bn%2)xi1aX z+4rBLZH;JaGwGi*78*^)&Xcm5CRFnOyTrY}+G_G#Tq0%u61iNwC}qBC{h6!Cd%uSH zHr~`z!W0xeczRT>J#q3&m6T!o+6yrfhHRp73i@+Z`m-9w%ts!Cpy8hHr9FA2Kh5#C zMt?R-f8IlD9yDRW8@Z(0ia^EcHVe(Jip+&B;#Us_hUJ^5;$ z&GSs|C-cHo`R~y9A#r{E1^wBca?^(Ul-}dsYpiJ|T7L?twaspqC0nXFnXAze_2e(; z4-6f6J?y0-sxPnGf(Ybu=%qURnUe@f2^vOR*mGf&qAXarLT|vjNP0qWz|Pb_U#RguRMVK(Vs>$n{>a|jp$0+eRbHRF&fC|1K{d(@ zWW`oLvDA|JO7{DS4=q`&v;KJD$x4%?2)F$K8iN`eSNz1-YRth|e{fJ0(#Kt0?RyWeN^XRRL#t!7xJEoVlrxw z7b9z+*X(d{Gx58_#p5+tBa1_5>4;f@SKml4jTF6Yp|^_^V{DnP?e0jej`rMpq$GolS!ih*{Biv9qi#nZ%EVI|WjTWEvEhzeVY zC3f(1ZY%Mn9X!=j$j$8`&ut@yJ0K?d6Nb|4kYmr{7w(m?u}$T^0oWjlqQ!yssG&bw zxXx{9%!!9Pkn@d@L3HVC=xqh)PaTeW(eL!+>d)&@hF}jzP5t@96({G9Sla)5I(ngp z0v~U(QT0Fjq3cC0#iJ!XE?vDerB>=~r(d<35A7}gC;O}mtkJwg4I9<*lepvhT7(Q%We!#4$XgE2Rpn%*4Cs)Xlb+R2 zjB{ijc<>X%p^hw49PY@%Ej;Mg7hJ08I}bUsiOeVn4<*a$usY%kXC~d5nvqHqB@L4i65MqwZzv?Wbv%7_@fT9W=UFYrqzdg&fgJvC3J+OD^Gz>*{$mEL<`*`03=HnbtL zMeh;*+NS2>$c8MG1!x;MH)75#P+aBrBZ){_n|Aa)uLGwv078a$WI&SR!y0mvE~ueCKhe-nqpowZ5B3X z0j#O$QxCI&vW57gIrBBb%}Qhq5EYH6S179uL)jhmbvA@Dxe?tUHG!nm5M#rbxp*>+ zd26ThZ&{OYHq0mhX>`yF9UlvaS>K&6!kIfW!?PF#NIV$HYKT)K;e2pQnDUNfmSVdo zW+rwg*_lXIg=9^{!I8{K{56v0BE2+ob|(rod$nM0{~%aOO*=&)%l@wBX;9WQF%|c; zV2=MFMZ4Mtf*N8(OJ-*v(6p0^Riju9tPB60U0bs4Mmw8Dv&VLB!?JTS1`kZ>qiUw# ff`#0KAsupCMx~Za*RCo2cM$lw%|%R3X7m3C){UTA delta 11905 zcmeI2cUV-%*T?T%Tx8J&A&4NLfP&POr7cAlP&DY8C^ljT6$M0)Vr(&si5Pnu?#Nipr@Gf?U30BdLdtI(Oi7# z#=o>^#)j|<7Oj*O?t-8~*1KF;FNrPTiHhb1D{rIQK9JPR3P>um1|6}1ywJ+n++Iku zP_P!#334u^BjgxJXUJs8CXflH{9sc)hac+pnDnf?{Ol~@q`y&DL!#S;f>lV^qQJHQ zV}oL#aXjf+X{ovC`FWYy!-r+(jugsJt})7u%!5Zf!%~N&r9j^D69jwMXCR+C{550) z$n31t!2I-)sl&3=St%n^g~hNdVNb~$mo)_S#zVIg;)Q|{qcc-;VMxtN8Jw9qRCqVY z7>WGUvH5{%sbhy^XJ%9WAdMh2go90x)Q~ywk^X$6rP{DC#2EMNtRbl=EsV)c88vF0 zAk2iF+MN+<9OrdN3iNK#=q5dDSZ4b0wERgZNBwSrevx#Bq;jLfjrA)aX#!G5W@n^l zrVkzgo$~uZV!jOpjZlFa8lIUwm^v^z!suvZdRF?Vl)Sus&?*1#9m+J>U89Txu!W=* z@EDTHo8==5kF*_j4O#fiY?6L(5%7Bj zI+YtA3u!=NFA_9E-ywsR#2!fM5RWrD+6deSat+iW73O|PyRlI zdvg_i=L!CldG2h@5qqu`*FqoG*Mk~8u?<431jBDJrYz|NNjS;_h z1Prm7M8i=lI(zdwC^E#`7>@cJ?J74z zqX7xL%ulO&1`Ye9fC++N#Z&D3d9j_9>M0J#K5tpO`Upa=x2$Vm?fRDW39S0JtU6yo zNPNpW2iEuAvR;PuZNL6l;(zsfEjmGL@6Y|(=)@X-p3z3948TcEO9IpHs8wV@>&Qn& zL@W0q6))RqnpJ_uQVMzY^w5k8qSj8U{1h6FEzG4RLM!eL@3*G~?Q%s&~}fFGgqO+uG=z$L$Z|*MgK*(8)jJWmr@aG+I>h zViZrd=6w1(yMDN^B-Qtn2|*ix;%*6KHCGyu5?%%L(6Ujwv} z0rA@mA%XthmxTKPiT4fnDTHMeyTE$Ih z5j@Z%TH%H-g-~AFI$D{C6qT>fYv0i-OQ0n{!xY$S#rq*VBVMO;g9mcLs8cpaT&b#Y zmOh3SMbWZ4jnu$8<&_$(dB$_%waRp8reI@Ft#kM330mZS{+oW01ic!pk7RyJvM=O6sio&3jn{>qx;-O(eowUkiXq0Cuukhv2 zXi6;PQ=rzAhcf}o>jQlAVR<=5E2bmWQC?nGkfL+Kc<45VBO0i&b`msF<}p0ueVuY(j3Bg^%hz_$Dpx|o>=iWP8Xv9l95f7~prO1M?BEEi zt3bhNkG6+~sW2`=u`rh3>8caIjpcsbbYg=zo&nJ6Dk_j9qCU$J`(N zhj#=3J4BfQjhdCe6~y)J_?<+Zc()z*>#h^M+Vc#EKJEF&?m7iWU*mbHXSDc3d+yic zV=*+IZ|tEHN5u0x5bNW)Ur(KA*`Yk6XLpO$2a}kAj?X1P1j_(DBuQTZD8JYwS3=T5 z(h6)K1<(IM8t5mkupi*}hVVVG04D%FBuPIFs3T_pJ$0oe^oz3feN*$@Q@_E7LeB` zfS$UN?7zv@zsh>By#Q4Ir70g$ZojTU&Z<*DP{8sAkYh%*|0c;K;)A3GKB%066qBR@ zHGodDVq=naCh5S8?F$a33Uwtpax@imhNL1*P11!FJar{C(9C2fN%h@LI!Q`;nDqaY z4eJ;fU)Hy|yu4eQtR%^eHzb)_nWT@&?q|~dO)>zIo_~_G{6kIobtU-^H`yUY!K(a9 z&#U6Ux7xqA8ZD)|TaH%AzqgukEB@0Kqj-`1zq!@;p443KR;Vu@JFKJ`A6=;DX@x5O zeW9KW;LcN$xYHCBpEyO&2Jvs89f213nVzNaai1mev7f2<6=*}a@6;sjGgZZBP1Unh zegWEfXlFB>S`wc+O~vm+OXrc(lX%2*6<;=8&qnau&~8C{Z-$>R({o_rajlZx{vF?%IqbJt3%H$p`&eVLkbl{N#frAHx z{@U}CC1t{%9e(3tU8g>~eR$-d4;B`VDI4bV@|PB&6{qTdiHI`cwe4%j2^3<}Q*V~9 z=F%1Mlb&C7zOYHXj32a4_gMeL-LdoFkw*^2wDq%D(X@X*UCSEhBZjW}B8T1G6xFNr z(g$m%js7(*?Z~Of;#59ht`m1#qJM9q*(YSZd+tHsNr~kyZQ6`J{o`fNL)nIiPN|Rf zA3WK!tJTtyd%pI!6Tfcjo7t;`PpvnntH&29t_ACy`}S$`s7K@XwloQ{;i`E~T@v5C zeDiSN@y%~MpT=*ob{U>hxuXA)g9GCxx0*2au=R$QjurQwgmsCV&eN_4wvXf6o$dBp zZLrUiX}9iGWbAUk{C=G=8@TgQO#eJAhNXHoiGKra?0l8s>dgM{Wd7ltapZVE(Vb0SLbVY+HBnPWPvF8JuPZ$|KT5JgAP7Dx$RY0%o!V-_{glt3~b=j>T$``^hp zQ)TFMqxJdxK`wo2cD#O7YCrSg{2M_pJfFC}QQeRgoJaPxkhD zY*EmA>;s2xw>>(0b#}g=_p~UabDxQx4M(~x{d)Y>#Ft~Qbr>}wV2J<52VSA$4t7}m zZ1mQKvR`9|3(dbA$bY@OW>0?(z3HW1_J#hNRt?3twKL=GCtqj~@ZfgH61P1a4F?9e z=H0pQi)Fyr#&L5D{T3Un4|YtLws6PH)AM^DTk>#Voeoc_+u__a?jdTH+1ms8PwOuS6&)>{?f-%eeAxD8 ziCeD(&(ses=c}sDUuf4fX@zjLch3Bpm%r0*0s7@)MUJP|b(|V{%C_V2Q{!HBU(nv! z`b1c8gPh5$pHI`gH~pEFV*ItRNj7KLs`Q~33p@7$la!%(X94uAUqepWig6u-41awbBsu*{iL(^Ghe%_Q^R=bE-+Z+^n_z z54=`xN$lCD)7ZHK9`CDCr?lI?t$p{L@2@>Gg_s;quj{y?_VC^ZFIxuYr98|Vs!RrDvSK zfVO@SPPo;2wvfM&aHcI*@g2}4&eq^e`&`9S*XY?|UIwiKTH_Ku{xnZ1N#bcsRQwRM zW!!Ep&g`WsK6D$rjzIHTr)Mj9&blPFihqO8)!bu!5?jN^;j@IF#OGS>yCI3K z9X9D%DWA6q<65cWzd_r|<2GYlt5m#X zv!0dlT4>Lq^(xh~a=x+@<65oaiY;f-?RspT?9zDCnQ}$qdWf&i{E8OlYjPDDK?<+mK%B!Irf#y}IXV-a7CB|2d z@m1=@p9Jo?w>S6Mjsfn~i#G*+3hH^NVf*yrF9QE$UvEBj2Zjjsw!nj{dh>{#4f(zO zajH7Y^sc~bkaKG%##^ly?+bi>b#K0C7Y1CdXAfx+OUc%(N%@-nR`tst?T=;npRk^F zMqc2!l#!XjAI;169_nkfjmk~U&reUy9q+}D9UH88;En&T%c~D<68WS3-KZ9KKV_v@ zhnIY7UVW$uS;`YmO=hA?MESAPota99KOU^{o}K{N$XIifofS3zTlu3O);gP0QFfGi z>iGP=aq|u}y%Jit$;%z0meLxqP@G4v-xwb%Loc`(H2pU&KW3d?H}D^v{Lnirm7zDM z5ZNLKmrXW0+URwMo-2To^eQO7xkCPEveE0^cp$$?UNsr(L&gAV>>8lT^rI{qP-E8t z*_6Qi%2#8uAsq61B!uu2ppMX+zWImnFO&ui!7V_YA}PPPsmOp_azby@RL}-knrwGW zHd{z5lkKj_M&Fl8s(|Mnpw8O?Yg4%gCYwDZY}8mP)UG=2&RJ@k4`Mh9U2W`At5 zHHM_fP^aj%oys`^TO_ChznW}KAZgK32k3R4%F$F(gVceifNb<%$Tjc|#s3)+WNZrP zi9MDKy0ELsDmw?K-0{WVv^1lPJxq%sgY<~c%?ksu00gSH?TY)08qutjpVW&X~4ko*c%g1ulLr~=i}6&u#Vunb8G z70nlghr&U_N4(|HQ8+1l6fO!6g@bxdqov-`XsGwifjjU3o}dM23A_L{tiNGXJ`!5MH4 z`~c1anrE643CBe5SG0*Ap7@GUqBR)BF}JeUAJ0%O2fFbE`r6fhX%f{~yP z=nDpdo}d><1n+~cpe@jW_dsVVpa)tI0U|*-p#MKS0qtG-&!--s{rLuYF97Y)OW-oN z0xp6R;3O!PW;J516nRMIOO=gS6GI0iJA!vX0*D21fd2ex0%%jxW~R-1A3Oj*f~(*( zm=9>5eF8E-8b}4BK@La)oj`j)e<0DnPro949Td_ee}=>e@BxSikHJr1I`|O8fN0>0 zink!=fi@33a}ci0u;_Qzz&pvwO|w2 z05*cnU~&sF!S}F=;^C22YbAz7TLgHb%;6$v+g2KRKfU5%^MvZ5;zVy8ns3pj>Rf5 zEpxC8R%=i~`T=g(5UGJTM4=Sp&ECT;A!)WZ`jVgZUEC&IT!CD!U4u zMHZwEqdp4eYeD845A~Qv9U(Aoar*M}RHt_rWE}W2$9xN_*PPf-wsfv(@n;Tw9bwfKtnexb@Gndq z9K;5O8Po_9j&VQZb&*Md7k+#E=Gjpnnvfux5c7o+n;XyiZuz!e1ag9r6NascIt}4Y zQIpK44^07A}n)IveO`{IME<_zH{(^VycDpa%YUAQ#Ktt40 zs9?SUQ}t-f18w~MS*R4M)@YGqz9Vybi+cF4H+(M1?zGee^R=2|>a?$4Zca=_PLMhh zRsQp;RrkpYU*3=W^-H-<2-PuPs&cI8Uh28Y;)1uQ^h(2=T|5yDf7k^1 zo>Es-ZHNLPY7K4D@&3~65auM#@R!zyV81N(moA5}F5%`&aNpfmd=TfoFI=P=@**-{ zdwY5Bb=K2O)!!h8_B(d+*Z$JLQ20{&OV>!A^q1y`vS8PL^d*nkSTb1L79crG7y{##r0qJ%hVs~k1*C$ zd^bpP3TK~-gEZ3ia2D)hzC2goVUWXw+wHbuI6<_&O^4JZaZ-phSiB33O`=3;czq- zoGZULL&&vtKn|@d(eGC%7h5%OCAuK7v7QVsJhy5$?^-*s$!st`4B&XG^oD5+f(3wGES zCBI)3JbyVMZT|-gN<_9kN}3wQ+!Jmf#|Awf+ULOj<+jBNksXJnF)Zf0c)d>FYdJo< zQ6JeWMuP(&+IZM#tZVQ3b#$mFvfrbmM^S8*cp_R_5RHia+(xP)*}AP1)CTfITj}FA zh~QkEw5SatyF@1)CEYCN>WbRJJU&)h+7{-$vC{jH;XKaRkXN_Ex4ic}o+vULKk{R~ zR=2@>MdxpB>{$0_j@gG9Az9=-8L^Mj|ITNUaH0N0|Cy?w8@84q)Tfv5hxgNj-mdn%mGHUA{6NSF{cPHzzY)@}o(K zA2XrnGimwP@D_}|CSu-fV3)q!EhW+f=RE{e? h^1F}jk>4SHXmYYK)M?3*VK(!iU%B|TUp$*F`VX!&vHk!6 diff --git a/package.json b/package.json index efa7bb7..dfb41d9 100644 --- a/package.json +++ b/package.json @@ -11,14 +11,14 @@ "src/content/panorama/scripts/lib" ], "devDependencies": { - "@biomejs/biome": "^1.8.0", - "@prettier/plugin-xml": "^3.4.1", - "prettier": "^3.3.0", - "stylelint": "^16.6.1", + "@biomejs/biome": "^1.9.4", + "@prettier/plugin-xml": "^3.4.2", + "prettier": "^3.6.2", + "stylelint": "^16.23.1", "stylelint-config-recess-order": "^4.6.0", - "stylelint-config-standard": "^36.0.0", + "stylelint-config-standard": "^36.0.1", "stylelint-order": "^6.0.4", - "typescript": "^5.4.5" + "typescript": "^5.9.2" }, "dota2": { "customGame": { From c4aa6ba895a5e3a65dcd09b4d76f55fa6948bc4c Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 12:18:05 -0300 Subject: [PATCH 12/29] fix(vscripts): fix timers and event handling --- game/scripts/vscripts/invk/combo/combos.lua | 7 +- game/scripts/vscripts/invk/dota2/timers.lua | 30 ++++---- game/scripts/vscripts/invk/game_mode.lua | 76 ++++++--------------- 3 files changed, 40 insertions(+), 73 deletions(-) diff --git a/game/scripts/vscripts/invk/combo/combos.lua b/game/scripts/vscripts/invk/combo/combos.lua index cec2432..9937090 100644 --- a/game/scripts/vscripts/invk/combo/combos.lua +++ b/game/scripts/vscripts/invk/combo/combos.lua @@ -364,10 +364,13 @@ function M:on_pre_finish(player) combo_comms.send_pre_finish(player, combo) + local this = self + Timers:create({ delay = combo.wait.duration, - callback = self.on_finish, - args = { self, player }, + callback = function() + this:on_finish(player) + end, }) end diff --git a/game/scripts/vscripts/invk/dota2/timers.lua b/game/scripts/vscripts/invk/dota2/timers.lua index 87ea59f..c2f6c29 100644 --- a/game/scripts/vscripts/invk/dota2/timers.lua +++ b/game/scripts/vscripts/invk/dota2/timers.lua @@ -46,7 +46,7 @@ end --- @field delay number --- @field paused boolean --- @field at number ---- @field onError (fun(err: string): string) +--- @field on_error (fun(err: string): string) --- @field private callback_wrapper (fun(): any...) local Timer = class("Timer") @@ -58,7 +58,7 @@ local Timer = class("Timer") --- @field delay? number # Delay start time (in seconds). `nil`, `0` or negative number means it starts immediately --- @field realtime? boolean # If `true`, uses real clock (ignores pauses) (default: `false`) --- @field paused? boolean # If `true`, the timer starts paused and must be manually unpaused with [Unpause] (default: `false`) ---- @field onError? fun(err: string): string # Error handler function. If `nil`, uses [default_error_handler] (default: `nil`) +--- @field on_error? fun(err: string): string # Error handler function. If `nil`, uses [default_error_handler] (default: `nil`) --- @param options invk.dota2.TimerOptions function Timer:initialize(options) @@ -67,7 +67,7 @@ function Timer:initialize(options) self.args = options.args or {} self.realtime = val.non_nil(options.realtime, false) self.delay = options.delay or 0 - self.onError = options.onError or M.default_error_handler + self.on_error = options.on_error or M.default_error_handler self.paused = val.non_nil(options.paused, false) self.at = (options.at or self:now()) + self.delay @@ -103,17 +103,17 @@ function M:process_timer(timer) return end - local removeTimer = true - local success, result = xpcall(timer.callbackWrapper, timer.onError) + local remove_timer = true + local success, result = xpcall(timer.callback_wrapper, timer.on_error) if not success then handle_error(timer, result) elseif type(result) == "number" then timer.at = timer.at + result - removeTimer = false + remove_timer = false end - if removeTimer then + if remove_timer then self.timers[timer.id] = nil end end @@ -135,10 +135,10 @@ end --- ```lua --- -- Immediately calls `obj.fn(obj, 13)` (equivalent to `obj:fn(13)`), --- -- if `fn` returns a number, repeats at that interval ---- Create({callback = obj.fn, args = {obj, 13}}) +--- create({callback = obj.fn, args = {obj, 13}}) --- --- -- 10 seconds delayed, run once using game time (respect pauses) ---- Create({ +--- create({ --- delay = 10.0, --- callback = function() --- print("Hello. I'm running 10 seconds after when I was started.") @@ -146,7 +146,7 @@ end --- }) --- --- -- 10 second delayed, run once regardless of pauses ---- Create({ +--- create({ --- delay = 10.0, --- realtime = true, --- callback = function() @@ -155,7 +155,7 @@ end --- }) --- --- -- At a specific time, run once using game time (respect pauses) ---- Create({ +--- create({ --- at = GameRules:GetGameTime() + 10.0, --- callback = function() --- print("Hello. I'm running when I was scheduled to run.") @@ -163,7 +163,7 @@ end --- }) --- --- -- At a specific time, run once using real time (regardless of pauses) ---- Create({ +--- create({ --- at = Time() + 10.0, --- realtime = true, --- callback = function() @@ -172,7 +172,7 @@ end --- }) --- --- -- At a specific time, 10 second delay from that time, run once using game time (respect pauses) ---- Create({ +--- create({ --- at = GameRules:GetGameTime() + 30.0, --- delay = 10.0, --- callback = function() @@ -182,7 +182,7 @@ end --- --- -- A timer running every second that starts 5 seconds in the future. --- -- Uses game time, respecting pauses. ---- Create({ +--- create({ --- delay = 5.0, --- callback = function() --- print("Hello. I'm running 5 seconds after you called me and then every second thereafter.") @@ -191,7 +191,7 @@ end --- }) --- --- -- A timer running every second that starts after 2 minutes regardless of pauses ---- Create({ +--- create({ --- id = "uniqueTimerId", --- delay = 120.0, --- realtime = true, diff --git a/game/scripts/vscripts/invk/game_mode.lua b/game/scripts/vscripts/invk/game_mode.lua index e558b2a..a63582f 100644 --- a/game/scripts/vscripts/invk/game_mode.lua +++ b/game/scripts/vscripts/invk/game_mode.lua @@ -5,7 +5,6 @@ local Ability = require("invk.dota2.ability") local COMMANDS = require("invk.const.commands") local CUSTOM_EVENTS = require("invk.const.custom_events") local Combos = require("invk.combo.combos") -local CustomEvents = require("invk.dota2.custom_events") local DamageInstance = require("invk.dota2.damage_instance") local Env = require("invk.game_mode.env") local INVOKER = require("invk.const.invoker") @@ -19,6 +18,7 @@ local PRECACHE = require("invk.const.precache") local S = require("invk.const.settings") local Timers = require("invk.dota2.timers") local Unit = require("invk.dota2.unit") +local custom_ev = require("invk.dota2.custom_events") local func = require("invk.lang.function") local rand = require("invk.lang.random") local tbl = require("invk.lang.table") @@ -336,7 +336,7 @@ end --- @param method_name string --- @return CustomGameEventListenerID function M:subscribe_to_custom_event(event, method_name) - return CustomEvents.subscribe(event, self:method_handler(method_name)) + return custom_ev.subscribe(event, self:method_handler(method_name)) end function M:register_game_events() @@ -386,7 +386,7 @@ local WARNF_MISSING_TEAM_COLOR = "Attempted to set custom player color for player %d and team %d, but the team color is not configured." --- Called when the overall game state has changed. ---- @param payload table +--- @param payload dota2.events.game_rules_state_change function M:_OnGameRulesStateChange(payload) if self._reentrant then return @@ -421,12 +421,8 @@ function M:_OnGameRulesStateChange(payload) end end ---- @class invk.game_mode.events.PlayerConnectFull ---- @field PlayerID integer # Player id ---- @field userid integer # User id - --- Called once when the player fully connects and becomes "Ready" during loading. ---- @param payload invk.game_mode.events.PlayerConnectFull +--- @param payload dota2.events.player_connect_full function M:_OnConnectFull(payload) self:d("_OnConnectFull", { payload = payload }) @@ -450,11 +446,8 @@ function M:_OnConnectFull(payload) end end ---- @class invk.game_mode.events.NpcSpawned ---- @field entindex integer # Unit entity index - --- Called when an NPC has spawned somewhere in game, including heroes. ---- @param payload invk.game_mode.events.NpcSpawned +--- @param payload dota2.events.npc_spawned function M:_OnNPCSpawned(payload) self:d("_OnNPCSpawned", { payload = payload }) @@ -470,13 +463,8 @@ function M:_OnNPCSpawned(payload) end end ---- @class invk.game_events.OnEntityKilled ---- @field entindex_killed integer # Victim (unit) entity index ---- @field entindex_attacker? integer # Attacker (unit) entity index ---- @field entindex_inflictor? integer # Inflictor (item, ability, etc) entity index - --- Called when an entity was killed. ---- @param payload invk.game_events.OnEntityKilled +--- @param payload dota2.events.entity_killed function M:_OnEntityKilled(payload) self:d("_OnEntityKilled", { payload = payload }) @@ -563,7 +551,7 @@ function M:OnHeroInGame(hero) variant = hero:GetHeroFacetID(), } - CustomEvents.send_player(CUSTOM_EVENTS.EVENT_PLAYER_HERO_IN_GAME, player, payload) + custom_ev.send_player(CUSTOM_EVENTS.EVENT_PLAYER_HERO_IN_GAME, player, payload) end --- Called once and only once when the game completely begins (about 0:00 on the clock). @@ -571,15 +559,8 @@ function M:OnGameInProgress() self:d("OnGameInProgress") end ---- @class invk.game_events.OnEntityHurt ---- @field damage number # Damage amount ---- @field damagebits integer # Damage flags ---- @field entindex_killed integer # Victim (unit) entity index ---- @field entindex_attacker integer # Attacker (unit) entity index ---- @field entindex_inflictor integer # Inflictor (item, ability, etc) entity index - --- An entity has been hurt. ---- @param payload invk.game_events.OnEntityHurt +--- @param payload dota2.events.entity_hurt function M:OnEntityHurt(payload) self:d("OnEntityHurt", { payload = payload }) @@ -603,13 +584,8 @@ function M:OnEntityHurt(payload) self.combos:on_entity_hurt(damage) end ---- @class invk.game_events.OnItemPurchased ---- @field PlayerID integer # Player id ---- @field itemname string # Item name ---- @field itemcost integer # Item cost - --- An item was purchased by a player. ---- @param payload invk.game_events.OnItemPurchased +--- @param payload dota2.events.dota_item_purchased function M:OnItemPurchased(payload) self:d("OnItemPurchased", { payload = payload }) @@ -625,23 +601,14 @@ function M:OnItemPurchased(payload) }) end ---- @class invk.game_events.OnAbilityCastBegins ---- @field PlayerID integer # Player id ---- @field abilityname string # Ability name - --- Called whenever an ability begins its PhaseStart phase (but before it is actually cast). ---- @param payload invk.game_events.OnAbilityCastBegins +--- @param payload dota2.events.dota_player_begin_cast function M:OnAbilityCastBegins(payload) self:d("OnAbilityCastBegins", { payload = payload }) end ---- @class invk.game_events.OnAbilityUsed ---- @field PlayerID integer # Player id ---- @field caster_entindex integer # Caster (unit) entity index ---- @field abilityname string # Ability name - --- An ability was used by a player (including items). ---- @param payload invk.game_events.OnAbilityUsed +--- @param payload dota2.events.dota_player_used_ability function M:OnAbilityUsed(payload) self:d("OnAbilityUsed", { payload = payload }) @@ -651,30 +618,26 @@ function M:OnAbilityUsed(payload) inspect(payload) ) - local caster = Unit(EntIndexToHScript(payload.caster_entindex)) - local abilityEnt = caster:FindAbilityOrItem(payload.abilityname) + local caster = Unit:new(EntIndexToHScript(payload.caster_entindex)) + local ability_ent = caster:find_ability_or_item(payload.abilityname) - if abilityEnt == nil then + if ability_ent == nil then errorf(ERRF_ABILITY_OR_ITEM_NOT_FOUND, payload.abilityname, caster.name) end - local ability = Ability(abilityEnt) + local ability = Ability:new(ability_ent) self.combos:on_ability_used(player, caster, ability) end --- A non-player entity (necro-book, chen creep, etc) used an ability. --- @tparam table payload --- @tparam int payload.caster_entindex Caster (unit) entity index --- @tparam string payload.abilityname Ability name +--- @param payload dota2.events.dota_non_player_used_ability function M:OnNonPlayerUsedAbility(payload) self:d("OnNonPlayerUsedAbility", { payload = payload }) end --- A channelled ability finished by either completing or being interrupted. --- @tparam table payload --- @tparam string payload.abilityname Ability name --- @tparam int payload.interrupted `1` if ability was interrupted +--- @param payload dota2.events.dota_ability_channel_finished function M:OnAbilityChannelFinished(payload) self:d("OnAbilityChannelFinished", { payload = payload }) end @@ -737,7 +700,8 @@ end function M:OnComboRestart(player, payload) self:d("OnComboRestart", { player = player:GetPlayerID(), payload = payload }) - local options = { hardReset = payload.hardReset == 1 } + --- @type invk.combo.hero.TeardownOptions + local options = { hard_reset = payload.hardReset == 1 } self.combos:on_restart(player, options) end @@ -782,7 +746,7 @@ function M:OnItemPickerQuery(player, payload) local response = { items = self.items_kv:search(payload.query) } - CustomEvents.send_player(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_RESPONSE, player, response) + custom_ev.send_player(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_RESPONSE, player, response) end -- }}} From 680347f6142d6682403f988ec3876a4c70618362 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 12:20:28 -0300 Subject: [PATCH 13/29] chore(panorama): update dependencies --- bun.lockb | Bin 102200 -> 102200 bytes .../panorama/scripts/custom_game/package.json | 6 +++--- src/content/panorama/scripts/lib/package.json | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bun.lockb b/bun.lockb index 5b42def789c9fa05c0d254af40d972dc469f7b30..bc67630f0e45e0a8140c37102dc814542f057e93 100755 GIT binary patch delta 473 zcmdlnk8Q_1wh4L)p1H&x ztf)^GX}HTGt#_uB(Wz~+?!f{FiPP6PK3H1b@NJ6z|5`lj>T?a4&t&>L2}VhCBL;?oqSTU-%+#VgaRxz~w0HJ$Fvc0{ndt##jxjJWa56A7u)hub ze&=~QKTyUHC}FH;INeT?(TLG-dZ8qv0njj`=^JDirMB;rWL%-bYyp&JG-Q-uw3ses z$S5;?o*knnlZol{`9_Sg)43cNML`<2%h@yX`2m&a_A*9*WCPO}6{k0JGO|x!-^-W; MGGx0*AEOE*00eNjzyJUM delta 458 zcmV;*0X6=(o(8y{29Pcwv@huV;Z%u}$I!X${~X|^lvEwy#<1K>lF|tvAS(! zy>i76166tc$B+iGuwToQEx~X=4!ZD^BlwEZ4HbcHt!l-yY=LOu(coaPI~q?J*o8bt z_r}XakjbNZZ17{DYw(G7FOT7T)Ac0m)<)dpxZAIxv)#d0Rsma=4Hy9zmrNJ|p9459 zFqiHa0U0+j003}uWps3DWpdnJFjBHBxs3<`UNbH;E-(N9#sB~S2><|q2klY!+~;Qx z2mxL(HZC?UF#wl7838f@Fqd%|0WbqJE;X01903})z8L|iB$sMG0c@AjJ^>X1GdGu? zG65Zz3P1rGw;(?O3{C+ymo1F}SOPOQmr-T`A(w!O0SA|_jR9f Date: Mon, 1 Sep 2025 12:21:41 -0300 Subject: [PATCH 14/29] fix(panorama): fix casing for networked data --- src/content/panorama/scripts/lib/combo.ts | 29 +++++++++------ .../scripts/lib/combo/combos_collection.ts | 36 +++++++++++++------ 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/content/panorama/scripts/lib/combo.ts b/src/content/panorama/scripts/lib/combo.ts index 495f25a..133fa1b 100644 --- a/src/content/panorama/scripts/lib/combo.ts +++ b/src/content/panorama/scripts/lib/combo.ts @@ -68,14 +68,6 @@ export type PropertyDescriptors = { [K in keyof Properties]: PropertyDescriptor; }; -export interface Base { - id: ComboId; - heroLevel: number; - talents: TalentSelection; - tags: string[]; - items: string[]; -} - export interface Properties { [Property.Specialty]: Specialty; [Property.Stance]: Stance; @@ -87,15 +79,30 @@ export type PropertiesL10n = { [K in keyof Properties]: string; }; -export interface NetworkCombo extends Base, Properties { +export interface NetworkCombo { + id: ComboId; + specialty: Specialty; + stance: Stance; + damage_rating: DamageRating; + difficulty_rating: DifficultyRating; + hero_level: number; orbs: [number, number, number]; + talents: TalentSelection; + items: string[]; + tags: string[]; sequence: NetworkStep[]; } -export interface Combo extends NetworkCombo { +export interface Combo extends Properties { + id: ComboId; + heroLevel: number; + orbs: [number, number, number]; orbsByName: Record; - sequence: Step[]; + talents: TalentSelection; + items: string[]; + tags: string[]; tagset: Set; + sequence: Step[]; l10n: ComboL10n; } diff --git a/src/content/panorama/scripts/lib/combo/combos_collection.ts b/src/content/panorama/scripts/lib/combo/combos_collection.ts index 9a24865..76e2353 100644 --- a/src/content/panorama/scripts/lib/combo/combos_collection.ts +++ b/src/content/panorama/scripts/lib/combo/combos_collection.ts @@ -1,4 +1,4 @@ -import type { Combo, ComboId, Step } from "../combo"; +import type { Combo, ComboId, Properties, Step } from "../combo"; import { OrbName } from "../combo"; import { CustomGameEvent, sendServer } from "../custom_events"; import type { NetworkValue as GenericNetworkValue } from "../custom_net_tables"; @@ -30,10 +30,18 @@ export class CombosCollection extends NetTableKeyListener< const value: Value = new Map(); for (const rcombo of Object.values(rvalue)) { + const orbs = lua.fromArray(rcombo.orbs) as [number, number, number]; + const orbsByName = { + [OrbName.Quas]: orbs[0], + [OrbName.Wex]: orbs[1], + [OrbName.Exort]: orbs[2], + }; + const tags = lua.fromArray(rcombo.tags); const tagset = new Set(tags); + const items = lua.fromArray(rcombo.items); - const orbs = lua.fromArray(rcombo.orbs) as [number, number, number]; + const rsequence = lua.fromArray(rcombo.sequence); const sequence: Step[] = []; @@ -49,20 +57,26 @@ export class CombosCollection extends NetTableKeyListener< }); } + const props: Properties = { + specialty: rcombo.specialty, + stance: rcombo.stance, + damageRating: rcombo.damage_rating, + difficultyRating: rcombo.difficulty_rating, + }; + const combo: Combo = { - ...rcombo, + id: rcombo.id, + ...props, + heroLevel: rcombo.hero_level, + orbs, + orbsByName, + talents: rcombo.talents, + items, tags, tagset, - items, sequence, - orbs, - orbsByName: { - [OrbName.Quas]: orbs[0], - [OrbName.Wex]: orbs[1], - [OrbName.Exort]: orbs[2], - }, l10n: { - ...l10n.comboProps(rcombo), + ...l10n.comboProps(props), name: l10n.comboAttrName(rcombo.id, "name"), description: l10n.comboAttrName(rcombo.id, "description"), }, From cd3e04204e1033a19c2e64da4db4d83e037417bb Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 12:41:52 -0300 Subject: [PATCH 15/29] chore: update selene config --- .selene/rockspec.yml | 28 ---------------------------- selene.toml | 10 +++++----- 2 files changed, 5 insertions(+), 33 deletions(-) delete mode 100644 .selene/rockspec.yml diff --git a/.selene/rockspec.yml b/.selene/rockspec.yml deleted file mode 100644 index 42ec852..0000000 --- a/.selene/rockspec.yml +++ /dev/null @@ -1,28 +0,0 @@ -# https://github.com/luarocks/luarocks/wiki/Rockspec-format ---- -name: rockspec -globals: - rockspec_format: - property: full-write - package: - property: full-write - version: - property: full-write - description: - property: full-write - supported_platforms: - property: full-write - dependencies: - property: full-write - build_dependencies: - property: full-write - external_dependencies: - property: full-write - test_dependencies: - property: full-write - source: - property: full-write - build: - property: full-write - test: - property: full-write diff --git a/selene.toml b/selene.toml index 352023f..1ed49e2 100644 --- a/selene.toml +++ b/selene.toml @@ -1,10 +1,10 @@ -std = ".selene/rockspec+.selene/busted+.selene/dota2+.selene/dota2-custom-game" +std = ".selene/busted+.selene/dota2+.selene/dota2-custom-game" exclude = [ - ".luarocks/**", + ".lux/**", ".luacats/**", - "lua_modules/**", + "game/scripts/vscripts/compat53/**", "game/scripts/vscripts/fsm.lua", - "game/scripts/vscripts/moses.lua", - "game/scripts/vscripts/pl/**", + "game/scripts/vscripts/inspect.lua", + "game/scripts/vscripts/middleclass.lua", "tmp/**", ] From 77d8455631fefe6bdd6ccef8d6dc09b1b8bdb17d Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 12:42:07 -0300 Subject: [PATCH 16/29] chore(panorama): fix lint warnings --- src/content/panorama/scripts/lib/combo.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/content/panorama/scripts/lib/combo.ts b/src/content/panorama/scripts/lib/combo.ts index 133fa1b..7de9b62 100644 --- a/src/content/panorama/scripts/lib/combo.ts +++ b/src/content/panorama/scripts/lib/combo.ts @@ -83,8 +83,11 @@ export interface NetworkCombo { id: ComboId; specialty: Specialty; stance: Stance; + // biome-ignore lint/style/useNamingConvention: network data damage_rating: DamageRating; + // biome-ignore lint/style/useNamingConvention: network data difficulty_rating: DifficultyRating; + // biome-ignore lint/style/useNamingConvention: network data hero_level: number; orbs: [number, number, number]; talents: TalentSelection; From 180b63c26f5139adececc6f595b4b7b2c1195cb8 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 12:53:19 -0300 Subject: [PATCH 17/29] docs: update DEVELOPMENT --- DEVELOPMENT.md | 56 ++++++-------------------------------------------- 1 file changed, 6 insertions(+), 50 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 31d16cd..783cda5 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -5,9 +5,9 @@ specification for commit messages. ## Requirements -- [lua](https://lua.org) 5.1 (same version as Dota 2) -- [luarocks](https://luarocks.org) -- [node](https://nodejs.org) LTS + npm +- [luajit](https://luajit.org) 2.1 (same version as Dota 2) +- [lux](https://nvim-neorocks.github.io) +- [bun](https://bun.com) - [task](https://taskfile.dev) - [git-cliff](https://git-cliff.org) (releases only) @@ -22,53 +22,9 @@ DOTA2_PATH="/path/to/dota2" - Install node packages: ```shell -npm install +bun install ``` -- Initialize luarocks: - -```shell -luarocks init --local -``` - -- Add `/lua_modules/bin` to the `PATH`. - ---- - -### A note about rocks tree isolation - -Custom rocks trees defined with `rocks_trees` in a LuaRocks user config -(usually at `$HOME/.config/luarocks/config.lua` or `$HOME/.luarocks/config.lua`) -will get added to the project's `rocks_trees` config too -(this is a LuaRocks specific behavior). - -To truly isolate the project tree from everything else, I recommend appending -the following to `/.luarocks/config-5.1.lua` -(after running `luarocks init`): - -```lua -rocks_trees = {} -``` - -Then verify LuaRocks is using only the projects rocks tree by running: - -```shell -luarocks config rocks_trees -``` - -It should print something like this: - -```lua -{ - { - name = "project", - root = "/lua_modules" - } -} -``` - ---- - ## Testing Run tests: @@ -99,8 +55,8 @@ task build - Update version strings - - `game/scripts/vscripts/invokation/const/metadata.lua` - - `src/content/panorama/scripts/lib/constants.ts` + - `game/scripts/vscripts/invk/const/metadata.lua` + - `src/content/panorama/scripts/lib/meta.ts` - Commit changes with `chore(release)` label From f5633f06470b1f1a05881975a614c02d49fa4536 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 13:05:10 -0300 Subject: [PATCH 18/29] feat(vscripts): improve hero reset --- game/scripts/vscripts/invk/dota2/player.lua | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/game/scripts/vscripts/invk/dota2/player.lua b/game/scripts/vscripts/invk/dota2/player.lua index a746ce7..8bdbc65 100644 --- a/game/scripts/vscripts/invk/dota2/player.lua +++ b/game/scripts/vscripts/invk/dota2/player.lua @@ -1,7 +1,5 @@ local class = require("middleclass") -local val = require("invk.lang.value") - --- Player class. --- @class invk.dota2.Player : middleclass.Class --- @field entity CDOTAPlayerController # player entity @@ -24,8 +22,6 @@ end --- @class invk.dota2.player.ReplaceHeroOptions --- @field gold? integer # New hero starting gold (default: `0`) --- @field xp? integer # New hero starting experience (default: `0`) ---- @field remove? boolean # Remove old hero entity. Not removing the entity will make it linger ---- under the player's ownership and control (default: `true`) --- Replaces the player's hero with a new one. --- @@ -36,16 +32,17 @@ end --- @return CDOTA_BaseNPC_Hero # New hero entity function M:replace_hero(hero_name, options) local opts = options or {} - local old_hero = self.hero - local gold = opts.gold or 0 + local gold = opts.gold or -1 local xp = opts.xp or 0 - local remove = val.non_nil(opts.remove, true) - self.hero = PlayerResource:ReplaceHeroWith(self.id, hero_name, gold, xp) + GameRules:SetSpeechUseSpawnInsteadOfRespawnConcept(true) - if remove then - old_hero:RemoveSelf() - end + local hero = PlayerResource:ReplaceHeroWithNoTransfer(self.id, hero_name, gold, xp) --[[@as CDOTA_BaseNPC_Hero]] + + GameRules:SetSpeechUseSpawnInsteadOfRespawnConcept(false) + + self.hero:RemoveSelf() + self.hero = hero return self.hero end From bca49f2a97d8304e8fc97abad1b008fbfdea9eaf Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 19:34:18 -0300 Subject: [PATCH 19/29] test(vscripts): fix tests --- spec/combo/hero_spec.lua | 8 ++++---- spec/support/dota2/GameRules.lua | 2 ++ spec/support/dota2/PlayerResource.lua | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/combo/hero_spec.lua b/spec/combo/hero_spec.lua index 9c67314..154d41f 100644 --- a/spec/combo/hero_spec.lua +++ b/spec/combo/hero_spec.lua @@ -260,11 +260,11 @@ describe("invk.combo.hero", function() describe("with hard reset", function() before_each(function() - mocks:stub("PlayerResource", PlayerResource, "ReplaceHeroWith") + mocks:stub("PlayerResource", PlayerResource, "ReplaceHeroWithNoTransfer") end) after_each(function() - mocks:reset("PlayerResource", "ReplaceHeroWith") + mocks:reset("PlayerResource", "ReplaceHeroWithNoTransfer") end) it("removes all hero's items", function() @@ -320,8 +320,8 @@ describe("invk.combo.hero", function() combo_hero.teardown(player, { hard_reset = true }) mocks - :assert("PlayerResource", "ReplaceHeroWith").self - .called_with(31, INVOKER.UNIT_NAME, 0, 0) + :assert("PlayerResource", "ReplaceHeroWithNoTransfer").self + .called_with(31, INVOKER.UNIT_NAME, -1, 0) mocks:assert("hero", "RemoveSelf").self.called() assert.is_true(hero:IsNull()) end) diff --git a/spec/support/dota2/GameRules.lua b/spec/support/dota2/GameRules.lua index f0f9387..dd70ffe 100644 --- a/spec/support/dota2/GameRules.lua +++ b/spec/support/dota2/GameRules.lua @@ -21,3 +21,5 @@ end function GameRules:GetDroppedItem(_i) return nil end + +function GameRules:SetSpeechUseSpawnInsteadOfRespawnConcept(_b) end diff --git a/spec/support/dota2/PlayerResource.lua b/spec/support/dota2/PlayerResource.lua index 324fbcd..52737bc 100644 --- a/spec/support/dota2/PlayerResource.lua +++ b/spec/support/dota2/PlayerResource.lua @@ -9,3 +9,4 @@ function PlayerResource:GetSteamID(player_id) end function PlayerResource:ReplaceHeroWith(_player_id, _hero_name, _gold, _xp) end +function PlayerResource:ReplaceHeroWithNoTransfer(_player_id, _hero_name, _gold, _xp) end From bc79cb5a45780a862d078d05bbb01af4870dfb00 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 19:34:42 -0300 Subject: [PATCH 20/29] chore(lua): update `middleclass` types --- .luacats/middleclass.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.luacats/middleclass.lua b/.luacats/middleclass.lua index b88fe77..892552a 100644 --- a/.luacats/middleclass.lua +++ b/.luacats/middleclass.lua @@ -6,22 +6,28 @@ local M = {} --- @class middleclass.Class +--- @field name string --- @field static table +--- @field class middleclass.Class local Class = {} +--- @param class middleclass.Class --- @param ... any --- @return self -function Class:new(...) end +function Class.new(class, ...) end +--- @param class middleclass.Class --- @param mixin table -function Class:include(mixin) end +function Class.include(class, mixin) end --- @param class middleclass.Class +--- @param super middleclass.Class --- @return boolean -function Class:isInstanceOf(class) end +function Class.isSubclassOf(class, super) end ---- @param super middleclass.Class +--- @param self self +--- @param class middleclass.Class --- @return boolean -function Class:isSubclassOf(super) end +function Class.isInstanceOf(self, class) end return M From 789763bf33239dd21dbfba9864f0734ecd4f1553 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 19:36:34 -0300 Subject: [PATCH 21/29] chore(vscripts): refactor game events --- game/scripts/vscripts/invk/game_mode.lua | 308 ++---------------- .../vscripts/invk/game_mode/game_events.lua | 273 ++++++++++++++++ 2 files changed, 293 insertions(+), 288 deletions(-) create mode 100644 game/scripts/vscripts/invk/game_mode/game_events.lua diff --git a/game/scripts/vscripts/invk/game_mode.lua b/game/scripts/vscripts/invk/game_mode.lua index a63582f..476c59f 100644 --- a/game/scripts/vscripts/invk/game_mode.lua +++ b/game/scripts/vscripts/invk/game_mode.lua @@ -1,12 +1,10 @@ local class = require("middleclass") -local inspect = require("inspect") -local Ability = require("invk.dota2.ability") local COMMANDS = require("invk.const.commands") local CUSTOM_EVENTS = require("invk.const.custom_events") local Combos = require("invk.combo.combos") -local DamageInstance = require("invk.dota2.damage_instance") local Env = require("invk.game_mode.env") +local GameEvents = require("invk.game_mode.game_events") local INVOKER = require("invk.const.invoker") local Invoker = require("invk.dota2.invoker") local ItemsKeyValues = require("invk.dota2.kv.items_key_values") @@ -17,7 +15,6 @@ local NetTable = require("invk.dota2.net_table") local PRECACHE = require("invk.const.precache") local S = require("invk.const.settings") local Timers = require("invk.dota2.timers") -local Unit = require("invk.dota2.unit") local custom_ev = require("invk.dota2.custom_events") local func = require("invk.lang.function") local rand = require("invk.lang.random") @@ -33,12 +30,11 @@ local DEFAULT_ENV = Env.is_dev_mode() and Env.DEVELOPMENT or Env.PRODUCTION --- @field players { [PlayerID]: CDOTAPlayerController? } --- @field items_kv invk.dota2.kv.ItemsKeyValues --- @field net_tables { [invk.net_table.Name]: invk.dota2.NetTable } +--- @field game_events invk.game_mode.GameEvents --- @field combos invk.combo.Combos --- @field logger invk.Logger --- @field private game_mode CDOTABaseGameMode --- @field private _reentrant boolean ---- @field private _first_player_loaded boolean ---- @field private _first_spawned boolean local M = class("invk.GameMode") M:include(Logger.Mixin) @@ -72,8 +68,6 @@ function M:initialize(options) local opts = options or {} self._reentrant = false - self._first_player_loaded = false - self._first_spawned = false self.env = opts.env or DEFAULT_ENV self.users = {} @@ -88,6 +82,8 @@ function M:initialize(options) return NetTable:new(config, { logger = self.logger }) end) + self.game_events = GameEvents:new(self, { logger = self.logger }) + self.combos = Combos:new(self.net_tables[NET_TABLES.Name.MAIN], { logger = self.logger }) end @@ -119,8 +115,10 @@ function M:activate() self:setup_net_tables() self:setup_game_rules() self:setup_game_mode() - self:register_game_events() + + self.game_events:register() self:register_custom_events() + self:register_commands() self:register_convars() @@ -325,13 +323,6 @@ end --- }}} --- events {{{ ---- @param event string ---- @param method_name string ---- @return EventListenerID -function M:listen_to_game_event(event, method_name) - return ListenToGameEvent(event, self:fn_handler(method_name), self) -end - --- @param event string --- @param method_name string --- @return CustomGameEventListenerID @@ -339,27 +330,11 @@ function M:subscribe_to_custom_event(event, method_name) return custom_ev.subscribe(event, self:method_handler(method_name)) end -function M:register_game_events() - self:d(" (game_events) register listeners") - - self:listen_to_game_event("dota_ability_channel_finished", "OnAbilityChannelFinished") - self:listen_to_game_event("dota_item_purchased", "OnItemPurchased") - self:listen_to_game_event("dota_non_player_used_ability", "OnNonPlayerUsedAbility") - self:listen_to_game_event("dota_player_begin_cast", "OnAbilityCastBegins") - self:listen_to_game_event("dota_player_used_ability", "OnAbilityUsed") - self:listen_to_game_event("entity_hurt", "OnEntityHurt") - self:listen_to_game_event("entity_killed", "_OnEntityKilled") - self:listen_to_game_event("game_rules_state_change", "_OnGameRulesStateChange") - self:listen_to_game_event("npc_spawned", "_OnNPCSpawned") - self:listen_to_game_event("player_connect_full", "_OnConnectFull") -end - function M:register_custom_events() self:d(" (custom_events) register listeners") self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_PLAYER_QUIT_REQUEST, "OnPlayerQuitRequest") self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_START, "OnComboStart") self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_STOP, "OnComboStop") self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_RESTART, "OnComboRestart") @@ -380,280 +355,37 @@ function M:register_custom_events() self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_REQUEST, "OnItemPickerQuery") end --- events.internal {{{ +-- events.game {{{ local WARNF_MISSING_TEAM_COLOR = "Attempted to set custom player color for player %d and team %d, but the team color is not configured." ---- Called when the overall game state has changed. ---- @param payload dota2.events.game_rules_state_change -function M:_OnGameRulesStateChange(payload) - if self._reentrant then +function M:set_team_colors() + if not S.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS then return end - local state = GameRules:State_Get() + for i = 0, DOTA_DEFAULT_MAX_TEAM_PLAYERS do + if PlayerResource:IsValidPlayer(i) then + local team = PlayerResource:GetTeam(i) + local color = S.TEAM_COLORS[team] - self._reentrant = true - self:OnGameRulesStateChange(state, payload) - self._reentrant = false - - if state == DOTA_GAMERULES_STATE_HERO_SELECTION then - self:post_load_precache() - self:OnAllPlayersLoaded() - - if S.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS then - for i = 0, DOTA_DEFAULT_MAX_TEAM_PLAYERS do - if PlayerResource:IsValidPlayer(i) then - local team = PlayerResource:GetTeam(i) - local color = S.TEAM_COLORS[team] - - if color ~= nil then - PlayerResource:SetCustomPlayerColor(i, color[1], color[2], color[3]) - else - self:warnf(WARNF_MISSING_TEAM_COLOR, i, team) - end - end + if color ~= nil then + PlayerResource:SetCustomPlayerColor(i, color[1], color[2], color[3]) + else + self:warnf(WARNF_MISSING_TEAM_COLOR, i, team) end end - elseif state == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then - self:OnGameInProgress() - end -end - ---- Called once when the player fully connects and becomes "Ready" during loading. ---- @param payload dota2.events.player_connect_full -function M:_OnConnectFull(payload) - self:d("_OnConnectFull", { payload = payload }) - - if self._reentrant then - return - end - - local player = assertf( - PlayerResource:GetPlayer(payload.PlayerID), - "received invalid player ID from event payload %s", - inspect(payload) - ) - - self._reentrant = true - self:OnConnectFull(player, payload.userid) - self._reentrant = false - - if not self._first_player_loaded then - self._first_player_loaded = true - self:OnFirstPlayerLoaded() end end ---- Called when an NPC has spawned somewhere in game, including heroes. ---- @param payload dota2.events.npc_spawned -function M:_OnNPCSpawned(payload) - self:d("_OnNPCSpawned", { payload = payload }) - - if self._reentrant then - return - end - - local npc = EntIndexToHScript(payload.entindex) --[[@as CDOTA_BaseNPC?]] - - if npc ~= nil and npc:IsRealHero() and not self._first_spawned then - self._first_spawned = true - self:OnHeroInGame(npc) - end -end - ---- Called when an entity was killed. ---- @param payload dota2.events.entity_killed -function M:_OnEntityKilled(payload) - self:d("_OnEntityKilled", { payload = payload }) - - if self._reentrant then - return - end - - local killed = EntIndexToHScript(payload.entindex_killed) - local attacker = nil - local inflictor = nil - - if payload.entindex_attacker ~= nil then - attacker = EntIndexToHScript(payload.entindex_attacker) - end - - if payload.entindex_inflictor ~= nil then - inflictor = EntIndexToHScript(payload.entindex_inflictor) - end - - self._reentrant = true - self:OnEntityKilled(killed, attacker, inflictor) - self._reentrant = false -end - --- }}} --- events.game {{{ - -local ERRF_ABILITY_OR_ITEM_NOT_FOUND = "Could not find ability or item named %q on unit %q" - ---- The overall game state has changeds. ---- @param state DOTA_GameState ---- @param payload table -function M:OnGameRulesStateChange(state, payload) - self:d("OnGameRulesStateChange", { state = state, payload = payload }) -end - ---- Called once when the player fully connects and becomes "Ready" during loading. ---- @param player CDOTAPlayerController --- @param user_id integer -function M:OnConnectFull(player, user_id) - self:d("OnConnectFull", { player = player:GetPlayerID() }) - +--- @param player CDOTAPlayerController +function M:add_player_user(user_id, player) self.users[user_id] = player self.players[player:GetPlayerID()] = player end ---- Called once and only once as soon as the first player (almost certain to be ---- the server in local lobbies) loads in. ---- ---- It can be used to initialize state that isn't initializeable in @{Activate} ---- but needs to be done before everyone loads in. -function M:OnFirstPlayerLoaded() - self:d("OnFirstPlayerLoaded") -end - ---- Called once and only once after all players have loaded into the game, ---- right as the hero selection time begins. ---- ---- It can be used to initialize non-hero player state or adjust the hero ---- selection (i.e. force random etc) -function M:OnAllPlayersLoaded() - self:d("OnAllPlayersLoaded") -end - ---- Called once and only once for every player when they spawn into the game ---- for the first time. ---- ---- It is also called if the player's hero is replaced with a new hero for any ---- reason. This function is useful for initializing heroes, such as adding ---- levels, changing the starting gold, removing/adding abilities, adding ---- physics, etc. ---- ---- @param hero CDOTA_BaseNPC_Hero -function M:OnHeroInGame(hero) - self:d("OnHeroInGame", { hero = hero:GetUnitName() }) - - local player_id = hero:GetPlayerID() - local player = - assertf(PlayerResource:GetPlayer(player_id), "received invalid player id %d", player_id) - - local payload = { - id = hero:GetHeroID(), - name = hero:GetUnitName(), - variant = hero:GetHeroFacetID(), - } - - custom_ev.send_player(CUSTOM_EVENTS.EVENT_PLAYER_HERO_IN_GAME, player, payload) -end - ---- Called once and only once when the game completely begins (about 0:00 on the clock). -function M:OnGameInProgress() - self:d("OnGameInProgress") -end - ---- An entity has been hurt. ---- @param payload dota2.events.entity_hurt -function M:OnEntityHurt(payload) - self:d("OnEntityHurt", { payload = payload }) - - local attacker - local inflictor - local victim = Unit:new(EntIndexToHScript(payload.entindex_killed)) - - if payload.entindex_attacker ~= nil then - attacker = Unit:new(EntIndexToHScript(payload.entindex_attacker)) - end - - -- FIXME: This is a hack to fix an issue when an entity is killed with `ForceKill`, - -- FIXME: which will trigger this event. I'm not sure which enum `damagebits` is using, - -- FIXME: but regular damage seems to always set it to 0 while `ForceKill` sets it to 4096 - if payload.entindex_inflictor ~= nil and payload.damagebits == 0 then - inflictor = Ability:new(EntIndexToHScript(payload.entindex_inflictor)) - end - - local damage = DamageInstance:new(victim, payload.damage, attacker, inflictor) - - self.combos:on_entity_hurt(damage) -end - ---- An item was purchased by a player. ---- @param payload dota2.events.dota_item_purchased -function M:OnItemPurchased(payload) - self:d("OnItemPurchased", { payload = payload }) - - local player = assertf( - PlayerResource:GetPlayer(payload.PlayerID), - "received invalid player ID from event payload %s", - inspect(payload) - ) - - self.combos:on_item_purchased(player, { - item = payload.itemname, - cost = payload.itemcost, - }) -end - ---- Called whenever an ability begins its PhaseStart phase (but before it is actually cast). ---- @param payload dota2.events.dota_player_begin_cast -function M:OnAbilityCastBegins(payload) - self:d("OnAbilityCastBegins", { payload = payload }) -end - ---- An ability was used by a player (including items). ---- @param payload dota2.events.dota_player_used_ability -function M:OnAbilityUsed(payload) - self:d("OnAbilityUsed", { payload = payload }) - - local player = assertf( - PlayerResource:GetPlayer(payload.PlayerID), - "received invalid player ID from event payload %s", - inspect(payload) - ) - - local caster = Unit:new(EntIndexToHScript(payload.caster_entindex)) - local ability_ent = caster:find_ability_or_item(payload.abilityname) - - if ability_ent == nil then - errorf(ERRF_ABILITY_OR_ITEM_NOT_FOUND, payload.abilityname, caster.name) - end - - local ability = Ability:new(ability_ent) - - self.combos:on_ability_used(player, caster, ability) -end - ---- A non-player entity (necro-book, chen creep, etc) used an ability. ---- @param payload dota2.events.dota_non_player_used_ability -function M:OnNonPlayerUsedAbility(payload) - self:d("OnNonPlayerUsedAbility", { payload = payload }) -end - ---- A channelled ability finished by either completing or being interrupted. ---- @param payload dota2.events.dota_ability_channel_finished -function M:OnAbilityChannelFinished(payload) - self:d("OnAbilityChannelFinished", { payload = payload }) -end - ---- An entity died. --- @tparam CDOTA_BaseNPC killed Killed unit --- @tparam[opt] CDOTA_BaseNPC attacker Attacker unit --- @tparam[opt] CDOTABaseAbility inflictor Inflictor ability -function M:OnEntityKilled(killed, attacker, inflictor) - self:d("OnEntityKilled", { - killed = killed:GetName(), - attacker = attacker and attacker:GetName(), - inflictor = inflictor and inflictor:GetName(), - }) -end - -- }}} -- events.custom {{{ diff --git a/game/scripts/vscripts/invk/game_mode/game_events.lua b/game/scripts/vscripts/invk/game_mode/game_events.lua new file mode 100644 index 0000000..07f9421 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/game_events.lua @@ -0,0 +1,273 @@ +local class = require("middleclass") +local inspect = require("inspect") + +local Ability = require("invk.dota2.ability") +local CUSTOM_EVENTS = require("invk.const.custom_events") +local DamageInstance = require("invk.dota2.damage_instance") +local Env = require("invk.game_mode.env") +local Logger = require("invk.logger") +local Unit = require("invk.dota2.unit") +local custom_ev = require("invk.dota2.custom_events") +local func = require("invk.lang.function") + +--- @class invk.game_mode.GameEvents : middleclass.Class, invk.log.Mixin +--- @field game invk.GameMode +--- @field logger? invk.Logger +--- @field private _first_spawned boolean +--- @field private _first_player_loaded boolean +local M = class("invk.game_mode.GameEvents") + +M:include(Logger.Mixin) + +--- @class invk.game_mode.GameEventsOptions +--- @field logger? invk.Logger + +--- @param game invk.GameMode +--- @param options? invk.game_mode.GameEventsOptions +function M:initialize(game, options) + self.game = game + self._first_spawned = false + self._first_player_loaded = false + + local opts = options or {} + + if opts.logger then + self.logger = opts.logger:child("game_events") + end +end + +function M:register() + self:d("register listeners") + + self:listen_to_game_event("dota_item_purchased", "_on_dota_item_purchased") + self:listen_to_game_event("dota_player_used_ability", "_on_dota_player_used_ability") + self:listen_to_game_event("entity_hurt", "_on_entity_hurt") + self:listen_to_game_event("game_rules_state_change", "_on_game_rules_state_change") + self:listen_to_game_event("npc_spawned", "_on_npc_spawned") + self:listen_to_game_event("player_connect_full", "_on_player_connect_full") +end + +--- @param name string +--- @return fun(...: any): any... +function M:fn_handler(name) + assertf(type(self[name]) == "function", "%s.%s is not a function", self.class.name, name) + + if self.game.env == Env.DEVELOPMENT then + return func.lookupbyname(self, name) + end + + return self[name] +end + +--- @param event string +--- @param method_name string +--- @return EventListenerID +function M:listen_to_game_event(event, method_name) + return ListenToGameEvent(event, self:fn_handler(method_name), self) +end + +--- @param event string +--- @param id PlayerID | { PlayerID: PlayerID } +--- @return CDOTAPlayerController +local function assert_player(event, id) + local fmt = "event %q: invalid player ID %d" + --- @type any[] + local values = { event } + + if type(id) == "table" then + fmt = fmt .. " in payload %s" + values[#values + 1] = id.PlayerID + values[#values + 1] = inspect(id) + id = id.PlayerID + else + values[#values + 1] = id + end + + local player = assertf(PlayerResource:GetPlayer(id), fmt, table.unpack(values)) + + return player +end + +local ERRF_ABILITY_OR_ITEM_NOT_FOUND = "Could not find ability or item named %q on unit %q" + +--- An item was purchased by a player. +--- @param payload dota2.events.dota_item_purchased +function M:_on_dota_item_purchased(payload) + self:d("_on_dota_item_purchased", { payload = payload }) + + local player = assert_player("dota_item_purchased", payload) + + self.game.combos:on_item_purchased(player, { + item = payload.itemname, + cost = payload.itemcost, + }) +end + +--- An ability was used by a player (including items). +--- @param payload dota2.events.dota_player_used_ability +function M:_on_dota_player_used_ability(payload) + self:d("_on_dota_player_used_ability", { payload = payload }) + + local player = assert_player("dota_player_used_ability", payload) + local caster = Unit:new(EntIndexToHScript(payload.caster_entindex)) + local ability_ent = caster:find_ability_or_item(payload.abilityname) + + if ability_ent == nil then + errorf(ERRF_ABILITY_OR_ITEM_NOT_FOUND, payload.abilityname, caster.name) + end + + local ability = Ability:new(ability_ent) + + self.game.combos:on_ability_used(player, caster, ability) +end + +--- An entity has been hurt. +--- @param payload dota2.events.entity_hurt +function M:_on_entity_hurt(payload) + self:d("_on_entity_hurt", { payload = payload }) + + --- @type invk.dota2.Unit + local attacker + --- @type invk.dota2.Ability + local inflictor + local victim = Unit:new(EntIndexToHScript(payload.entindex_killed)) + + if payload.entindex_attacker ~= nil then + attacker = Unit:new(EntIndexToHScript(payload.entindex_attacker)) + end + + -- FIXME: This is a hack to fix an issue when an entity is killed with `ForceKill`, + -- FIXME: which will trigger this event. I'm not sure which enum `damagebits` is using, + -- FIXME: but regular damage seems to always set it to 0 while `ForceKill` sets it to 4096 + if payload.entindex_inflictor ~= nil and payload.damagebits == 0 then + inflictor = Ability:new(EntIndexToHScript(payload.entindex_inflictor)) + end + + local damage = DamageInstance:new(victim, payload.damage, attacker, inflictor) + + self.game.combos:on_entity_hurt(damage) +end + +--- Called when the overall game state has changed. +--- @param payload dota2.events.game_rules_state_change +function M:_on_game_rules_state_change(payload) + self:d("_on_game_rules_state_change", { payload = payload }) + + -- if self._reentrant then + -- return + -- end + + local state = GameRules:State_Get() + + -- self._reentrant = true + self:on_game_rules_state_change(state, payload) + -- self._reentrant = false + + if state == DOTA_GAMERULES_STATE_HERO_SELECTION then + self.game:post_load_precache() + self:on_all_players_loaded() + self.game:set_team_colors() + elseif state == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then + self:on_game_in_progress() + end +end + +--- The overall game state has changed. +--- @param state DOTA_GameState +--- @param payload dota2.events.game_rules_state_change +function M:on_game_rules_state_change(state, payload) + self:d("on_game_rules_state_change", { state = state, payload = payload }) +end + +--- Called once and only once after all players have loaded into the game, +--- right as the hero selection time begins. +function M:on_all_players_loaded() + self:d("on_all_players_loaded") +end + +--- Called once and only once when the game completely begins (about 0:00 on the clock). +function M:on_game_in_progress() + self:d("on_game_in_progress") +end + +--- Called when an NPC has spawned somewhere in game, including heroes. +--- @param payload dota2.events.npc_spawned +function M:_on_npc_spawned(payload) + self:d("_on_npc_spawned", { payload = payload }) + + -- if self._reentrant then + -- return + -- end + + local npc = EntIndexToHScript(payload.entindex) --[[@as CDOTA_BaseNPC?]] + + if npc ~= nil and npc:IsRealHero() and not self._first_spawned then + self._first_spawned = true + self:on_hero_in_game(npc) + end +end + +--- Called once and only once for every player when they spawn into the game +--- for the first time. +--- +--- It is also called if the player's hero is replaced with a new hero for any +--- reason. This function is useful for initializing heroes, such as adding +--- levels, changing the starting gold, removing/adding abilities, adding +--- physics, etc. +--- +--- @param hero CDOTA_BaseNPC_Hero +function M:on_hero_in_game(hero) + self:d("on_hero_in_game", { hero = hero:GetUnitName() }) + + local player = hero:GetPlayerOwner() + + --- @type invk.custom_events.PlayerHeroInGame + local payload = { + id = hero:GetHeroID(), + name = hero:GetUnitName(), + variant = hero:GetHeroFacetID(), + } + + custom_ev.send_player(CUSTOM_EVENTS.EVENT_PLAYER_HERO_IN_GAME, player, payload) +end + +--- Called once when the player fully connects and becomes "Ready" during loading. +--- @param payload dota2.events.player_connect_full +function M:_on_player_connect_full(payload) + self:d("_on_player_connect_full", { payload = payload }) + + -- if self._reentrant then + -- return + -- end + + local player = assert_player("player_connect_full", payload) + + -- self._reentrant = true + self:on_connect_full(payload.userid, player) + -- self._reentrant = false + + if not self._first_player_loaded then + self._first_player_loaded = true + self:on_first_player_loaded() + end +end + +--- Called once when the player fully connects and becomes "ready" during loading. +--- @param user_id integer +--- @param player CDOTAPlayerController +function M:on_connect_full(user_id, player) + self:d("on_connect_full", { player = player:GetPlayerID() }) + + self.game:add_player_user(user_id, player) +end + +--- Called once and only once as soon as the first player (almost certain to be +--- the server in local lobbies) loads in. +--- +--- It can be used to initialize state that isn't initializeable in [invk.GameMode:Activate] +--- but needs to be done before everyone loads in. +function M:on_first_player_loaded() + self:d("on_first_player_loaded") +end + +return M From 15305dad8335528f9963c5247a8e80bab212f2b0 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 19:45:10 -0300 Subject: [PATCH 22/29] chore(vscripts): refactor game rules --- game/scripts/vscripts/invk/game_mode.lua | 56 +---------------- .../vscripts/invk/game_mode/game_rules.lua | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 54 deletions(-) create mode 100644 game/scripts/vscripts/invk/game_mode/game_rules.lua diff --git a/game/scripts/vscripts/invk/game_mode.lua b/game/scripts/vscripts/invk/game_mode.lua index 476c59f..0c877d7 100644 --- a/game/scripts/vscripts/invk/game_mode.lua +++ b/game/scripts/vscripts/invk/game_mode.lua @@ -17,6 +17,7 @@ local S = require("invk.const.settings") local Timers = require("invk.dota2.timers") local custom_ev = require("invk.dota2.custom_events") local func = require("invk.lang.function") +local game_rules = require("invk.game_mode.game_rules") local rand = require("invk.lang.random") local tbl = require("invk.lang.table") @@ -186,60 +187,7 @@ end function M:setup_game_rules() self:d(" (GameRules) setup") - GameRules:SetCreepMinimapIconScale(S.MINIMAP_CREEP_ICON_SCALE) - GameRules:SetCreepSpawningEnabled(S.ENABLE_CREEP_SPAWN) - GameRules:SetCustomGameAllowBattleMusic(S.ENABLE_BATTLE_MUSIC) - GameRules:SetCustomGameAllowHeroPickMusic(S.ENABLE_HERO_PICK_MUSIC) - GameRules:SetCustomGameAllowMusicAtGameStart(S.ENABLE_GAME_START_MUSIC) - GameRules:SetCustomGameEndDelay(S.GAME_END_DELAY) - GameRules:SetCustomGameSetupRemainingTime(S.GAME_SETUP_TIME) - GameRules:SetCustomGameSetupTimeout(S.GAME_SETUP_TIMEOUT) - GameRules:SetCustomVictoryMessage(S.VICTORY_MESSAGE) - GameRules:SetCustomVictoryMessageDuration(S.VICTORY_MESSAGE_DURATION) - GameRules:SetFirstBloodActive(S.ENABLE_FIRST_BLOOD) - GameRules:SetGoldPerTick(S.GOLD_PER_TICK) - GameRules:SetGoldTickTime(S.GOLD_TICK_TIME) - GameRules:SetHeroMinimapIconScale(S.MINIMAP_HERO_ICON_SCALE) - GameRules:SetHeroRespawnEnabled(S.ENABLE_HERO_RESPAWN) - GameRules:SetHeroSelectionTime(S.HERO_SELECTION_TIME) - GameRules:SetHeroSelectPenaltyTime(S.HERO_SELECTION_PENALTY_TIME) - GameRules:SetHideKillMessageHeaders(S.HIDE_KILL_BANNERS) - GameRules:SetPostGameTime(S.POST_GAME_TIME) - GameRules:SetPreGameTime(S.PRE_GAME_TIME) - GameRules:SetRuneMinimapIconScale(S.MINIMAP_RUNE_ICON_SCALE) - GameRules:SetRuneSpawnTime(S.RUNE_SPAWN_TIME) - GameRules:SetSameHeroSelectionEnabled(S.ALLOW_SAME_HERO_SELECTION) - GameRules:SetShowcaseTime(S.SHOWCASE_TIME) - GameRules:SetStartingGold(S.STARTING_GOLD) - GameRules:SetStrategyTime(S.STRATEGY_TIME) - GameRules:SetTreeRegrowTime(S.TREE_REGROW_TIME) - GameRules:SetUseBaseGoldBountyOnHeroes(S.USE_BASE_HERO_GOLD_BOUNTY) - GameRules:SetUseCustomHeroXPValues(S.USE_CUSTOM_XP_VALUES) - GameRules:SetUseUniversalShopMode(S.UNIVERSAL_SHOP_MODE) - - if self.env == Env.DEVELOPMENT then - GameRules:EnableCustomGameSetupAutoLaunch(true) - GameRules:LockCustomGameSetupTeamAssignment(true) - GameRules:SetCustomGameSetupAutoLaunchDelay(0) - else - GameRules:EnableCustomGameSetupAutoLaunch(S.ENABLE_AUTO_LAUNCH) - GameRules:LockCustomGameSetupTeamAssignment(S.LOCK_TEAM_SETUP) - GameRules:SetCustomGameSetupAutoLaunchDelay(S.AUTO_LAUNCH_DELAY) - end - - for team, number in pairs(S.CUSTOM_TEAM_PLAYER_COUNT) do - GameRules:SetCustomGameTeamMaxPlayers(team, number) - end - - if S.USE_CUSTOM_TEAM_COLORS then - for team, color in pairs(S.TEAM_COLORS) do - SetTeamCustomHealthbarColor(team, color[1], color[2], color[3]) - end - end - - -- Sets a callback to handle saving custom game account records (callback is - -- passed a player id and should return a flat simple table) [Preview/Unreleased] - -- GameRules:SetCustomGameAccountRecordSaveFunction(handle, handle) + game_rules.setup(self.env) end --- }}} diff --git a/game/scripts/vscripts/invk/game_mode/game_rules.lua b/game/scripts/vscripts/invk/game_mode/game_rules.lua new file mode 100644 index 0000000..904aa60 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/game_rules.lua @@ -0,0 +1,60 @@ +local Env = require("invk.game_mode.env") +local S = require("invk.const.settings") + +local M = {} + +--- @param env invk.Env +function M.setup(env) + GameRules:SetCreepMinimapIconScale(S.MINIMAP_CREEP_ICON_SCALE) + GameRules:SetCreepSpawningEnabled(S.ENABLE_CREEP_SPAWN) + GameRules:SetCustomGameAllowBattleMusic(S.ENABLE_BATTLE_MUSIC) + GameRules:SetCustomGameAllowHeroPickMusic(S.ENABLE_HERO_PICK_MUSIC) + GameRules:SetCustomGameAllowMusicAtGameStart(S.ENABLE_GAME_START_MUSIC) + GameRules:SetCustomGameEndDelay(S.GAME_END_DELAY) + GameRules:SetCustomGameSetupRemainingTime(S.GAME_SETUP_TIME) + GameRules:SetCustomGameSetupTimeout(S.GAME_SETUP_TIMEOUT) + GameRules:SetCustomVictoryMessage(S.VICTORY_MESSAGE) + GameRules:SetCustomVictoryMessageDuration(S.VICTORY_MESSAGE_DURATION) + GameRules:SetFirstBloodActive(S.ENABLE_FIRST_BLOOD) + GameRules:SetGoldPerTick(S.GOLD_PER_TICK) + GameRules:SetGoldTickTime(S.GOLD_TICK_TIME) + GameRules:SetHeroMinimapIconScale(S.MINIMAP_HERO_ICON_SCALE) + GameRules:SetHeroRespawnEnabled(S.ENABLE_HERO_RESPAWN) + GameRules:SetHeroSelectionTime(S.HERO_SELECTION_TIME) + GameRules:SetHeroSelectPenaltyTime(S.HERO_SELECTION_PENALTY_TIME) + GameRules:SetHideKillMessageHeaders(S.HIDE_KILL_BANNERS) + GameRules:SetPostGameTime(S.POST_GAME_TIME) + GameRules:SetPreGameTime(S.PRE_GAME_TIME) + GameRules:SetRuneMinimapIconScale(S.MINIMAP_RUNE_ICON_SCALE) + GameRules:SetRuneSpawnTime(S.RUNE_SPAWN_TIME) + GameRules:SetSameHeroSelectionEnabled(S.ALLOW_SAME_HERO_SELECTION) + GameRules:SetShowcaseTime(S.SHOWCASE_TIME) + GameRules:SetStartingGold(S.STARTING_GOLD) + GameRules:SetStrategyTime(S.STRATEGY_TIME) + GameRules:SetTreeRegrowTime(S.TREE_REGROW_TIME) + GameRules:SetUseBaseGoldBountyOnHeroes(S.USE_BASE_HERO_GOLD_BOUNTY) + GameRules:SetUseCustomHeroXPValues(S.USE_CUSTOM_XP_VALUES) + GameRules:SetUseUniversalShopMode(S.UNIVERSAL_SHOP_MODE) + + if env == Env.DEVELOPMENT then + GameRules:EnableCustomGameSetupAutoLaunch(true) + GameRules:LockCustomGameSetupTeamAssignment(true) + GameRules:SetCustomGameSetupAutoLaunchDelay(0) + else + GameRules:EnableCustomGameSetupAutoLaunch(S.ENABLE_AUTO_LAUNCH) + GameRules:LockCustomGameSetupTeamAssignment(S.LOCK_TEAM_SETUP) + GameRules:SetCustomGameSetupAutoLaunchDelay(S.AUTO_LAUNCH_DELAY) + end + + for team, number in pairs(S.CUSTOM_TEAM_PLAYER_COUNT) do + GameRules:SetCustomGameTeamMaxPlayers(team, number) + end + + if S.USE_CUSTOM_TEAM_COLORS then + for team, color in pairs(S.TEAM_COLORS) do + SetTeamCustomHealthbarColor(team, color[1], color[2], color[3]) + end + end +end + +return M From fac3a9d4f77cbccc06d132a8e1d7345f09e0ff61 Mon Sep 17 00:00:00 2001 From: 13k Date: Mon, 1 Sep 2025 19:49:07 -0300 Subject: [PATCH 23/29] chore(vscripts): refactor game mode setup --- game/scripts/vscripts/invk/game_mode.lua | 90 +------------------ .../vscripts/invk/game_mode/game_mode.lua | 81 +++++++++++++++++ 2 files changed, 84 insertions(+), 87 deletions(-) create mode 100644 game/scripts/vscripts/invk/game_mode/game_mode.lua diff --git a/game/scripts/vscripts/invk/game_mode.lua b/game/scripts/vscripts/invk/game_mode.lua index 0c877d7..e615105 100644 --- a/game/scripts/vscripts/invk/game_mode.lua +++ b/game/scripts/vscripts/invk/game_mode.lua @@ -17,6 +17,7 @@ local S = require("invk.const.settings") local Timers = require("invk.dota2.timers") local custom_ev = require("invk.dota2.custom_events") local func = require("invk.lang.function") +local game_mode = require("invk.game_mode.game_mode") local game_rules = require("invk.game_mode.game_rules") local rand = require("invk.lang.random") local tbl = require("invk.lang.table") @@ -134,24 +135,8 @@ function M:setup_modules() rand.seed() end ---- Used to set up async precache calls at the beginning of the gameplay. ---- ---- In this function, place all of your `PrecacheItemByNameAsync` and ---- `PrecacheUnitByNameAsync`. These calls will be made after all players have ---- loaded in, but before they have selected their heroes. ---- `PrecacheItemByNameAsync` can also be used to precache dynamically-added ---- datadriven abilities instead of items. `PrecacheUnitByNameAsync` will ---- precache the `precache{}` block statement of the unit and all `precache{}` ---- block statements for every `Ability#` defined on the unit. ---- ---- This function should only be called once. If you want to/need to precache ---- more items/abilities/units at a later time, you can call the functions ---- individually (for example if you want to precache units in a new wave of ---- holdout). ---- ---- This function should generally only be used if `Precache` is not working. function M:post_load_precache() - self:d("Performing Post-Load precache") + self:d(" (precache) post-load") end --- net_tables {{{ @@ -196,76 +181,7 @@ end function M:setup_game_mode() self:d(" (GameMode) setup") - self.game_mode = GameRules:GetGameModeEntity() - - self.game_mode:SetAlwaysShowPlayerInventory(S.ALWAYS_SHOW_PLAYER_INVENTORY) - self.game_mode:SetAlwaysShowPlayerNames(S.ALWAYS_SHOW_PLAYER_NAMES) - self.game_mode:SetAnnouncerDisabled(S.DISABLE_ANNOUNCER) - self.game_mode:SetBotThinkingEnabled(S.USE_STANDARD_DOTA_BOT_THINKING) - self.game_mode:SetBotsAlwaysPushWithHuman(S.BOTS_ALWAYS_PUSH_WITH_HUMAN) - self.game_mode:SetBotsInLateGame(S.BOTS_LATE_GAME_BEHAVIOR) - self.game_mode:SetBotsMaxPushTier(S.BOTS_MAX_PUSH_TIER) - self.game_mode:SetBountyRuneSpawnInterval(S.BOUNTY_RUNE_SPAWN_INTERVAL) - self.game_mode:SetBuybackEnabled(S.BUYBACK_ENABLED) - self.game_mode:SetCameraDistanceOverride(S.CAMERA_DISTANCE_OVERRIDE) - self.game_mode:SetCameraSmoothCountOverride(S.CAMERA_SMOOTH_COUNT) - self.game_mode:SetCustomBackpackCooldownPercent(S.CUSTOM_BACKPACK_COOLDOWN_PERCENT) - self.game_mode:SetCustomBackpackSwapCooldown(S.CUSTOM_BACKPACK_SWAP_COOLDOWN) - self.game_mode:SetCustomBuybackCooldownEnabled(S.CUSTOM_BUYBACK_COOLDOWN_ENABLED) - self.game_mode:SetCustomBuybackCostEnabled(S.CUSTOM_BUYBACK_COST_ENABLED) - self.game_mode:SetCustomGlyphCooldown(S.CUSTOM_GLYPH_COOLDOWN) - self.game_mode:SetCustomScanCooldown(S.CUSTOM_SCAN_COOLDOWN) - self.game_mode:SetDaynightCycleDisabled(S.DISABLE_DAY_NIGHT_CYCLE) - self.game_mode:SetDeathOverlayDisabled(S.DISABLE_DEATH_OVERLAY) - self.game_mode:SetDraftingBanningTimeOverride(S.DRAFTING_BANNING_TIME) - self.game_mode:SetDraftingHeroPickSelectTimeOverride(S.DRAFTING_HERO_PICK_SELECTION_TIME) - self.game_mode:SetFixedRespawnTime(S.FIXED_RESPAWN_TIME) - self.game_mode:SetFogOfWarDisabled(S.DISABLE_FOG_OF_WAR) - self.game_mode:SetFountainConstantManaRegen(S.FOUNTAIN_CONSTANT_MANA_REGEN) - self.game_mode:SetFountainPercentageHealthRegen(S.FOUNTAIN_PERCENTAGE_HEALTH_REGEN) - self.game_mode:SetFountainPercentageManaRegen(S.FOUNTAIN_PERCENTAGE_MANA_REGEN) - self.game_mode:SetFriendlyBuildingMoveToEnabled(S.ENABLE_FRIENDLY_BUILDING_MOVE_TO_CLICK) - self.game_mode:SetGoldSoundDisabled(S.DISABLE_GOLD_SOUNDS) - self.game_mode:SetHudCombatEventsDisabled(S.DISABLE_COMBAT_EVENTS_HUD) - self.game_mode:SetKillingSpreeAnnouncerDisabled(S.DISABLE_KILLING_SPREE_ANNOUNCER) - self.game_mode:SetLoseGoldOnDeath(S.LOSE_GOLD_ON_DEATH) - self.game_mode:SetMaximumAttackSpeed(S.MAXIMUM_ATTACK_SPEED) - self.game_mode:SetMinimumAttackSpeed(S.MINIMUM_ATTACK_SPEED) - self.game_mode:SetPauseEnabled(S.ENABLE_PAUSE) - self.game_mode:SetPowerRuneSpawnInterval(S.POWER_RUNE_SPAWN_INTERVAL) - self.game_mode:SetRecommendedItemsDisabled(S.RECOMMENDED_BUILDS_DISABLED) - self.game_mode:SetRemoveIllusionsOnDeath(S.REMOVE_ILLUSIONS_ON_DEATH) - self.game_mode:SetRespawnTimeScale(S.RESPAWN_TIME_SCALE) - self.game_mode:SetSelectionGoldPenaltyEnabled(S.ENABLE_SELECTION_GOLD_PENALTY) - self.game_mode:SetStashPurchasingDisabled(S.DISABLE_STASH_PURCHASING) - self.game_mode:SetStickyItemDisabled(S.DISABLE_STICKY_ITEM) - self.game_mode:SetTopBarTeamValuesOverride(S.USE_CUSTOM_TOP_BAR_VALUES) - self.game_mode:SetTopBarTeamValuesVisible(S.TOP_BAR_VISIBLE) - self.game_mode:SetTowerBackdoorProtectionEnabled(S.ENABLE_TOWER_BACKDOOR_PROTECTION) - self.game_mode:SetUnseenFogOfWarEnabled(S.USE_UNSEEN_FOG_OF_WAR) - self.game_mode:SetUseDefaultDOTARuneSpawnLogic(S.USE_DEFAULT_DOTA_RUNE_SPAWN_LOGIC) - self.game_mode:SetWeatherEffectsDisabled(S.DISABLE_WEATHER_EFFECTS) - - -- Must be set before `SetUseCustomHeroLevels` - self.game_mode:SetCustomXPRequiredToReachNextLevel(S.XP_PER_LEVEL_TABLE) - self.game_mode:SetUseCustomHeroLevels(S.USE_CUSTOM_HERO_LEVELS) - - -- self.gameMode:SetCustomAttributeDerivedStatValue(nStatType, flNewValue) - -- self.gameMode:SetHUDVisible(iHUDElement, bVisible) - -- self.gameMode:SetKillableTombstones(S.KILLABLE_TOMBSTONES) - -- self.gameMode:SetTopBarTeamValue(iTeam, nValue) - - if S.FORCE_PICKED_HERO ~= nil then - self.game_mode:SetCustomGameForceHero(S.FORCE_PICKED_HERO) - end - - if S.CUSTOM_TERRAIN_WEATHER_EFFECT ~= nil then - self.game_mode:SetCustomTerrainWeatherEffect(S.CUSTOM_TERRAIN_WEATHER_EFFECT) - end - - for rune, spawn in pairs(S.ENABLED_RUNES) do - self.game_mode:SetRuneEnabled(rune, spawn) - end + self.game_mode = game_mode.setup() end --- }}} diff --git a/game/scripts/vscripts/invk/game_mode/game_mode.lua b/game/scripts/vscripts/invk/game_mode/game_mode.lua new file mode 100644 index 0000000..a4ca68b --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/game_mode.lua @@ -0,0 +1,81 @@ +local S = require("invk.const.settings") + +local M = {} + +--- @return CDOTABaseGameMode +function M.setup() + local game_mode = GameRules:GetGameModeEntity() + + game_mode:SetAlwaysShowPlayerInventory(S.ALWAYS_SHOW_PLAYER_INVENTORY) + game_mode:SetAlwaysShowPlayerNames(S.ALWAYS_SHOW_PLAYER_NAMES) + game_mode:SetAnnouncerDisabled(S.DISABLE_ANNOUNCER) + game_mode:SetBotThinkingEnabled(S.USE_STANDARD_DOTA_BOT_THINKING) + game_mode:SetBotsAlwaysPushWithHuman(S.BOTS_ALWAYS_PUSH_WITH_HUMAN) + game_mode:SetBotsInLateGame(S.BOTS_LATE_GAME_BEHAVIOR) + game_mode:SetBotsMaxPushTier(S.BOTS_MAX_PUSH_TIER) + game_mode:SetBountyRuneSpawnInterval(S.BOUNTY_RUNE_SPAWN_INTERVAL) + game_mode:SetBuybackEnabled(S.BUYBACK_ENABLED) + game_mode:SetCameraDistanceOverride(S.CAMERA_DISTANCE_OVERRIDE) + game_mode:SetCameraSmoothCountOverride(S.CAMERA_SMOOTH_COUNT) + game_mode:SetCustomBackpackCooldownPercent(S.CUSTOM_BACKPACK_COOLDOWN_PERCENT) + game_mode:SetCustomBackpackSwapCooldown(S.CUSTOM_BACKPACK_SWAP_COOLDOWN) + game_mode:SetCustomBuybackCooldownEnabled(S.CUSTOM_BUYBACK_COOLDOWN_ENABLED) + game_mode:SetCustomBuybackCostEnabled(S.CUSTOM_BUYBACK_COST_ENABLED) + game_mode:SetCustomGlyphCooldown(S.CUSTOM_GLYPH_COOLDOWN) + game_mode:SetCustomScanCooldown(S.CUSTOM_SCAN_COOLDOWN) + game_mode:SetDaynightCycleDisabled(S.DISABLE_DAY_NIGHT_CYCLE) + game_mode:SetDeathOverlayDisabled(S.DISABLE_DEATH_OVERLAY) + game_mode:SetDraftingBanningTimeOverride(S.DRAFTING_BANNING_TIME) + game_mode:SetDraftingHeroPickSelectTimeOverride(S.DRAFTING_HERO_PICK_SELECTION_TIME) + game_mode:SetFixedRespawnTime(S.FIXED_RESPAWN_TIME) + game_mode:SetFogOfWarDisabled(S.DISABLE_FOG_OF_WAR) + game_mode:SetFountainConstantManaRegen(S.FOUNTAIN_CONSTANT_MANA_REGEN) + game_mode:SetFountainPercentageHealthRegen(S.FOUNTAIN_PERCENTAGE_HEALTH_REGEN) + game_mode:SetFountainPercentageManaRegen(S.FOUNTAIN_PERCENTAGE_MANA_REGEN) + game_mode:SetFriendlyBuildingMoveToEnabled(S.ENABLE_FRIENDLY_BUILDING_MOVE_TO_CLICK) + game_mode:SetGoldSoundDisabled(S.DISABLE_GOLD_SOUNDS) + game_mode:SetHudCombatEventsDisabled(S.DISABLE_COMBAT_EVENTS_HUD) + game_mode:SetKillingSpreeAnnouncerDisabled(S.DISABLE_KILLING_SPREE_ANNOUNCER) + game_mode:SetLoseGoldOnDeath(S.LOSE_GOLD_ON_DEATH) + game_mode:SetMaximumAttackSpeed(S.MAXIMUM_ATTACK_SPEED) + game_mode:SetMinimumAttackSpeed(S.MINIMUM_ATTACK_SPEED) + game_mode:SetPauseEnabled(S.ENABLE_PAUSE) + game_mode:SetPowerRuneSpawnInterval(S.POWER_RUNE_SPAWN_INTERVAL) + game_mode:SetRecommendedItemsDisabled(S.RECOMMENDED_BUILDS_DISABLED) + game_mode:SetRemoveIllusionsOnDeath(S.REMOVE_ILLUSIONS_ON_DEATH) + game_mode:SetRespawnTimeScale(S.RESPAWN_TIME_SCALE) + game_mode:SetSelectionGoldPenaltyEnabled(S.ENABLE_SELECTION_GOLD_PENALTY) + game_mode:SetStashPurchasingDisabled(S.DISABLE_STASH_PURCHASING) + game_mode:SetStickyItemDisabled(S.DISABLE_STICKY_ITEM) + game_mode:SetTopBarTeamValuesOverride(S.USE_CUSTOM_TOP_BAR_VALUES) + game_mode:SetTopBarTeamValuesVisible(S.TOP_BAR_VISIBLE) + game_mode:SetTowerBackdoorProtectionEnabled(S.ENABLE_TOWER_BACKDOOR_PROTECTION) + game_mode:SetUnseenFogOfWarEnabled(S.USE_UNSEEN_FOG_OF_WAR) + game_mode:SetUseDefaultDOTARuneSpawnLogic(S.USE_DEFAULT_DOTA_RUNE_SPAWN_LOGIC) + game_mode:SetWeatherEffectsDisabled(S.DISABLE_WEATHER_EFFECTS) + + -- Must be set before `SetUseCustomHeroLevels` + game_mode:SetCustomXPRequiredToReachNextLevel(S.XP_PER_LEVEL_TABLE) + game_mode:SetUseCustomHeroLevels(S.USE_CUSTOM_HERO_LEVELS) + + -- gameMode:SetCustomAttributeDerivedStatValue(nStatType, flNewValue) + -- gameMode:SetHUDVisible(iHUDElement, bVisible) + -- gameMode:SetKillableTombstones(S.KILLABLE_TOMBSTONES) + -- gameMode:SetTopBarTeamValue(iTeam, nValue) + + if S.FORCE_PICKED_HERO ~= nil then + game_mode:SetCustomGameForceHero(S.FORCE_PICKED_HERO) + end + + if S.CUSTOM_TERRAIN_WEATHER_EFFECT ~= nil then + game_mode:SetCustomTerrainWeatherEffect(S.CUSTOM_TERRAIN_WEATHER_EFFECT) + end + + for rune, spawn in pairs(S.ENABLED_RUNES) do + game_mode:SetRuneEnabled(rune, spawn) + end + + return game_mode +end + +return M From a782796fe68e30fdba39b8da0875d8ad4f7e466a Mon Sep 17 00:00:00 2001 From: 13k Date: Tue, 2 Sep 2025 11:13:45 -0300 Subject: [PATCH 24/29] fix(vscripts): fix item key values --- .../invk/dota2/kv/item_key_values.lua | 5 -- .../invk/dota2/kv/items_key_values.lua | 42 ++++++------- spec/dota2/kv/item_key_values.lua | 38 ++++++++++++ spec/dota2/kv/items_key_values_spec.lua | 59 +++++++++++++++++++ 4 files changed, 119 insertions(+), 25 deletions(-) create mode 100644 spec/dota2/kv/item_key_values.lua create mode 100644 spec/dota2/kv/items_key_values_spec.lua diff --git a/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua index 04750d6..f4cc7ee 100644 --- a/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua +++ b/game/scripts/vscripts/invk/dota2/kv/item_key_values.lua @@ -20,11 +20,6 @@ function M:initialize(name, data) end --- Checks if the item matches the given search query. ---- ---- It searches for matches in these entries: ---- ---- * `ItemShopTags` ---- --- @param query string # Query string --- @return boolean function M:matches_query(query) diff --git a/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua index 4b36eea..20e0a3f 100644 --- a/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua +++ b/game/scripts/vscripts/invk/dota2/kv/items_key_values.lua @@ -5,18 +5,7 @@ local KeyValues = require("invk.dota2.kv.key_values") local tbl = require("invk.lang.table") local KV_PATH = "scripts/npc/items.txt" -local ITEM_KEY_PATT = "^item_" - ---- @param value invk.dota2.kv.Value ---- @param key string ---- @return invk.dota2.kv.ItemKeyValues? -local function parse_item_entry(value, key) - if key:match(ITEM_KEY_PATT) and type(value) == "table" then - return ItemKeyValues:new(key, value) - else - return nil - end -end +local ITEM_KEY_PREFIX = "item_" --- Collection of [invk.dota2.kv.ItemKeyValues]. --- @class invk.dota2.kv.ItemsKeyValues : middleclass.Class @@ -34,20 +23,33 @@ end --- Constructor. --- @param data invk.dota2.KeyValues # KeyValues data function M:initialize(data) - self.data = tbl.map(data, parse_item_entry) + self.data = tbl.map(data, M.parse_item_entry) +end + +--- @private +--- @param value invk.dota2.kv.Value +--- @param key string +--- @return invk.dota2.kv.ItemKeyValues? +function M.parse_item_entry(value, key) + if key:sub(1, #ITEM_KEY_PREFIX) == ITEM_KEY_PREFIX and type(value) == "table" then + return ItemKeyValues:new(key, value) + end + + return nil end --- Searches for item KeyValues matching the given query. --- @param query string # Query string ---- @return invk.dota2.KeyValues # A table of found entries +--- @return invk.dota2.KeyValues # Table of found items function M:search(query) - return tbl.map(self.data, function(item) - if item:MatchesQuery(query) then - return item.data - else - return nil + return tbl.map( + self.data, + --- @param item invk.dota2.kv.ItemKeyValues + --- @return invk.dota2.KeyValues? + function(item) + return item:matches_query(query) and item.data or nil end - end) + ) end return M diff --git a/spec/dota2/kv/item_key_values.lua b/spec/dota2/kv/item_key_values.lua new file mode 100644 index 0000000..57aa021 --- /dev/null +++ b/spec/dota2/kv/item_key_values.lua @@ -0,0 +1,38 @@ +local assert = require("luassert") + +local ItemKeyValues = require("invk.dota2.kv.item_key_values") + +describe("invk.dota2.kv.ItemKeyValues", function() + describe("constructor", function() + it("sets attributes", function() + local subject = ItemKeyValues:new("item_empty", { + foo = "bar", + }) + + assert.equal("item_empty", subject.name) + assert.same({}, subject.shop_tags) + + subject = ItemKeyValues:new("item_mango", { + foo = "baz", + ItemShopTags = "consumable;delicious", + }) + + assert.equal("item_mango", subject.name) + assert.same({ "consumable", "delicious" }, subject.shop_tags) + end) + end) + + describe(":matches_query", function() + it("checks if its attributes match the given query", function() + local subject = ItemKeyValues:new("item_mango", { + foo = "baz", + ItemShopTags = "consumable;delicious", + }) + + assert.is_false(subject:matches_query("non-match")) + assert.is_true(subject:matches_query("mango")) + assert.is_true(subject:matches_query("consumable")) + assert.is_true(subject:matches_query("delicious")) + end) + end) +end) diff --git a/spec/dota2/kv/items_key_values_spec.lua b/spec/dota2/kv/items_key_values_spec.lua new file mode 100644 index 0000000..a1c7a95 --- /dev/null +++ b/spec/dota2/kv/items_key_values_spec.lua @@ -0,0 +1,59 @@ +local assert = require("luassert") + +local ItemKeyValues = require("invk.dota2.kv.item_key_values") +local ItemsKeyValues = require("invk.dota2.kv.items_key_values") + +describe("invk.dota2.kv.ItemsKeyValues", function() + local item_blink_kv = { foo = "bar", ItemShopTags = "mobility;dagger" } + local item_mango_kv = { foo = "qux", ItemShopTags = "consumable;delicious" } + local item_potion_kv = { foo = "fox", ItemShopTags = "consumable;health" } + + describe("constructor", function() + it("filters item keys", function() + local subject = ItemsKeyValues:new({ + ["item_blink"] = item_blink_kv, + ["non_item"] = { foo = "baz" }, + ["item_mango"] = item_mango_kv, + }) + + local expected = { + ["item_blink"] = ItemKeyValues:new("item_blink", item_blink_kv), + ["item_mango"] = ItemKeyValues:new("item_mango", item_mango_kv), + } + + assert.same(expected, subject.data) + end) + end) + + describe(":search", function() + it("filters items matching the given query", function() + local subject = ItemsKeyValues:new({ + ["item_blink"] = item_blink_kv, + ["item_mango"] = item_mango_kv, + ["item_potion"] = item_potion_kv, + ["non_item"] = { foo = "baz" }, + }) + + local expected = {} + + assert.same(expected, subject:search("non-match")) + + -- match by name + + expected = { + ["item_mango"] = item_mango_kv, + } + + assert.same(expected, subject:search("mango")) + + -- match by shop tag + + expected = { + ["item_mango"] = item_mango_kv, + ["item_potion"] = item_potion_kv, + } + + assert.same(expected, subject:search("consumable")) + end) + end) +end) From 1fd0b16ae9ef7883b50ae10f4cff5d2f6d53a262 Mon Sep 17 00:00:00 2001 From: 13k Date: Tue, 2 Sep 2025 12:01:37 -0300 Subject: [PATCH 25/29] chore(vscripts): refactor custom events setup --- .../vscripts/invk/const/custom_events.lua | 2 +- game/scripts/vscripts/invk/game_mode.lua | 211 ++++-------------- .../vscripts/invk/game_mode/custom_events.lua | 163 ++++++++++++++ .../vscripts/invk/game_mode/game_events.lua | 24 +- 4 files changed, 216 insertions(+), 184 deletions(-) create mode 100644 game/scripts/vscripts/invk/game_mode/custom_events.lua diff --git a/game/scripts/vscripts/invk/const/custom_events.lua b/game/scripts/vscripts/invk/const/custom_events.lua index 2905576..0334056 100644 --- a/game/scripts/vscripts/invk/const/custom_events.lua +++ b/game/scripts/vscripts/invk/const/custom_events.lua @@ -138,7 +138,7 @@ M.EVENT_ITEM_PICKER_QUERY_REQUEST = "invk_item_picker_query_request" --- Payload for event `EVENT_ITEM_PICKER_QUERY_RESPONSE` --- @class invk.custom_events.ItemPickerQueryResponsePayload ---- @field items table[] # Items found +--- @field items invk.dota2.KeyValues # Items found --- Item picker query response M.EVENT_ITEM_PICKER_QUERY_RESPONSE = "invk_item_picker_query_response" diff --git a/game/scripts/vscripts/invk/game_mode.lua b/game/scripts/vscripts/invk/game_mode.lua index e615105..78cc8a0 100644 --- a/game/scripts/vscripts/invk/game_mode.lua +++ b/game/scripts/vscripts/invk/game_mode.lua @@ -1,8 +1,8 @@ local class = require("middleclass") local COMMANDS = require("invk.const.commands") -local CUSTOM_EVENTS = require("invk.const.custom_events") local Combos = require("invk.combo.combos") +local CustomEvents = require("invk.game_mode.custom_events") local Env = require("invk.game_mode.env") local GameEvents = require("invk.game_mode.game_events") local INVOKER = require("invk.const.invoker") @@ -15,7 +15,6 @@ local NetTable = require("invk.dota2.net_table") local PRECACHE = require("invk.const.precache") local S = require("invk.const.settings") local Timers = require("invk.dota2.timers") -local custom_ev = require("invk.dota2.custom_events") local func = require("invk.lang.function") local game_mode = require("invk.game_mode.game_mode") local game_rules = require("invk.game_mode.game_rules") @@ -32,10 +31,11 @@ local DEFAULT_ENV = Env.is_dev_mode() and Env.DEVELOPMENT or Env.PRODUCTION --- @field players { [PlayerID]: CDOTAPlayerController? } --- @field items_kv invk.dota2.kv.ItemsKeyValues --- @field net_tables { [invk.net_table.Name]: invk.dota2.NetTable } +--- @field game_mode CDOTABaseGameMode --- @field game_events invk.game_mode.GameEvents +--- @field custom_events invk.game_mode.CustomEvents --- @field combos invk.combo.Combos --- @field logger invk.Logger ---- @field private game_mode CDOTABaseGameMode --- @field private _reentrant boolean local M = class("invk.GameMode") @@ -85,6 +85,7 @@ function M:initialize(options) end) self.game_events = GameEvents:new(self, { logger = self.logger }) + self.custom_events = CustomEvents:new(self, { logger = self.logger }) self.combos = Combos:new(self.net_tables[NET_TABLES.Name.MAIN], { logger = self.logger }) end @@ -92,6 +93,8 @@ end --- @param fn_name string --- @return fun(...: any): any... function M:fn_handler(fn_name) + assertf(type(self[fn_name]) == "function", "%s.%s is not a function", self.class.name, fn_name) + if self.env == Env.DEVELOPMENT then return func.lookupbyname(self, fn_name) end @@ -119,7 +122,7 @@ function M:activate() self:setup_game_mode() self.game_events:register() - self:register_custom_events() + self.custom_events:register() self:register_commands() self:register_convars() @@ -139,88 +142,13 @@ function M:post_load_precache() self:d(" (precache) post-load") end ---- net_tables {{{ - -function M:setup_net_tables() - self:d(" (net_tables) setup") - - -- main/hero_data - do - local net_table = self.net_tables[NET_TABLES.Name.MAIN] - - net_table:set(net_table.keys.HERO_DATA, INVOKER:serialize()) - end - - -- hero/key_values - do - local net_table = self.net_tables[NET_TABLES.Name.HERO] - - net_table:set(net_table.keys.KEY_VALUES, INVOKER.KEY_VALUES.data) - end - - -- abilities/key_values - do - local net_table = self.net_tables[NET_TABLES.Name.ABILITIES] - - net_table:set(net_table.keys.KEY_VALUES, INVOKER.KEY_VALUES:abilities_data()) - end -end - ---- }}} ---- game_rules {{{ - -function M:setup_game_rules() - self:d(" (GameRules) setup") - - game_rules.setup(self.env) -end - ---- }}} ---- game_mode {{{ - -function M:setup_game_mode() - self:d(" (GameMode) setup") - - self.game_mode = game_mode.setup() -end - ---- }}} ---- events {{{ - ---- @param event string ---- @param method_name string ---- @return CustomGameEventListenerID -function M:subscribe_to_custom_event(event, method_name) - return custom_ev.subscribe(event, self:method_handler(method_name)) -end - -function M:register_custom_events() - self:d(" (custom_events) register listeners") - - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_PLAYER_QUIT_REQUEST, "OnPlayerQuitRequest") - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "OnCombosReload") - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_START, "OnComboStart") - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_STOP, "OnComboStop") - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_COMBO_RESTART, "OnComboRestart") - self:subscribe_to_custom_event( - CUSTOM_EVENTS.EVENT_FREESTYLE_HERO_LEVEL_UP, - "OnFreestyleHeroLevelUp" - ) - - self:subscribe_to_custom_event( - CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_START, - "OnCombatLogCaptureStart" - ) - - self:subscribe_to_custom_event( - CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_STOP, - "OnCombatLogCaptureStop" - ) - self:subscribe_to_custom_event(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_REQUEST, "OnItemPickerQuery") +--- @param user_id integer +--- @param player CDOTAPlayerController +function M:add_player_user(user_id, player) + self.users[user_id] = player + self.players[player:GetPlayerID()] = player end --- events.game {{{ - local WARNF_MISSING_TEAM_COLOR = "Attempted to set custom player color for player %d and team %d, but the team color is not configured." @@ -243,110 +171,51 @@ function M:set_team_colors() end end ---- @param user_id integer ---- @param player CDOTAPlayerController -function M:add_player_user(user_id, player) - self.users[user_id] = player - self.players[player:GetPlayerID()] = player -end - --- }}} --- events.custom {{{ - ---- Handles player quit request events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.PlayerQuitRequest -function M:OnPlayerQuitRequest(player, payload) - self:d("OnPlayerQuitRequest", { player = player:GetPlayerID(), payload = payload }) - - SendToServerConsole("disconnect") -end - ---- Handles combos reload events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.CombosReloadPayload -function M:OnCombosReload(player, payload) - self:d("OnCombosReload", { player = player:GetPlayerID(), payload = payload }) - self.combos:load() -end - ---- Handles combo start events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.ComboStartPayload -function M:OnComboStart(player, payload) - self:d("OnComboStart", { player = player:GetPlayerID(), payload = payload }) - - local combo = self.combos:create(payload.id) - - self.combos:on_start(player, combo) -end - ---- Handles combo stop events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.ComboStopPayload -function M:OnComboStop(player, payload) - self:d("OnComboStop", { player = player:GetPlayerID(), payload = payload }) +--- net_tables {{{ - self.combos:on_stop(player) -end +function M:setup_net_tables() + self:d(" (net_tables) setup") ---- Handles combo restart events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.ComboRestartPayload -function M:OnComboRestart(player, payload) - self:d("OnComboRestart", { player = player:GetPlayerID(), payload = payload }) + -- main/hero_data + do + local nt = self.net_tables[NET_TABLES.Name.MAIN] - --- @type invk.combo.hero.TeardownOptions - local options = { hard_reset = payload.hardReset == 1 } + nt:set(nt.keys.HERO_DATA, INVOKER:serialize()) + end - self.combos:on_restart(player, options) -end + -- hero/key_values + do + local nt = self.net_tables[NET_TABLES.Name.HERO] ---- Handles freestyle hero level up events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.FreestyleHeroLevelUpPayload -function M:OnFreestyleHeroLevelUp(player, payload) - self:d("OnFreestyleHeroLevelUp", { player = player:GetPlayerID(), payload = payload }) + nt:set(nt.keys.KEY_VALUES, INVOKER.KEY_VALUES.data) + end - local options = { - level = payload.level, - max_level = payload.maxLevel == 1, - } + -- abilities/key_values + do + local nt = self.net_tables[NET_TABLES.Name.ABILITIES] - self.combos:freestyle_hero_level_up(player, options) + nt:set(nt.keys.KEY_VALUES, INVOKER.KEY_VALUES:abilities_data()) + end end ---- Handles combat log capture start events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.CombatLogCaptureStartPayload -function M:OnCombatLogCaptureStart(player, payload) - self:d("OnCombatLogCaptureStart", { player = player:GetPlayerID(), payload = payload }) - - self.combos:start_capturing_abilities(player) -end +--- }}} +--- game_rules {{{ ---- Handles combat log capture stop events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.CombatLogCaptureStopPayload -function M:OnCombatLogCaptureStop(player, payload) - self:d("OnCombatLogCaptureStop", { player = player:GetPlayerID(), payload = payload }) +function M:setup_game_rules() + self:d(" (GameRules) setup") - self.combos:stop_capturing_abilities(player) + game_rules.setup(self.env) end ---- Handles item picker query events. ---- @param player CDOTAPlayerController ---- @param payload invk.custom_events.ItemPickerQueryPayload -function M:OnItemPickerQuery(player, payload) - self:d("OnItemPickerQuery", { player = player:GetPlayerID(), payload = payload }) +--- }}} +--- game_mode {{{ - local response = { items = self.items_kv:search(payload.query) } +function M:setup_game_mode() + self:d(" (GameMode) setup") - custom_ev.send_player(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_RESPONSE, player, response) + self.game_mode = game_mode.setup() end --- }}} - --- }}} --- commands {{{ diff --git a/game/scripts/vscripts/invk/game_mode/custom_events.lua b/game/scripts/vscripts/invk/game_mode/custom_events.lua new file mode 100644 index 0000000..621d950 --- /dev/null +++ b/game/scripts/vscripts/invk/game_mode/custom_events.lua @@ -0,0 +1,163 @@ +local class = require("middleclass") + +local CUSTOM_EVENTS = require("invk.const.custom_events") +local Env = require("invk.game_mode.env") +local Logger = require("invk.logger") +local custom_ev = require("invk.dota2.custom_events") +local func = require("invk.lang.function") + +--- @class invk.game_mode.CustomEvents : middleclass.Class, invk.log.Mixin +--- @field game invk.GameMode +--- @field logger? invk.Logger +local M = class("invk.game_mode.CustomEvents") + +M:include(Logger.Mixin) + +--- @class invk.game_mode.CustomEventsOptions +--- @field logger? invk.Logger + +--- @param game invk.GameMode +--- @param options? invk.game_mode.CustomEventsOptions +function M:initialize(game, options) + self.game = game + + local opts = options or {} + + if opts.logger then + self.logger = opts.logger:child("custom_events") + end +end + +function M:register() + self:d("register listeners") + + self:subscribe(CUSTOM_EVENTS.EVENT_PLAYER_QUIT_REQUEST, "on_player_quit_request") + self:subscribe(CUSTOM_EVENTS.EVENT_COMBOS_RELOAD, "on_combos_reload") + self:subscribe(CUSTOM_EVENTS.EVENT_COMBO_START, "on_combo_start") + self:subscribe(CUSTOM_EVENTS.EVENT_COMBO_STOP, "on_combo_stop") + self:subscribe(CUSTOM_EVENTS.EVENT_COMBO_RESTART, "on_combo_restart") + self:subscribe(CUSTOM_EVENTS.EVENT_FREESTYLE_HERO_LEVEL_UP, "on_freestyle_hero_level_up") + self:subscribe(CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_START, "on_combat_log_capture_start") + self:subscribe(CUSTOM_EVENTS.EVENT_COMBAT_LOG_CAPTURE_STOP, "on_combat_log_capture_stop") + self:subscribe(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_REQUEST, "on_item_picker_query") +end + +--- @param fn_name string +--- @return fun(...: any): any... +function M:fn_handler(fn_name) + assertf(type(self[fn_name]) == "function", "%s.%s is not a function", self.class.name, fn_name) + + if self.game.env == Env.DEVELOPMENT then + return func.lookupbyname(self, fn_name) + end + + return self[fn_name] +end + +--- @param method_name string +--- @return fun(...: any): any... +function M:method_handler(method_name) + return func.bind(self:fn_handler(method_name), self) +end + +--- @param event string +--- @param method_name string +--- @return CustomGameEventListenerID +function M:subscribe(event, method_name) + return custom_ev.subscribe(event, self:method_handler(method_name)) +end + +--- Handles player quit request events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.PlayerQuitRequest +function M:on_player_quit_request(player, payload) + self:d("on_player_quit_request", { player = player:GetPlayerID(), payload = payload }) + + SendToServerConsole("disconnect") +end + +--- Handles combos reload events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.CombosReloadPayload +function M:on_combos_reload(player, payload) + self:d("on_combos_reload", { player = player:GetPlayerID(), payload = payload }) + + self.game.combos:load() +end + +--- Handles combo start events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ComboStartPayload +function M:on_combo_start(player, payload) + self:d("on_combo_start", { player = player:GetPlayerID(), payload = payload }) + + local combo = self.game.combos:create(payload.id) + + self.game.combos:on_start(player, combo) +end + +--- Handles combo stop events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ComboStopPayload +function M:on_combo_stop(player, payload) + self:d("on_combo_stop", { player = player:GetPlayerID(), payload = payload }) + + self.game.combos:on_stop(player) +end + +--- Handles combo restart events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ComboRestartPayload +function M:on_combo_restart(player, payload) + self:d("on_combo_restart", { player = player:GetPlayerID(), payload = payload }) + + self.game.combos:on_restart(player, { + hard_reset = payload.hardReset == 1, + }) +end + +--- Handles freestyle hero level up events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.FreestyleHeroLevelUpPayload +function M:on_freestyle_hero_level_up(player, payload) + self:d("on_freestyle_hero_level_up", { player = player:GetPlayerID(), payload = payload }) + + self.game.combos:freestyle_hero_level_up(player, { + level = payload.level, + max_level = payload.maxLevel == 1, + }) +end + +--- Handles combat log capture start events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.CombatLogCaptureStartPayload +function M:on_combat_log_capture_start(player, payload) + self:d("on_combat_log_capture_start", { player = player:GetPlayerID(), payload = payload }) + + self.game.combos:start_capturing_abilities(player) +end + +--- Handles combat log capture stop events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.CombatLogCaptureStopPayload +function M:on_combat_log_capture_stop(player, payload) + self:d("on_combat_log_capture_stop", { player = player:GetPlayerID(), payload = payload }) + + self.game.combos:stop_capturing_abilities(player) +end + +--- Handles item picker query events. +--- @param player CDOTAPlayerController +--- @param payload invk.custom_events.ItemPickerQueryPayload +function M:on_item_picker_query(player, payload) + self:d("on_item_picker_query", { player = player:GetPlayerID(), payload = payload }) + + local items = self.game.items_kv:search(payload.query) + + --- @type invk.custom_events.ItemPickerQueryResponsePayload + local response = { items = items } + + custom_ev.send_player(CUSTOM_EVENTS.EVENT_ITEM_PICKER_QUERY_RESPONSE, player, response) +end + +return M diff --git a/game/scripts/vscripts/invk/game_mode/game_events.lua b/game/scripts/vscripts/invk/game_mode/game_events.lua index 07f9421..cc3b7c3 100644 --- a/game/scripts/vscripts/invk/game_mode/game_events.lua +++ b/game/scripts/vscripts/invk/game_mode/game_events.lua @@ -39,30 +39,30 @@ end function M:register() self:d("register listeners") - self:listen_to_game_event("dota_item_purchased", "_on_dota_item_purchased") - self:listen_to_game_event("dota_player_used_ability", "_on_dota_player_used_ability") - self:listen_to_game_event("entity_hurt", "_on_entity_hurt") - self:listen_to_game_event("game_rules_state_change", "_on_game_rules_state_change") - self:listen_to_game_event("npc_spawned", "_on_npc_spawned") - self:listen_to_game_event("player_connect_full", "_on_player_connect_full") + self:listen("dota_item_purchased", "_on_dota_item_purchased") + self:listen("dota_player_used_ability", "_on_dota_player_used_ability") + self:listen("entity_hurt", "_on_entity_hurt") + self:listen("game_rules_state_change", "_on_game_rules_state_change") + self:listen("npc_spawned", "_on_npc_spawned") + self:listen("player_connect_full", "_on_player_connect_full") end ---- @param name string +--- @param fn_name string --- @return fun(...: any): any... -function M:fn_handler(name) - assertf(type(self[name]) == "function", "%s.%s is not a function", self.class.name, name) +function M:fn_handler(fn_name) + assertf(type(self[fn_name]) == "function", "%s.%s is not a function", self.class.name, fn_name) if self.game.env == Env.DEVELOPMENT then - return func.lookupbyname(self, name) + return func.lookupbyname(self, fn_name) end - return self[name] + return self[fn_name] end --- @param event string --- @param method_name string --- @return EventListenerID -function M:listen_to_game_event(event, method_name) +function M:listen(event, method_name) return ListenToGameEvent(event, self:fn_handler(method_name), self) end From 0d85451b3e6d9dcd3e97c76a80c84de2491bea05 Mon Sep 17 00:00:00 2001 From: 13k Date: Tue, 2 Sep 2025 12:49:20 -0300 Subject: [PATCH 26/29] refactor(vscripts): change table mapping types --- .../vscripts/invk/combo/base_combo.lua | 11 ++- .../vscripts/invk/combo/combo_sequence.lua | 4 +- game/scripts/vscripts/invk/combo/wait.lua | 2 +- .../invk/dota2/kv/ability_key_values.lua | 2 +- .../invk/dota2/kv/hero_key_values.lua | 67 ++++++++++--------- .../vscripts/invk/dota2/kv/key_values.lua | 4 +- game/scripts/vscripts/invk/dota2/talents.lua | 2 +- game/scripts/vscripts/invk/dota2/unit.lua | 2 +- game/scripts/vscripts/invk/lang/table.lua | 45 ++++++++++--- 9 files changed, 85 insertions(+), 54 deletions(-) diff --git a/game/scripts/vscripts/invk/combo/base_combo.lua b/game/scripts/vscripts/invk/combo/base_combo.lua index 9d06f8d..394fee3 100644 --- a/game/scripts/vscripts/invk/combo/base_combo.lua +++ b/game/scripts/vscripts/invk/combo/base_combo.lua @@ -106,9 +106,14 @@ end --- @return integer[] function M:next_steps_ids() - return tbl.map(self:next_steps(), function(step) - return step.id - end) + return tbl.lmap( + self:next_steps(), + --- @param step invk.combo.ComboStep + --- @return integer + function(step) + return step.id + end + ) end --- Progresses the combo with the given ability if possible. diff --git a/game/scripts/vscripts/invk/combo/combo_sequence.lua b/game/scripts/vscripts/invk/combo/combo_sequence.lua index 3088a1c..b070972 100644 --- a/game/scripts/vscripts/invk/combo/combo_sequence.lua +++ b/game/scripts/vscripts/invk/combo/combo_sequence.lua @@ -55,7 +55,7 @@ M.EVENTS = { local function step_events(steps, step) local next_ids = step.next or {} - return tbl.map(next_ids, function(next_id) + return tbl.lmap(next_ids, function(next_id) local next_step = assertf(steps[next_id], "invalid next_id %d", next_id) --- @type invk.combo.Event @@ -122,7 +122,7 @@ function M:initialize(id, specs, options) self.id = id self.logger = opts.logger self.clock = opts.clock - self.sequence = tbl.map(specs, func.ctor(ComboStep)) + self.sequence = tbl.lmap(specs, func.ctor(ComboStep)) local first_step = assert(self.sequence[1], "received empty sequence") diff --git a/game/scripts/vscripts/invk/combo/wait.lua b/game/scripts/vscripts/invk/combo/wait.lua index d342c18..79432fc 100644 --- a/game/scripts/vscripts/invk/combo/wait.lua +++ b/game/scripts/vscripts/invk/combo/wait.lua @@ -45,7 +45,7 @@ function M.ability_wait(ability) return wait end - local special_waits = tbl.map(special_keys, function(special_key) + local special_waits = tbl.lmap(special_keys, function(special_key) return ability:get_special_value_for(special_key) or 0 end) diff --git a/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua index e83aa89..78e081b 100644 --- a/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua +++ b/game/scripts/vscripts/invk/dota2/kv/ability_key_values.lua @@ -3,7 +3,7 @@ local class = require("middleclass") local KeyValues = require("invk.dota2.kv.key_values") --- AbilityKeyValues class. ---- @class invk.dota2.kv.AbilityKeyValues : middleclass.Class, invk.dota2.kv.KeyValues +--- @class invk.dota2.kv.AbilityKeyValues : invk.dota2.kv.KeyValues --- @field name string --- @field kv invk.dota2.KeyValues local M = class("invk.dota2.kv.AbilityKeyValues", KeyValues) diff --git a/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua b/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua index 42e005c..f1af94e 100644 --- a/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua +++ b/game/scripts/vscripts/invk/dota2/kv/hero_key_values.lua @@ -9,34 +9,10 @@ local KV_HEROES_PATH = "scripts/npc/npc_heroes.txt" local KV_ABILITIES_PATH_PATT = "scripts/npc/heroes/%s.txt" local ABILITY_KEY_PATT = "^Ability(%d+)$" ---- @param value invk.dota2.kv.Value ---- @param key string ---- @return integer?, string? -local function parse_ability_entry(value, key) - if type(value) ~= "string" or value == "" then - return nil - end - - local m_ability_id = key:match(ABILITY_KEY_PATT) - - if m_ability_id == nil then - return nil - end - - local ability_id = tonumber(m_ability_id) - - if ability_id == nil then - return nil - end - - --- @cast ability_id integer - return ability_id, value -end - --- HeroKeyValues class. ---- @class invk.dota2.kv.HeroKeyValues : middleclass.Class, invk.dota2.kv.KeyValues +--- @class invk.dota2.kv.HeroKeyValues : invk.dota2.kv.KeyValues --- @field name string ---- @field abilities { [invk.dota2.invoker.AbilityName]: invk.dota2.kv.AbilityKeyValues } +--- @field abilities { [string]: invk.dota2.kv.AbilityKeyValues } --- @field talents invk.dota2.talents.Map --- @field load fun(class: invk.dota2.kv.HeroKeyValues, name: string): invk.dota2.kv.HeroKeyValues local M = class("invk.dota2.kv.HeroKeyValues", KeyValues) @@ -63,8 +39,8 @@ function M:initialize(name, hero, abilities) self.name = name self.abilities = {} - --- @type invk.dota2.invoker.AbilityName[] - local abilities_names = tbl.map(self.data, parse_ability_entry) + --- @type { [integer]: string } + local abilities_names = tbl.transform(self.data, M.parse_ability_entry) local talents_start = self:require_integer("AbilityTalentStart") local regular_abilities = tbl.slice(abilities_names, 1, talents_start - 1) local talent_abilities = tbl.slice(abilities_names, talents_start) @@ -78,11 +54,40 @@ function M:initialize(name, hero, abilities) self.talents = talents.names_array_to_enums_table(talent_abilities) end +--- @private +--- @param value invk.dota2.kv.Value +--- @param key string +--- @return integer?, string? +function M.parse_ability_entry(value, key) + if type(value) ~= "string" or value == "" then + return nil, nil + end + + local match_id = key:match(ABILITY_KEY_PATT) + + if match_id == nil then + return nil, nil + end + + local id = tonumber(match_id) --[[@as integer?]] + + if id == nil then + return nil, nil + end + + return id, value +end + --- @return invk.dota2.KeyValues function M:abilities_data() - return tbl.map(self.abilities, function(kv) - return kv.data - end) + return tbl.map( + self.abilities, + --- @param kv invk.dota2.kv.AbilityKeyValues + --- @return invk.dota2.KeyValues + function(kv) + return kv.data + end + ) end return M diff --git a/game/scripts/vscripts/invk/dota2/kv/key_values.lua b/game/scripts/vscripts/invk/dota2/kv/key_values.lua index 5b8400a..0cfa2d3 100644 --- a/game/scripts/vscripts/invk/dota2/kv/key_values.lua +++ b/game/scripts/vscripts/invk/dota2/kv/key_values.lua @@ -118,9 +118,7 @@ function M:get_strings(key, sep) local strings = str.split(s, sep) - strings = tbl.map(strings, str.trim) - - return strings + return tbl.lmap(strings, str.trim) end return M diff --git a/game/scripts/vscripts/invk/dota2/talents.lua b/game/scripts/vscripts/invk/dota2/talents.lua index 1ba129a..22d9d71 100644 --- a/game/scripts/vscripts/invk/dota2/talents.lua +++ b/game/scripts/vscripts/invk/dota2/talents.lua @@ -88,7 +88,7 @@ function M.names_array_to_enums_table(names) #LIST ) - return tbl.transform(names, function(name, i) + return tbl.ltransform(names, function(name, i) return LIST[i], name end) end diff --git a/game/scripts/vscripts/invk/dota2/unit.lua b/game/scripts/vscripts/invk/dota2/unit.lua index afacdb2..dbcf867 100644 --- a/game/scripts/vscripts/invk/dota2/unit.lua +++ b/game/scripts/vscripts/invk/dota2/unit.lua @@ -206,7 +206,7 @@ function M:add_items_by_name(items, options) items = tbl.diff(items, self:item_names()) end - return tbl.map(items, function(name) + return tbl.lmap(items, function(name) return self.entity:AddItemByName(name) end) end diff --git a/game/scripts/vscripts/invk/lang/table.lua b/game/scripts/vscripts/invk/lang/table.lua index 532c855..6e8610a 100644 --- a/game/scripts/vscripts/invk/lang/table.lua +++ b/game/scripts/vscripts/invk/lang/table.lua @@ -242,18 +242,17 @@ function M.filter(t, filter) end) end ---- Map table entries with the given map function. ---- @generic K1, V1, K2, V2 ---- @param t { [K1]: V1 } ---- @param map (fun(value: V1, key: K1): V2?) ---- @return { [K2]: V2 } ---- @overload fun(t: V1[], map: (fun(value: V1, index: integer): V2?)): V2[] +--- Map table values with the given mapping function. +--- @generic K, V1, V2 +--- @param t { [K]: V1 } +--- @param map (fun(value: V1, key: K): V2?) +--- @return { [K]: V2 } function M.map(t, map) if t == nil then return {} end - --- @type { [K2]: V2 } + --- @type { [K]: V2 } local res = {} for k1, v1 in pairs(t) do @@ -268,14 +267,38 @@ function M.map(t, map) return res end +--- Map list values with the given mapping function. +--- +--- Alias of [map]. +--- @generic V1, V2 +--- @param t V1[] +--- @param map (fun(value: V1, index: integer): V2?) +--- @return V2[] +function M.lmap(t, map) + return M.map(t, map) +end + +--- Transform table entries with the given mapping function. +--- --- Alias of [map]. --- @generic K1, V1, K2, V2 --- @param t { [K1]: V1 } ---- @param transform (fun(value: V1, key: K1): K2?, V2?) +--- @param map (fun(value: V1, key: K1): K2?, V2?) --- @return { [K2]: V2 } ---- @overload fun(t: V1[], map: (fun(value: V1, index: integer): K2?, V2?)): { [K2]: V2 } -function M.transform(t, transform) - return M.map(t, transform) +function M.transform(t, map) + return M.map(t, map) +end + +--- Transform a list of values into a table of mapped keys and values using the given mapping +--- function. +--- +--- Alias of [map]. +--- @generic K, V1, V2 +--- @param t V1[] +--- @param map (fun(value: V1, index: integer): K?, V2?) +--- @return { [K]: V2 } +function M.ltransform(t, map) + return M.map(t, map) end --- Reduce table values with the given reduce function. From 75381ab045211839ee42077f6f8c7f071a4d7939 Mon Sep 17 00:00:00 2001 From: 13k Date: Tue, 2 Sep 2025 13:01:04 -0300 Subject: [PATCH 27/29] fix(panorama): fix item picker --- .../panorama/scripts/custom_game/ui/item_picker.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/content/panorama/scripts/custom_game/ui/item_picker.ts b/src/content/panorama/scripts/custom_game/ui/item_picker.ts index 242c1b4..c1e7d57 100644 --- a/src/content/panorama/scripts/custom_game/ui/item_picker.ts +++ b/src/content/panorama/scripts/custom_game/ui/item_picker.ts @@ -1,12 +1,7 @@ import type { ItemPickerQueryResponse } from "@invokation/panorama-lib/custom_events"; import { CustomGameEvent } from "@invokation/panorama-lib/custom_events"; import type { Action } from "@invokation/panorama-lib/sequence"; -import { - AddClassAction, - ParallelSequence, - RemoveClassAction, - Sequence, -} from "@invokation/panorama-lib/sequence"; +import { AddClassAction, ParallelSequence, RemoveClassAction, Sequence } from "@invokation/panorama-lib/sequence"; import type { Elements, Outputs } from "../component"; import { Component } from "../component"; @@ -80,11 +75,11 @@ class ItemPicker extends Component const shopItem = this.shopItems.get(itemName); if (shopItem == null) { - throw new Error(`Could not find shop item panel for item ${itemName}`); + this.warn(`Could not find shop item panel for item ${itemName}`); } return shopItem; - }); + }).filter((panel) => panel != null); this.highlight(shopItems); } From b33a506a5d7692b1efc47f5ccc6540971c6b03f2 Mon Sep 17 00:00:00 2001 From: 13k Date: Tue, 2 Sep 2025 14:15:46 -0300 Subject: [PATCH 28/29] feat(vscripts): improve hero reset --- game/scripts/vscripts/invk/combo/hero.lua | 6 --- game/scripts/vscripts/invk/dota2/player.lua | 4 +- .../vscripts/invk/game_mode/game_events.lua | 7 ++- spec/combo/hero_spec.lua | 44 ------------------- 4 files changed, 7 insertions(+), 54 deletions(-) diff --git a/game/scripts/vscripts/invk/combo/hero.lua b/game/scripts/vscripts/invk/combo/hero.lua index 33affa2..cc5033c 100644 --- a/game/scripts/vscripts/invk/combo/hero.lua +++ b/game/scripts/vscripts/invk/combo/hero.lua @@ -47,12 +47,6 @@ function M.teardown(base_player, options) end if opts.hard_reset then - local invoker = Invoker:new(player.hero) - - unit:remove_items() - -- Orbs reset must come before hero replacement - invoker:reset_abilities() - unit:set_ability_points(1) player:replace_hero(player.hero:GetUnitName()) else unit:purge() diff --git a/game/scripts/vscripts/invk/dota2/player.lua b/game/scripts/vscripts/invk/dota2/player.lua index 8bdbc65..6c3a322 100644 --- a/game/scripts/vscripts/invk/dota2/player.lua +++ b/game/scripts/vscripts/invk/dota2/player.lua @@ -37,12 +37,12 @@ function M:replace_hero(hero_name, options) GameRules:SetSpeechUseSpawnInsteadOfRespawnConcept(true) - local hero = PlayerResource:ReplaceHeroWithNoTransfer(self.id, hero_name, gold, xp) --[[@as CDOTA_BaseNPC_Hero]] + PlayerResource:ReplaceHeroWithNoTransfer(self.id, hero_name, gold, xp) GameRules:SetSpeechUseSpawnInsteadOfRespawnConcept(false) self.hero:RemoveSelf() - self.hero = hero + self.hero = self.entity:GetAssignedHero() return self.hero end diff --git a/game/scripts/vscripts/invk/game_mode/game_events.lua b/game/scripts/vscripts/invk/game_mode/game_events.lua index cc3b7c3..8670dc9 100644 --- a/game/scripts/vscripts/invk/game_mode/game_events.lua +++ b/game/scripts/vscripts/invk/game_mode/game_events.lua @@ -193,14 +193,17 @@ end --- Called when an NPC has spawned somewhere in game, including heroes. --- @param payload dota2.events.npc_spawned function M:_on_npc_spawned(payload) - self:d("_on_npc_spawned", { payload = payload }) - -- if self._reentrant then -- return -- end local npc = EntIndexToHScript(payload.entindex) --[[@as CDOTA_BaseNPC?]] + self:d("_on_npc_spawned", { + payload = payload, + unit = npc and npc:GetUnitName() or "", + }) + if npc ~= nil and npc:IsRealHero() and not self._first_spawned then self._first_spawned = true self:on_hero_in_game(npc) diff --git a/spec/combo/hero_spec.lua b/spec/combo/hero_spec.lua index 154d41f..2a6ace1 100644 --- a/spec/combo/hero_spec.lua +++ b/spec/combo/hero_spec.lua @@ -267,50 +267,6 @@ describe("invk.combo.hero", function() mocks:reset("PlayerResource", "ReplaceHeroWithNoTransfer") end) - it("removes all hero's items", function() - local hero = F.dota_hero_invoker(nil, { items = { "item_shivas_guard", "item_refresher" } }) - local player = F.dota_player({ hero = hero }) - - combo_hero.teardown(player, { hard_reset = true }) - - assert.same({}, hero.inventory) - end) - - it("resets hero abilities", function() - local abilities = { - [AbilityName.QUAS] = 7, - [AbilityName.WEX] = 4, - [AbilityName.EXORT] = 6, - [AbilityName.COLD_SNAP] = 1, - [AbilityName.SUN_STRIKE] = 1, - [AbilityName.TALENT_L10_RIGHT] = 1, - [AbilityName.TALENT_L10_LEFT] = 0, - [AbilityName.TALENT_L15_RIGHT] = 1, - [AbilityName.TALENT_L15_LEFT] = 0, - [AbilityName.TALENT_L20_RIGHT] = 1, - [AbilityName.TALENT_L20_LEFT] = 0, - [AbilityName.TALENT_L25_RIGHT] = 1, - [AbilityName.TALENT_L25_LEFT] = 0, - } - - local hero = F.dota_hero_invoker(nil, { abilities = abilities }) - local player = F.dota_player({ hero = hero }) - - combo_hero.teardown(player, { hard_reset = true }) - - for _, name in ipairs(INVOKER.ORB_ABILITIES) do - assert.equal(0, dota2_h.require_ability(hero, name):GetLevel()) - end - - for _, name in ipairs(INVOKER.TALENT_ABILITIES) do - assert.equal(0, dota2_h.require_ability(hero, name):GetLevel()) - end - - assert.equal(1, dota2_h.require_ability(hero, AbilityName.COLD_SNAP):GetLevel()) - assert.equal(1, dota2_h.require_ability(hero, AbilityName.SUN_STRIKE):GetLevel()) - assert.equal(1, hero:GetAbilityPoints()) - end) - it("replaces hero with a new one", function() local hero = F.dota_hero_invoker() local player = F.dota_player({ player_id = 31, hero = hero }) From 843cbfa2a080324e51a68feee0a3114bf91503e5 Mon Sep 17 00:00:00 2001 From: 13k Date: Thu, 4 Sep 2025 18:46:30 -0300 Subject: [PATCH 29/29] chore: update bun lock --- bun.lockb | Bin 102200 -> 102200 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bun.lockb b/bun.lockb index bc67630f0e45e0a8140c37102dc814542f057e93..4865de708515170df652216ab2ec56e504aa3468 100755 GIT binary patch delta 31 ncmdlnk8Q_1wuUW?S@zS@>=<*VU$bZQWVX~Z+OFilDCQ3Uzm^J6 delta 40 wcmdlnk8Q_1wuUW?S@z7vdIr-O4H-?R&$DARnSRZl(UaLk&tSWf1EZKf01&ea+yDRo