Skip to content

Instantly share code, notes, and snippets.

@ark120202
Last active January 17, 2020 10:18
Show Gist options
  • Save ark120202/f9ccd1076887664e8e8cb7e7d78fd7d1 to your computer and use it in GitHub Desktop.
Save ark120202/f9ccd1076887664e8e8cb7e7d78fd7d1 to your computer and use it in GitHub Desktop.
export interface BaseAbility extends CDOTA_Ability_Lua {}
export class BaseAbility {}
export interface BaseItem extends CDOTA_Item_Lua {}
export class BaseItem {}
export interface BaseModifier extends CDOTA_Modifier_Lua {}
export class BaseModifier {
public static apply<T extends typeof BaseModifier>(
this: T,
target: CDOTA_BaseNPC,
caster?: CDOTA_BaseNPC,
ability?: CDOTABaseAbility,
modifierTable?: object,
): InstanceType<T> {
return target.AddNewModifier(caster, ability, this.name, modifierTable) as any;
}
}
export const registerAbility = (name: string) => (ability: new () => CDOTA_Ability_Lua | CDOTA_Item_Lua) => {
const [env] = getFileScope();
if (env[name]) {
clearTable(env[name]);
} else {
env[name] = {};
}
toDotaClassInstance(env[name], ability);
const originalSpawn = env[name].Spawn;
env[name].Spawn = function() {
this.____constructor();
if (originalSpawn) {
originalSpawn.call(this);
}
};
};
export const registerModifier = (name: string, type = LuaModifierType.LUA_MODIFIER_MOTION_NONE) => (
modifier: new () => CDOTA_Modifier_Lua,
) => {
(modifier as any).name = name;
const [env, source] = getFileScope();
const [fileName] = string.gsub(source, ".*scripts[\\/]vscripts[\\/]", "");
if (env[name]) {
clearTable(env[name]);
} else {
env[name] = {};
}
toDotaClassInstance(env[name], modifier);
const originalOnCreated = env[name].OnCreated;
env[name].OnCreated = function(parameters: any) {
this.____constructor();
if (originalOnCreated) {
originalOnCreated.call(this, parameters);
}
};
LinkLuaModifier(name, fileName, type);
};
function clearTable(table: object) {
for (const key in table) {
delete (table as any)[key];
}
}
function getFileScope(): [any, string] {
let level = 1;
while (true) {
const info = debug.getinfo(level, "S");
if (info && info.what === "main") {
return [getfenv(level), info.source!];
}
level += 1;
}
}
function toDotaClassInstance(instance: any, table: new () => any) {
let { prototype } = table;
while (prototype) {
for (const key in prototype) {
if (instance[key] == null) {
instance[key] = prototype[key];
}
}
prototype = getmetatable(prototype);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment