Skip to content

Commit 55c26e1

Browse files
authored
Merge pull request #1 from ModDota/use-dota-lua-types
Use `dota-lua-types`
2 parents fd10e62 + 64d6e1b commit 55c26e1

15 files changed

Lines changed: 224 additions & 86 deletions

File tree

.github/workflows/ci.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ jobs:
99

1010
steps:
1111
- uses: actions/checkout@v2
12-
- name: Checkout Submodules
13-
run: git submodule update --init --recursive
1412
- name: Use Node.js 12
1513
uses: actions/setup-node@v1
1614
with:

.gitmodules

Lines changed: 0 additions & 3 deletions
This file was deleted.

content/panorama/scripts/custom_game/hud.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ GameEvents.Subscribe("my_custom_event", event => {
44
$.Msg("Received custom event", event);
55
});
66

7-
GameEvents.SendCustomGameEventToServer("ui_loaded", {});
7+
GameEvents.SendCustomGameEventToServer<{}>("ui_loaded", {});

content/panorama/scripts/custom_game/manifest.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,5 @@ GameUI.SetDefaultUIEnabled(DotaDefaultUIElement_t.DOTA_DEFAULT_UI_FLYOUT_SCOREBO
66
GameUI.SetDefaultUIEnabled(DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_BAR_BACKGROUND, false);
77
GameUI.SetDefaultUIEnabled(DotaDefaultUIElement_t.DOTA_DEFAULT_UI_TOP_HEROES, false);
88

9-
const hudRoot = $.GetContextPanel()
10-
.GetParent()!
11-
.GetParent()!;
9+
const hudRoot = $.GetContextPanel().GetParent()!.GetParent()!;
1210
hudRoot.FindChildTraverse("quickstats")!.style.visibility = "collapse";
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
{
22
"compilerOptions": {
3+
"rootDir": ".",
34
"target": "es2017",
45
"lib": ["es2017"],
56
"types": ["panorama-types"],
7+
"moduleResolution": "node",
68
"strict": true
79
}
810
}

game/scripts/declarations

Lines changed: 0 additions & 1 deletion
This file was deleted.

game/scripts/vscripts/GameMode.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { reloadable } from "./lib/dota_ts_adapter";
2-
3-
LinkLuaModifier("modifier_panic", "modifiers/modifier_panic.lua", LuaModifierType.LUA_MODIFIER_MOTION_NONE);
1+
import { reloadable } from "./lib/tstl-utils";
2+
import "./modifiers/modifier_panic";
43

54
const heroSelectionTime = 10;
65

76
declare global {
8-
class CDOTAGamerules {
7+
interface CDOTAGamerules {
98
Addon: GameMode;
109
}
1110
}
@@ -69,7 +68,7 @@ export class GameMode {
6968
const unit = EntIndexToHScript(event.entindex) as CDOTA_BaseNPC; // Cast to npc since this is the 'npc_spawned' event
7069
if (unit.IsRealHero()) {
7170
Timers.CreateTimer(1, () => {
72-
unit.AddNewModifier(undefined, undefined, "modifier_panic", { duration: 8 });
71+
unit.AddNewModifier(unit, undefined, "modifier_panic", { duration: 8 });
7372
});
7473

7574
if (!unit.HasAbility("meepo_earthbind_ts_example")) {

game/scripts/vscripts/abilities/heroes/meepo/earthbind_ts_example.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { luaAbility } from "../../../lib/dota_ts_adapter";
1+
import { BaseAbility, registerAbility } from "../../../lib/dota_ts_adapter";
22

3-
@luaAbility
4-
class meepo_earthbind_ts_example extends CDOTA_Ability_Lua {
3+
@registerAbility()
4+
export class meepo_earthbind_ts_example extends BaseAbility {
55
particle?: ParticleID;
66

77
GetCooldown() {
@@ -57,11 +57,9 @@ class meepo_earthbind_ts_example extends CDOTA_Ability_Lua {
5757
fEndRadius: radius,
5858
Source: caster,
5959
bHasFrontalCone: false,
60-
bReplaceExisting: false,
6160
iUnitTargetTeam: DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_NONE,
6261
iUnitTargetFlags: DOTA_UNIT_TARGET_FLAGS.DOTA_UNIT_TARGET_FLAG_NONE,
6362
iUnitTargetType: DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_NONE,
64-
bDeleteOnHit: false,
6563
vVelocity: (direction * projectileSpeed) as Vector,
6664
bProvidesVision: true,
6765
iVisionRadius: radius,
@@ -77,7 +75,7 @@ class meepo_earthbind_ts_example extends CDOTA_Ability_Lua {
7775
const units = FindUnitsInRadius(
7876
caster.GetTeamNumber(),
7977
location,
80-
null,
78+
undefined,
8179
radius,
8280
DOTA_UNIT_TARGET_TEAM.DOTA_UNIT_TARGET_TEAM_ENEMY,
8381
DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_BASIC | DOTA_UNIT_TARGET_TYPE.DOTA_UNIT_TARGET_HERO,

game/scripts/vscripts/addon_game_mode.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
// Temporary workaround for https://github.com/microsoft/TypeScript/issues/35973
2-
// @ts-ignore
31
import "./lib/timers";
42
import { GameMode } from "./GameMode";
53

6-
Object.assign(getfenv(1), {
4+
Object.assign(getfenv(), {
75
Activate: GameMode.Activate,
86
Precache: GameMode.Precache,
97
});
Lines changed: 111 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,129 @@
1-
const global = globalThis as typeof globalThis & { reloadCache: Record<string, any> };
2-
if (global.reloadCache === undefined) {
3-
global.reloadCache = {};
1+
export interface BaseAbility extends CDOTA_Ability_Lua {}
2+
export class BaseAbility {}
3+
4+
export interface BaseItem extends CDOTA_Item_Lua {}
5+
export class BaseItem {}
6+
7+
export interface BaseModifier extends CDOTA_Modifier_Lua {}
8+
export class BaseModifier {
9+
public static apply<T extends typeof BaseModifier>(
10+
this: T,
11+
target: CDOTA_BaseNPC,
12+
caster?: CDOTA_BaseNPC,
13+
ability?: CDOTABaseAbility,
14+
modifierTable?: object,
15+
): InstanceType<T> {
16+
return target.AddNewModifier(caster, ability, this.name, modifierTable) as any;
17+
}
418
}
519

6-
export function reloadable<T extends { new (...args: any[]): {} }>(constructor: T): T {
7-
const className = constructor.name;
8-
if (global.reloadCache[className] === undefined) {
9-
global.reloadCache[className] = constructor;
20+
export interface BaseModifierMotionHorizontal extends CDOTA_Modifier_Lua_Horizontal_Motion {}
21+
export class BaseModifierMotionHorizontal extends BaseModifier {}
22+
23+
export interface BaseModifierMotionVertical extends CDOTA_Modifier_Lua_Vertical_Motion {}
24+
export class BaseModifierMotionVertical extends BaseModifier {}
25+
26+
export interface BaseModifierMotionBoth extends CDOTA_Modifier_Lua_Motion_Both {}
27+
export class BaseModifierMotionBoth extends BaseModifier {}
28+
29+
export const registerAbility = (name?: string) => (ability: new () => CDOTA_Ability_Lua | CDOTA_Item_Lua) => {
30+
if (name !== undefined) {
31+
// @ts-ignore
32+
ability.name = name;
33+
} else {
34+
name = ability.name;
35+
}
36+
37+
const [env] = getFileScope();
38+
39+
if (env[name]) {
40+
clearTable(env[name]);
41+
} else {
42+
env[name] = {};
43+
}
44+
45+
toDotaClassInstance(env[name], ability);
46+
47+
const originalSpawn = env[name].Spawn;
48+
env[name].Spawn = function () {
49+
this.____constructor();
50+
if (originalSpawn) {
51+
originalSpawn.call(this);
52+
}
53+
};
54+
};
55+
56+
export const registerModifier = (name?: string) => (modifier: new () => CDOTA_Modifier_Lua) => {
57+
if (name !== undefined) {
58+
// @ts-ignore
59+
modifier.name = name;
60+
} else {
61+
name = modifier.name;
62+
}
63+
64+
const [env, source] = getFileScope();
65+
const [fileName] = string.gsub(source, ".*scripts[\\/]vscripts[\\/]", "");
66+
67+
if (env[name]) {
68+
clearTable(env[name]);
69+
} else {
70+
env[name] = {};
1071
}
1172

12-
Object.assign(global.reloadCache[className].prototype, constructor.prototype);
13-
return global.reloadCache[className];
73+
toDotaClassInstance(env[name], modifier);
74+
75+
const originalOnCreated = env[name].OnCreated;
76+
env[name].OnCreated = function (parameters: any) {
77+
this.____constructor();
78+
if (originalOnCreated) {
79+
originalOnCreated.call(this, parameters);
80+
}
81+
};
82+
83+
let type = LuaModifierType.LUA_MODIFIER_MOTION_NONE;
84+
let base = (modifier as any).____super;
85+
while (base && type === undefined) {
86+
if (base === BaseModifierMotionBoth) {
87+
type = LuaModifierType.LUA_MODIFIER_MOTION_BOTH;
88+
} else if (base === BaseModifierMotionHorizontal) {
89+
type = LuaModifierType.LUA_MODIFIER_MOTION_HORIZONTAL;
90+
} else if (base === BaseModifierMotionVertical) {
91+
type = LuaModifierType.LUA_MODIFIER_MOTION_VERTICAL;
92+
}
93+
94+
base = base.____super;
95+
}
96+
97+
LinkLuaModifier(name, fileName, type);
98+
};
99+
100+
function clearTable(table: object) {
101+
for (const key in table) {
102+
delete (table as any)[key];
103+
}
14104
}
15105

16-
export function luaModifier<T extends typeof CDOTA_Modifier_Lua>(modifier: T): T {
17-
const instance: any = {};
18-
let prototype = modifier.prototype as any;
19-
while (prototype) {
20-
for (const key in prototype) {
21-
if (instance[key] === undefined) {
22-
instance[key] = prototype[key];
23-
}
106+
function getFileScope(): [any, string] {
107+
let level = 1;
108+
while (true) {
109+
const info = debug.getinfo(level, "S");
110+
if (info && info.what === "main") {
111+
return [getfenv(level), info.source!];
24112
}
25-
prototype = getmetatable(prototype);
113+
114+
level += 1;
26115
}
27-
getfenv(1)[modifier.name] = instance;
28-
return instance;
29116
}
30117

31-
export function luaAbility<T extends typeof CDOTA_Ability_Lua>(ability: T): T {
32-
const instance: any = {};
33-
let prototype = ability.prototype as any;
118+
function toDotaClassInstance(instance: any, table: new () => any) {
119+
let { prototype } = table;
34120
while (prototype) {
35121
for (const key in prototype) {
36-
if (instance[key] === undefined) {
122+
if (instance[key] == null) {
37123
instance[key] = prototype[key];
38124
}
39125
}
126+
40127
prototype = getmetatable(prototype);
41128
}
42-
getfenv(1)[ability.name] = instance;
43-
return instance;
44129
}

0 commit comments

Comments
 (0)