Skip to content

Commit bd3d23c

Browse files
committed
Pull source files out of junctions
1 parent 782fa2e commit bd3d23c

19 files changed

+205
-16
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ node_modules
22

33
/content/panorama/scripts/custom_game/**/*.js
44
/game/scripts/vscripts/**/*.lua
5-
!/game/scripts/vscripts/lib/timers.lua
65

76
# Dota 2 stuff
87
*.bin

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ A template for Dota 2 Custom Games built with modern technologies. It includes
1515

1616
After that you can press `Ctrl+Shift+B` in VSCode or run `npm run dev` command in terminal to compile your code and watch for changes.
1717

18+
## Contents:
19+
20+
* **[src/vscripts]:** TypeScript code Dota addon (Lua) scripts. Compiles lua to game/scripts/vscripts.
21+
* **[src/panorama]:** TypeScript code for panorama UI
22+
1823
## Continuous Integration
1924

2025
This template includes a [GitHub Actions](https://github.com/features/actions) [workflow](.github/workflows/ci.yml) that builds your custom game on every commit and fails when there are type errors.

content/panorama/scripts/custom_game/hud.ts

-7
This file was deleted.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
"build:panorama": "tsc --project content/panorama/scripts/custom_game/tsconfig.json",
99
"build:vscripts": "tstl --project game/scripts/vscripts/tsconfig.json",
1010
"dev": "run-p dev:*",
11-
"dev:panorama": "tsc --project content/panorama/scripts/custom_game/tsconfig.json --watch",
12-
"dev:vscripts": "tstl --project game/scripts/vscripts/tsconfig.json --watch"
11+
"dev:panorama": "tsc --project src/panorama/tsconfig.json --watch",
12+
"dev:vscripts": "tstl --project src/vscripts/tsconfig.json --watch"
1313
},
1414
"devDependencies": {
1515
"@moddota/dota-lua-types": "^4.11.0",

src/common/events.d.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* This file contains types for the events you want to send between the UI (Panorama)
3+
* and the server (VScripts).
4+
*
5+
* IMPORTANT:
6+
*
7+
* The dota engine will change the type of event data slightly when it is sent, so on the
8+
* Panorama side your event handlers will have to handle NetworkedData<EventType>, changes are:
9+
* - Booleans are turned to 0 | 1
10+
* - Arrays are automatically translated to objects when sending them as event. You have
11+
* to change them back into arrays yourself! See 'toArray()' in src/panorama/hud.ts
12+
*/
13+
14+
// To declare an event for use, add it to this table with the type of its data
15+
interface CustomGameEventDeclarations {
16+
example_event: ExampleEventData
17+
}
18+
19+
// Define the type of data sent by the example_event event
20+
interface ExampleEventData {
21+
myNumber: number;
22+
myBoolean: boolean;
23+
myString: string[];
24+
myArrayOfNumbers: number[]
25+
}

src/common/general.d.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* This file contains some general types related to your game that can be shared between
3+
* front-end (Panorama) and back-end (VScripts). Only put stuff in here you need to share.
4+
*/
5+
6+
interface Color {
7+
r: number,
8+
g: number,
9+
b: number
10+
}
11+
12+
interface UnitData {
13+
name: string,
14+
level: number
15+
}

src/panorama/hud.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
$.Msg("Hud panorama loaded");
2+
3+
GameEvents.Subscribe("my_custom_event", event => {
4+
$.Msg("Received custom event", event);
5+
});
6+
7+
GameEvents.SendCustomGameEventToServer<{}>("ui_loaded", {});
8+
9+
GameEvents.Subscribe("example_event", (data: NetworkedData<ExampleEventData>) => {
10+
const myNumber = data.myNumber;
11+
const myString = data.myString;
12+
13+
const myBoolean = data.myBoolean; // After sending to client this is now type 0 | 1!
14+
15+
const myArrayObject = data.myArrayOfNumbers; // After sending this is now an object!
16+
17+
const myArray = toArray(myArrayObject); // We can turn it back into an array ourselves.
18+
19+
});
20+
21+
/**
22+
* Turn a table object into an array.
23+
* @param obj The object to transform to an array.
24+
* @returns An array with items of the value type of the original object.
25+
*/
26+
function toArray<T>(obj: Record<number, T>): T[] {
27+
const result = [];
28+
29+
let key = 1;
30+
while (obj[key]) {
31+
result.push(obj[key]);
32+
key++;
33+
}
34+
35+
return result;
36+
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
{
22
"compilerOptions": {
33
"rootDir": ".",
4+
"outDir": "../../content/panorama/scripts/custom_game",
45
"target": "es2017",
56
"lib": ["es2017"],
67
"types": ["@moddota/panorama-types"],
78
"moduleResolution": "node",
89
"strict": true
9-
}
10+
},
11+
"include": ["**/*.ts", "../common/**/*.ts"]
1012
}

game/scripts/vscripts/GameMode.ts renamed to src/vscripts/GameMode.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { reloadable } from "./lib/tstl-utils";
2-
import "./modifiers/modifier_panic";
2+
import { modifier_panic } from "./modifiers/modifier_panic";
33

4-
const heroSelectionTime = 10;
4+
const heroSelectionTime = 20;
55

66
declare global {
77
interface CDOTAGamerules {
@@ -17,6 +17,7 @@ export class GameMode {
1717
}
1818

1919
public static Activate(this: void) {
20+
// When the addon activates, create a new instance of this GameMode class.
2021
GameRules.Addon = new GameMode();
2122
}
2223

@@ -44,8 +45,17 @@ export class GameMode {
4445
}
4546
}
4647

48+
if (state === DOTA_GameState.DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP) {
49+
// Automatically skip setup in tools
50+
if (IsInToolsMode()) {
51+
Timers.CreateTimer(3, () => {
52+
GameRules.FinishCustomGameSetup();
53+
});
54+
}
55+
}
56+
4757
// Start game once pregame hits
48-
if (state == DOTA_GameState.DOTA_GAMERULES_STATE_PRE_GAME) {
58+
if (state === DOTA_GameState.DOTA_GAMERULES_STATE_PRE_GAME) {
4959
Timers.CreateTimer(0.2, () => this.StartGame());
5060
}
5161
}
@@ -68,7 +78,7 @@ export class GameMode {
6878
const unit = EntIndexToHScript(event.entindex) as CDOTA_BaseNPC; // Cast to npc since this is the 'npc_spawned' event
6979
if (unit.IsRealHero()) {
7080
Timers.CreateTimer(1, () => {
71-
unit.AddNewModifier(unit, undefined, "modifier_panic", { duration: 8 });
81+
unit.AddNewModifier(unit, undefined, modifier_panic.name, { duration: 8 });
7282
});
7383

7484
if (!unit.HasAbility("meepo_earthbind_ts_example")) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
2+
require("lualib_bundle");
3+
__TS__SourceMapTraceBack(debug.getinfo(1).short_src, {["5"] = 1,["6"] = 1,["7"] = 1,["8"] = 3,["9"] = 4,["10"] = 3,["11"] = 4,["12"] = 7,["13"] = 8,["14"] = 9,["15"] = 10,["16"] = 11,["17"] = 12,["20"] = 16,["21"] = 7,["22"] = 19,["23"] = 20,["24"] = 21,["26"] = 24,["27"] = 19,["28"] = 27,["29"] = 28,["30"] = 27,["31"] = 31,["32"] = 32,["33"] = 33,["34"] = 34,["35"] = 36,["36"] = 37,["37"] = 38,["38"] = 40,["39"] = 41,["40"] = 47,["41"] = 47,["42"] = 47,["43"] = 47,["44"] = 47,["45"] = 48,["46"] = 49,["47"] = 49,["48"] = 49,["49"] = 49,["50"] = 49,["51"] = 51,["52"] = 51,["53"] = 51,["54"] = 51,["55"] = 51,["56"] = 51,["57"] = 51,["58"] = 51,["59"] = 51,["60"] = 51,["61"] = 51,["62"] = 51,["63"] = 51,["64"] = 51,["65"] = 51,["66"] = 51,["67"] = 51,["68"] = 51,["69"] = 51,["70"] = 31,["71"] = 70,["72"] = 71,["73"] = 72,["74"] = 73,["75"] = 75,["76"] = 75,["77"] = 75,["78"] = 75,["79"] = 75,["80"] = 75,["81"] = 75,["82"] = 75,["83"] = 75,["84"] = 75,["85"] = 75,["86"] = 87,["87"] = 88,["88"] = 89,["90"] = 92,["91"] = 93,["92"] = 95,["93"] = 70,["94"] = 4,["96"] = 3,["98"] = 4});
4+
local ____exports = {}
5+
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
6+
local BaseAbility = ____dota_ts_adapter.BaseAbility
7+
local registerAbility = ____dota_ts_adapter.registerAbility
8+
____exports.meepo_earthbind_ts_example = __TS__Class()
9+
local meepo_earthbind_ts_example = ____exports.meepo_earthbind_ts_example
10+
meepo_earthbind_ts_example.name = "meepo_earthbind_ts_example"
11+
__TS__ClassExtends(meepo_earthbind_ts_example, BaseAbility)
12+
function meepo_earthbind_ts_example.prototype.GetCooldown(self)
13+
local cooldown = self:GetSpecialValueFor("cooldown")
14+
if IsServer() then
15+
local talent = self:GetCaster():FindAbilityByName("special_bonus_unique_meepo_3")
16+
if talent then
17+
cooldown = cooldown - talent:GetSpecialValueFor("value")
18+
end
19+
end
20+
return cooldown
21+
end
22+
function meepo_earthbind_ts_example.prototype.OnAbilityPhaseStart(self)
23+
if IsServer() then
24+
self:GetCaster():EmitSound("Hero_Meepo.Earthbind.Cast")
25+
end
26+
return true
27+
end
28+
function meepo_earthbind_ts_example.prototype.OnAbilityPhaseInterrupted(self)
29+
self:GetCaster():StopSound("Hero_Meepo.Earthbind.Cast")
30+
end
31+
function meepo_earthbind_ts_example.prototype.OnSpellStart(self)
32+
local caster = self:GetCaster()
33+
local point = self:GetCursorPosition()
34+
local projectileSpeed = self:GetSpecialValueFor("speed")
35+
local direction = (point - caster:GetAbsOrigin()):Normalized()
36+
direction.z = 0
37+
local distance = (point - caster:GetAbsOrigin()):Length()
38+
local radius = self:GetSpecialValueFor("radius")
39+
self.particle = ParticleManager:CreateParticle("particles/units/heroes/hero_meepo/meepo_earthbind_projectile_fx.vpcf", PATTACH_CUSTOMORIGIN, caster)
40+
ParticleManager:SetParticleControl(
41+
self.particle,
42+
0,
43+
caster:GetAbsOrigin()
44+
)
45+
ParticleManager:SetParticleControl(self.particle, 1, point)
46+
ParticleManager:SetParticleControl(
47+
self.particle,
48+
2,
49+
Vector(projectileSpeed, 0, 0)
50+
)
51+
ProjectileManager:CreateLinearProjectile(
52+
{
53+
Ability = self,
54+
EffectName = "",
55+
vSpawnOrigin = caster:GetAbsOrigin(),
56+
fDistance = distance,
57+
fStartRadius = radius,
58+
fEndRadius = radius,
59+
Source = caster,
60+
bHasFrontalCone = false,
61+
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_NONE,
62+
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
63+
iUnitTargetType = DOTA_UNIT_TARGET_NONE,
64+
vVelocity = direction * projectileSpeed,
65+
bProvidesVision = true,
66+
iVisionRadius = radius,
67+
iVisionTeamNumber = caster:GetTeamNumber()
68+
}
69+
)
70+
end
71+
function meepo_earthbind_ts_example.prototype.OnProjectileHit(self, _target, location)
72+
local caster = self:GetCaster()
73+
local duration = self:GetSpecialValueFor("duration")
74+
local radius = self:GetSpecialValueFor("radius")
75+
local units = FindUnitsInRadius(
76+
caster:GetTeamNumber(),
77+
location,
78+
nil,
79+
radius,
80+
DOTA_UNIT_TARGET_TEAM_ENEMY,
81+
bit.bor(DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_HERO),
82+
DOTA_UNIT_TARGET_FLAG_NONE,
83+
0,
84+
false
85+
)
86+
for ____, unit in ipairs(units) do
87+
unit:AddNewModifier(caster, self, "modifier_meepo_earthbind", {duration = duration})
88+
unit:EmitSound("Hero_Meepo.Earthbind.Target")
89+
end
90+
ParticleManager:DestroyParticle(self.particle, false)
91+
ParticleManager:ReleaseParticleIndex(self.particle)
92+
return true
93+
end
94+
meepo_earthbind_ts_example = __TS__Decorate(
95+
{
96+
registerAbility(nil)
97+
},
98+
meepo_earthbind_ts_example
99+
)
100+
return ____exports
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import "./lib/timers";
22
import { GameMode } from "./GameMode";
33

4+
// Connect GameMode.Activate and GameMode.Precache to the dota engine
45
Object.assign(getfenv(), {
56
Activate: GameMode.Activate,
67
Precache: GameMode.Precache,
78
});
89

910
if (GameRules.Addon) {
11+
// This code is only run after script_reload, not at startup
1012
GameRules.Addon.Reload();
1113
}
File renamed without changes.
File renamed without changes.

game/scripts/vscripts/tsconfig.json renamed to src/vscripts/tsconfig.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"compilerOptions": {
33
"rootDir": ".",
4+
"outDir": "../../game/scripts/vscripts",
45
"target": "esnext",
56
"lib": ["esnext"],
67
"types": ["@moddota/dota-lua-types"],
@@ -12,5 +13,6 @@
1213
"tstl": {
1314
"luaTarget": "JIT",
1415
"sourceMapTraceback": true
15-
}
16+
},
17+
"include": ["**/*.ts", "../common/**/*.ts"]
1618
}

0 commit comments

Comments
 (0)