Compare commits

..

No commits in common. "main" and "spritesheet" have entirely different histories.

80 changed files with 383 additions and 539 deletions

View File

@ -26,7 +26,8 @@ List of things to implement following the "release" of the minimum viable produc
## Other
- [ ] Disable player action during combat phase.
- [ ] Add sound effects
- [x] Tutorial image/mission
- [x] Pause menu
- [ ] Pause menu
- [x] Score screen when winning/losing map

View File

@ -4,19 +4,8 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Bastion: The Watchers Lament</title>
<meta property="og:title" content="Bastion: The Watchers Lament" />
<meta
property="og:description"
content="A free, open source, browser based, tower defense game inspired by GemCraft: Frostborn Wrath. Playable NOW on PC!"
/>
<meta property="og:image" content="https://bastion.overflow.fun/favicon.png" />
<meta property="og:url" content="https://bastion.overflow.fun" />
<meta name="twitter:title" content="Bastion: The Watchers Lament" />
<meta
name="twitter:description"
content="A free, open source, browser based, tower defense game inspired by GemCraft: Frostborn Wrath. Playable NOW on PC!"
/>
<link href="https://fonts.googleapis.com/css?family=Aclonica" rel="stylesheet" />
<title>Bastion: The Watcher's Lament</title>
</head>
<body>
<script type="module" src="/src/main.ts"></script>

BIN
public/aclonica.woff2 Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

BIN
public/assets/gui/banner_03.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
public/assets/gui/frame_c2_02.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
public/assets/gui/gem_frame.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

BIN
public/assets/gui/inventory.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 KiB

BIN
public/assets/gui/plank_14.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/assets/gui/shield_01.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/assets/gui/shield_02.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

BIN
public/assets/gui/skull_01.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/assets/gui/star.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
public/assets/gui/star_empty.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
public/assets/gui/title.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

View File

@ -2,15 +2,14 @@
{
"name": "basic",
"sprite": "wood",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 12,
"stats": {
"health": 2,
"speed": 3,
"health": 5,
"speed": 4,
"special": null,
"resistance": {
"physical": 0.05,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
@ -21,12 +20,11 @@
{
"name": "quick",
"sprite": "zombie",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 8,
"stats": {
"health": 1,
"speed": 5,
"health": 2,
"speed": 6,
"special": null,
"resistance": {
"physical": 0,
@ -40,11 +38,10 @@
{
"name": "tank",
"sprite": "skeleton",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 12,
"stats": {
"health": 5,
"health": 12,
"speed": 2,
"special": null,
"resistance": {
@ -59,50 +56,29 @@
{
"name": "cloaker",
"sprite": "hood",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 12,
"stats": {
"health": 7,
"speed": 3,
"health": 12,
"speed": 2,
"special": null,
"resistance": {
"physical": 0,
"divine": 1,
"fire": 1,
"ice": 1,
"frostfire": 1
"divine": 0,
"fire": 0,
"ice": 0,
"frostfire": 0
}
}
},
{
"name": "demon",
"sprite": "demon",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 8,
"stats": {
"health": 5,
"speed": 3,
"special": null,
"resistance": {
"physical": 1,
"divine": -0.25,
"fire": 1,
"ice": 1,
"frostfire": 1
}
}
},
{
"name": "maker",
"sprite": "pumpkin",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 11,
"stats": {
"health": 5,
"speed": 3,
"health": 12,
"speed": 2,
"special": null,
"resistance": {
"physical": 0,
@ -113,57 +89,17 @@
}
}
},
{
"name": "monster",
"sprite": "green",
"tint": "0xffffff",
"name": "maker",
"sprite": "pumpkin",
"textures": [],
"textureArrayLength": 12,
"textureArrayLength": 11,
"stats": {
"health": 30,
"speed": 1,
"health": 11,
"speed": 2,
"special": null,
"resistance": {
"physical": 0.05,
"divine": 0.05,
"fire": -0.25,
"ice": 0.05,
"frostfire": 0.05
}
}
},
{
"name": "remaker",
"sprite": "orange",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 12,
"stats": {
"health": 2,
"speed": 3,
"special": null,
"resistance": {
"physical": 0.05,
"divine": 0,
"fire": 0,
"ice": 0,
"frostfire": 0
}
}
},
{
"name": "elite",
"sprite": "phood",
"tint": "0xffffff",
"textures": [],
"textureArrayLength": 12,
"stats": {
"health": 2,
"speed": 3,
"special": null,
"resistance": {
"physical": 0.05,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,

View File

@ -1,14 +1,14 @@
[
{
"name": "Fire Gem",
"description": "Forged from molten lava, the Fire Gem imbues your tower's attacks and add extra fire damage. Well researched and common.",
"description": "Forged from molten lava, the Fire Gem imbues your tower's attacks and add extra fire damage. It can be merged with any gem and is common.",
"color": "red",
"type": "Fire",
"totalLevels": 9,
"textures": [],
"cantCombineWith": [],
"specialCombine": [],
"initialGemValue": 75,
"initialGemValue": 50,
"genericImprovements": [
{
"damageUp": 1,
@ -16,6 +16,14 @@
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 50
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 100
},
{
@ -24,15 +32,7 @@
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 150
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 2,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 250
"gemValueUp": 100
},
{
"damageUp": 2,
@ -40,31 +40,7 @@
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 400
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 650
},
{
"damageUp": 2,
"attackSpeedUp": 100,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 750
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 900
"gemValueUp": 100
},
{
"damageUp": 2,
@ -72,25 +48,42 @@
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 1000
"gemValueUp": 100
},
{
"damageUp": 2,
"attackSpeedUp": 250,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 1200
"gemValueUp": 100
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 100
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 100
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 100
}
],
"gemResistanceModifications": [
{
"physical": 0,
"divine": 0,
"fire": 0.05,
"ice": 0,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
@ -101,14 +94,7 @@
{
"physical": 0,
"divine": 0,
"fire": 0.15,
"ice": 0,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0.2,
"fire": 0.25,
"ice": 0,
"frostfire": 0
},
@ -129,7 +115,14 @@
{
"physical": 0,
"divine": 0,
"fire": 0.35,
"fire": 0.3,
"ice": 0,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0.3,
"ice": 0,
"frostfire": 0
},
@ -146,93 +139,93 @@
"fire": 0.45,
"ice": 0,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0.5,
"ice": 0,
"frostfire": 0
}
]
},
{
"name": "Yeti Gem",
"description": "Crafted from the essence of the frozen bears, the Yeti Gem enhances your tower's attacks with the chilling power of ice. It gives ice damage and is known for its rarity.",
"description": "Yeti gem description. Something something, write this while drunk or something.",
"color": "#32e4fc",
"type": "Yeti",
"totalLevels": 8,
"textures": [],
"cantCombineWith": [],
"specialCombine": [],
"initialGemValue": 80,
"initialGemValue": 10,
"genericImprovements": [
{
"damageUp": 1,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 100
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 150
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 2,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 250
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 400
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 650
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 750
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 900
},
{
"damageUp": 2,
"attackSpeedUp": 100,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 1000
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
}
],
"gemResistanceModifications": [
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.05,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
@ -240,13 +233,6 @@
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.15,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
@ -258,98 +244,112 @@
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.25,
"frostfire": 0.1
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.3,
"frostfire": 0.1
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.35,
"frostfire": 0.2
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.4,
"frostfire": 0.25
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0.2,
"frostfire": 0
}
]
},
{
"name": "Titalium Gem",
"description": "Created from distilled creep eyes, the Titalium gem is known for boosting tower range, at the sacrifice for other stats.",
"description": "Titalium gem description. Something something zombie creeps working for you something something.",
"color": "pink",
"type": "Titalium",
"totalLevels": 7,
"textures": [],
"cantCombineWith": [],
"specialCombine": [],
"initialGemValue": 100,
"initialGemValue": 10,
"genericImprovements": [
{
"damageUp": 1,
"attackSpeedUp": 0,
"rangeUp": 1,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 200
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 1,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 350
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 1,
"timeToLiveUp": 0,
"pierceUp": 2,
"gemValueUp": 450
},
{
"damageUp": 2,
"attackSpeedUp": 200,
"rangeUp": 1,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 600
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 1,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 850
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 900
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 0,
"rangeUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 900
"pierceUp": 1,
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
}
],
"gemResistanceModifications": [
@ -357,190 +357,191 @@
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0.05,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0.1,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0.1,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0.15,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0.2,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0.25,
"physical": 0,
"divine": 0,
"fire": 0,
"ice": 0,
"frostfire": 0
},
{
"physical": 0.3,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
}
]
},
{
"name": "Soulforge Gem",
"description": "Made from the wandering souls of the damned, the Soulforge gem accelerates your towers cooldowns and acts as a repellant for all things unholy.",
"description": "Soulforge gem description, have to write later.",
"color": "gray",
"type": "Soulforge",
"totalLevels": 7,
"totalLevels": 2,
"textures": [],
"cantCombineWith": [],
"specialCombine": [],
"initialGemValue": 150,
"initialGemValue": 10,
"genericImprovements": [
{
"damageUp": 0,
"attackSpeedUp": 100,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 200
},
{
"damageUp": 0,
"attackSpeedUp": 100,
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 350
"gemValueUp": 0
},
{
"damageUp": 0,
"attackSpeedUp": 150,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 450
},
{
"damageUp": 0,
"attackSpeedUp": 100,
"rangeUp": 1,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 600
},
{
"damageUp": 0,
"attackSpeedUp": 250,
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 850
"gemValueUp": 10
},
{
"damageUp": 0,
"attackSpeedUp": 400,
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 900
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 0,
"attackSpeedUp": 500,
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 0,
"gemValueUp": 900
"pierceUp": 1,
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
}
],
"gemResistanceModifications": [
{
"physical": 0,
"divine": 0.2,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.3,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.4,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.5,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.6,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.7,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.75,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.1,
"frostfire": 0
},
{
"physical": 0,
"divine": 0.8,
"divine": 0,
"fire": 0,
"ice": 0,
"ice": 0.2,
"frostfire": 0
}
]
},
{
"name": "Golden Gem",
"description": "An inherently useless gem, providing no tower buffs, but high in monetary value. Highly sought after by all rich people.",
"description": "An inherently useless gem, but high monetary value. Perhaps someone would pay a lot for this.",
"color": "gold",
"type": "Gold",
"totalLevels": 1,
@ -570,21 +571,21 @@
},
{
"name": "Artifact",
"description": "An insanely rare gem of unknown origin, packed with power. No one knows how it works, yet your towers oddly resonate stronger with it.",
"description": "A wildly rare gem, packed with power. No monetary value, yet your towers oddly resonate stronger with it.",
"color": "blue",
"type": "Artifact",
"totalLevels": 1,
"textures": [],
"cantCombineWith": [],
"specialCombine": [],
"initialGemValue": 1000,
"initialGemValue": 0,
"genericImprovements": [
{
"damageUp": 10,
"attackSpeedUp": 100,
"rangeUp": 2,
"timeToLiveUp": 200,
"pierceUp": 3,
"pierceUp": 20,
"gemValueUp": 0
}
],

View File

@ -9,13 +9,13 @@
"projectileTexturesArrayLength": 5,
"description": "The building block of society, nothing more basic exists.",
"stats": {
"damage": 1,
"damage": 2,
"cooldown": 1500,
"gemSlotsAmount": 1,
"cost": 25,
"cost": 50,
"range": 3,
"timeToLive": 20,
"pierce": 1
"pierce": 2
}
},
{
@ -26,15 +26,15 @@
"projectile": "blue",
"projectileTextures": [],
"projectileTexturesArrayLength": 4,
"description": "Shoots 8 projectiles in a circle, they may miss.",
"description": "If you feel a little circular.",
"stats": {
"damage": 1,
"cooldown": 2000,
"damage": 3,
"cooldown": 4000,
"gemSlotsAmount": 2,
"cost": 55,
"range": 3,
"timeToLive": 18,
"pierce": 5
"cost": 100,
"range": 2.5,
"timeToLive": 12,
"pierce": 30
}
},
{
@ -45,15 +45,15 @@
"projectile": "yellow",
"projectileTextures": [],
"projectileTexturesArrayLength": 4,
"description": "Zap zap zap! This towers shots connect to other enemies!",
"description": "Zap zap zap!",
"stats": {
"damage": 2,
"damage": 3,
"cooldown": 3500,
"gemSlotsAmount": 2,
"cost": 110,
"cost": 150,
"range": 3,
"timeToLive": 12,
"pierce": 1
"pierce": 10
}
},
{
@ -64,13 +64,13 @@
"projectile": "blue",
"projectileTextures": [],
"projectileTexturesArrayLength": 4,
"description": "Doesn't shoot, instead buffs other towers with some of its power.",
"description": "Doesn't shoot, instead buffs other towers with 50% of its power.",
"stats": {
"damage": 3,
"damage": 4,
"cooldown": 1000,
"gemSlotsAmount": 3,
"cost": 200,
"range": 2.5,
"range": 2,
"timeToLive": 15,
"pierce": 5
}
@ -83,15 +83,15 @@
"projectile": "white",
"projectileTextures": [],
"projectileTexturesArrayLength": 5,
"description": "Behaves like the Basic Tower, only its shots stop creeps in their tracks!",
"description": "Like a regular tower, just slows down creeps.",
"stats": {
"damage": 2,
"cooldown": 2200,
"gemSlotsAmount": 2,
"cost": 80,
"range": 3.25,
"cooldown": 2000,
"gemSlotsAmount": 3,
"cost": 125,
"range": 2.5,
"timeToLive": 12,
"pierce": 2
"pierce": 1
}
},
{
@ -104,13 +104,13 @@
"projectileTexturesArrayLength": 4,
"description": "Shoots a quick, high pierce rail projectile at creeps.",
"stats": {
"damage": 5,
"cooldown": 5020,
"damage": 2,
"cooldown": 2000,
"gemSlotsAmount": 3,
"cost": 134,
"cost": 125,
"range": 2.5,
"timeToLive": 12,
"pierce": 10
"pierce": 30
}
},
{
@ -121,15 +121,15 @@
"projectile": "stone",
"projectileTextures": [],
"projectileTexturesArrayLength": 1,
"description": "Randomly places expiring traps on the track, instead of attacking creeps.",
"description": "Randomly places traps on the track, instead of attacking creeps.",
"stats": {
"damage": 2,
"cooldown": 2000,
"gemSlotsAmount": 3,
"cost": 150,
"range": 3,
"cost": 125,
"range": 2.5,
"timeToLive": 400,
"pierce": 3
"pierce": 2
}
},
{
@ -143,12 +143,12 @@
"description": "On top of a regular attack, this tower gives creeps a debuff, making them take more damage.",
"stats": {
"damage": 2,
"cooldown": 1750,
"cooldown": 2000,
"gemSlotsAmount": 3,
"cost": 200,
"cost": 125,
"range": 2.5,
"timeToLive": 12,
"pierce": 2
"pierce": 30
}
}
]

View File

@ -62,30 +62,15 @@
{
"firstCreepSpawnTick": 500,
"spawnIntervalTicks": 1000,
"creeps": [0, 0, 0, 0, 0]
"creeps": [0, 0, 0]
},
{
"firstCreepSpawnTick": 4000,
"spawnIntervalTicks": 1000,
"creeps": [0, 0, 0, 0, 0]
"creeps": [0, 0, 0, 0]
}
],
"offeredGems": [0, 1, 0, 1]
},
{
"waves": [
{
"firstCreepSpawnTick": 500,
"spawnIntervalTicks": 1000,
"creeps": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
{
"firstCreepSpawnTick": 1000,
"spawnIntervalTicks": 1000,
"creeps": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
],
"offeredGems": [0, 1, 0, 1]
"offeredGems": [0, 1]
}
]
}

View File

@ -99,7 +99,7 @@
{
"firstCreepSpawnTick": 500,
"spawnIntervalTicks": 500,
"creeps": [0]
"creeps": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2]
}
],
"offeredGems": [0, 0, 0, 0]

View File

@ -10,13 +10,17 @@ export default class GameAssets {
public static Frame03Texture: PIXI.Texture;
public static Frame04Texture: PIXI.Texture;
public static Frame05Texture: PIXI.Texture;
public static FrameInventory: PIXI.Texture;
public static FrameBackground: PIXI.Texture;
public static FrameTowerTab: PIXI.Texture;
public static VioletBackground: PIXI.Texture;
public static RedBackground: PIXI.Texture;
public static GreenBackground: PIXI.Texture;
public static BlueBackground: PIXI.Texture;
public static YellowBackground: PIXI.Texture;
public static Button01Texture: PIXI.Texture;
public static Button02Texture: PIXI.Texture;
public static ButtonSmallTexture: PIXI.Texture;
public static HealthTexture: PIXI.Texture;
public static GoldTexture: PIXI.Texture;
public static WaveTexture: PIXI.Texture;
@ -36,6 +40,8 @@ export default class GameAssets {
public static PauseIconTexture: PIXI.Texture;
public static ExclamationIconTexture: PIXI.Texture;
public static FastForwardIconTexture: PIXI.Texture;
public static HomeIconTexture: PIXI.Texture;
public static HammerIconTexture: PIXI.Texture;
public static XIconTexture: PIXI.Texture;
public static PlusIconTexture: PIXI.Texture;
public static GemAmountIcons: PIXI.Texture[] = [];
@ -47,10 +53,8 @@ export default class GameAssets {
public static Gems: GemDefinition[];
private static text;
private static counter = 0;
private static async Load(src) {
this.text.text = `Loading asset: ${src} (${this.counter}/102)`;
this.counter++;
this.text.text = 'Loading asset: ' + src;
return await PIXI.Assets.load({
src: src,
});
@ -87,14 +91,19 @@ export default class GameAssets {
Engine.app.stage.addChild(this.text);
await Promise.all([
this.Load('./aclonica.woff2'),
this.Load('./assets/gui/button_01.png').then((texture) => (this.Button01Texture = texture)),
this.Load('./assets/gui/button_02.png').then((texture) => (this.Button02Texture = texture)),
this.Load('./assets/gui/button_small.png').then((texture) => (this.ButtonSmallTexture = texture)),
this.Load('./assets/gui/frame_01.png').then((texture) => (this.Frame01Texture = texture)),
this.Load('./assets/gui/frame_02.png').then((texture) => (this.Frame02Texture = texture)),
this.Load('./assets/gui/frame_03.png').then((texture) => (this.Frame03Texture = texture)),
this.Load('./assets/gui/frame_04.png').then((texture) => (this.Frame04Texture = texture)),
this.Load('./assets/gui/frame_05.png').then((texture) => (this.Frame05Texture = texture)),
this.Load('./assets/gui/frame_inv.png').then((texture) => (this.FrameInventory = texture)),
this.Load('./assets/gui/background_01.png').then((texture) => (this.FrameBackground = texture)),
this.Load('./assets/gui/background_02.png').then((texture) => (this.FrameTowerTab = texture)),
this.Load('./assets/gui/frame_violet.png').then((texture) => (this.VioletBackground = texture)),
this.Load('./assets/gui/frame_red.png').then((texture) => (this.RedBackground = texture)),
this.Load('./assets/gui/frame_green.png').then((texture) => (this.GreenBackground = texture)),
this.Load('./assets/gui/frame_blue.png').then((texture) => (this.BlueBackground = texture)),
@ -116,7 +125,10 @@ export default class GameAssets {
this.Load('./assets/gui/title01.png').then((texture) => (this.TitleTexture = texture)),
this.Load('./assets/gui/icons/play.png').then((texture) => (this.PlayIconTexture = texture)),
this.Load('./assets/gui/icons/pause.png').then((texture) => (this.PauseIconTexture = texture)),
this.Load('./assets/gui/icons/pause.png').then((texture) => (this.PauseIconTexture = texture)),
this.Load('./assets/gui/icons/fastforward.png').then((texture) => (this.FastForwardIconTexture = texture)),
this.Load('./assets/gui/icons/home.png').then((texture) => (this.HomeIconTexture = texture)),
this.Load('./assets/gui/icons/hammer.png').then((texture) => (this.HammerIconTexture = texture)),
this.Load('./assets/gui/icons/cross.png').then((texture) => (this.XIconTexture = texture)),
this.Load('./assets/gui/icons/plus.png').then((texture) => (this.PlusIconTexture = texture)),
this.LoadMissions(),
@ -136,27 +148,9 @@ export default class GameAssets {
for (let idx = 0; idx < gems.length; idx++) {
const gem = this.Gems[idx];
const texture = await this.Load(`./assets/gems/${gem.type}_spritesheet.png`);
for (let i = 1; i <= gem.totalLevels; i++) {
const spritesheet = new PIXI.Spritesheet(texture, {
frames: {
[`${gem.type}_${i}.png`]: {
frame: { x: (i - 1) * 64, y: 0, w: 64, h: 64 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 64, h: 64 },
sourceSize: { w: 64, h: 64 },
},
},
meta: {
image: `./assets/gems/${gem.type}_spritesheet.png`,
format: 'RGBA8888',
size: { w: 64 * gem.totalLevels, h: 64 },
scale: '1',
},
});
await spritesheet.parse();
gem.textures[i - 1] = spritesheet.textures[`${gem.type}_${i}.png`];
const texture = await this.Load(`./assets/gems/${gem.type}/${i}.png`);
gem.textures[i - 1] = texture;
}
}
for (let i = 0; i < 7; i++) {
@ -170,8 +164,8 @@ export default class GameAssets {
this.Creeps = creeps;
for (let idx = 0; idx < this.Creeps.length; idx++) {
const creep = this.Creeps[idx];
const texture = await this.Load(`./assets/creeps/${creep.sprite}_spritesheet.png`);
for (let i = 0; i < creep.textureArrayLength; i++) {
const texture = await this.Load(`./assets/creeps/${creep.sprite}/spritesheet.png`);
const spritesheet = new PIXI.Spritesheet(texture, {
frames: {
[`${creep.sprite}_${i}.png`]: {
@ -191,6 +185,7 @@ export default class GameAssets {
});
await spritesheet.parse();
creep.textures[i] = spritesheet.textures[`${creep.sprite}_${i}.png`];
// creep.textures[i] = texture;
}
}
}
@ -213,8 +208,6 @@ export default class GameAssets {
for (let idx = 0; idx < this.Towers.length; idx++) {
const tower = this.Towers[idx];
for (let i = 0; i < tower.projectileTexturesArrayLength; i++) {
// My only grievance is that projectiles have to load like this, not like a spritesheet
// due to them not being a fixed w/h.
const projTexture = await this.Load(`./assets/projectiles/${tower.projectile}/${i}.png`);
tower.projectileTextures[i] = projTexture;
}
@ -228,7 +221,7 @@ export default class GameAssets {
private static async LoadMission(missionUrl: string) {
const res = await fetch(missionUrl);
const mission = await res.json();
// console.log(`Loading mission: ${missionUrl} [${mission.name} / ${mission.mapImage.url}]`);
console.log(`Loading mission: ${missionUrl} [${mission.name} / ${mission.mapImage.url}]`);
GameAssets.Missions.push(mission);
GameAssets.MissionBackgrounds.push(await this.Load(mission.mapImage.url));
}

View File

@ -34,13 +34,12 @@ export class Engine {
public static TestSuite() {
let params = new URLSearchParams(location.href);
if (params.entries().next().value[1] != 'game') return;
Engine.NotificationManager.Notify('Loaded.', 'danger');
Engine.NotificationManager.Notify('Loaded testing suite.', 'danger');
let tower = GameAssets.Towers[TowerType.Electric];
Engine.TowerManager.ToggleChoosingTowerLocation('RESET');
Engine.TowerManager.PlaceTower(tower, 6, 10, tower.behaviour, true);
Engine.GameScene.MissionStats.earnGold(2000);
for (let i = 0; i < 24; i++) {
this.GameScene.MissionStats.giveGem(new Gem(i % 6), true);
for (let i = 0; i < 29; i++) {
this.GameScene.MissionStats.giveGem(new Gem(i % 4), true);
}
}
}

View File

@ -32,7 +32,6 @@ export type WaveDefinition = {
export type CreepDefinition = {
name: string;
sprite: string;
tint: PIXI.ColorSource;
textures: PIXI.Texture[];
textureArrayLength: number;
stats: CreepStatsDefinition;
@ -114,9 +113,6 @@ export enum CreepType {
Cloaker = 3,
Demon = 4,
Maker = 5,
Monster = 6,
Remaker = 7,
Elite = 8,
}
export enum GemType {

View File

@ -49,7 +49,6 @@ export default class Creep extends GameObject {
this.sprite.scale.x *= -1;
this.sprite.anchor.set(0.5, 0.5);
this.sprite.animationSpeed = 0.3;
this.sprite.tint = Assets.Creeps[this.creepType].tint;
this.sprite.play();
this.id = id;
// Explanation: WaveManager spawns all creeps instantly, and since I don't want
@ -64,20 +63,20 @@ export default class Creep extends GameObject {
this.health = this.stats.health;
this.maxHealth = this.stats.health;
this.path = path;
// Added + 32 to center them.
this.x = path[0][0] * Engine.GridCellSize + Engine.GridCellSize / 2;
this.y = path[0][1] * Engine.GridCellSize + Engine.GridCellSize / 2;
// TODO: Unsubscribe from events once the scene is destroyed
Engine.GameScene.events.on(
CreepEvents.TakenDamage,
(creepID, damage, gemResistanceModifications: CreepResistancesDefinition) => {
if (creepID != this.id) return;
if (this.effects.find((e) => e.effectEnum == CreepEffects.DebuffTowerDebuff)) {
damage = damage * 1.5;
console.log('multiplying damage, ' + damage);
}
// Apply resistances.
this.health -= Math.max(
damage + damage * (gemResistanceModifications.physical - this.stats.resistance.physical),
0
);
this.health -= damage + damage * (gemResistanceModifications.physical - this.stats.resistance.physical);
if (gemResistanceModifications.fire != 0)
this.health -= Math.max(damage * (gemResistanceModifications.fire - this.stats.resistance.fire), 0);
if (gemResistanceModifications.ice != 0)
@ -99,6 +98,7 @@ export default class Creep extends GameObject {
CreepEvents.GiveEffect,
(creepID: number, effect: CreepEffects, durationInMS: number) => {
if (creepID != this.id) return;
console.log(' I CAUGHT THE EVENT!');
if (this.effects.find((e) => e.effectEnum == effect) == undefined)
this.effects.push(new Effect(effect, durationInMS));
}
@ -224,13 +224,13 @@ export default class Creep extends GameObject {
this.container.y = this.y;
}
// public takeDamage(amount: number) {
// this.health -= amount;
// if (this.health < 0 && !this.died) {
// this.died = true;
// this.events.emit(CreepEvents.Died, this);
// }
// }
public takeDamage(amount: number) {
this.health -= amount;
if (this.health < 0 && !this.died) {
this.died = true;
this.events.emit(CreepEvents.Died, this);
}
}
public destroy() {
super.destroy();

View File

@ -10,9 +10,9 @@ export default class MissionStats extends GameObject {
private gold: number = 0;
private goldEarned: number = 0;
private goldSpent: number = 0;
public damageDealt: number = 0;
public wavesSurvived: number = 0;
public creepsKilled: number = 0;
private wavesSurvived: number = 0;
private damageDealt: number = 0;
private creepsKilled: number = 0;
private goldText: PIXI.Text;
private healthText: PIXI.Text;
private waveText: PIXI.Text;
@ -44,13 +44,11 @@ export default class MissionStats extends GameObject {
public earnGold(gold: number) {
this.gold += gold;
this.goldText.text = this.gold;
this.goldEarned += gold;
}
public spendGold(amount: number) {
this.gold -= amount;
this.goldText.text = this.gold;
this.goldSpent += amount;
}
public giveGem(gem: Gem, noNotify?) {
@ -84,7 +82,6 @@ export default class MissionStats extends GameObject {
super();
this.hp = initialHP;
this.gold = initialGold;
this.goldEarned = initialGold;
this.container.x = 0;
this.container.y = 20;
Engine.GameMaster.currentScene.stage.addChild(this.container);
@ -164,25 +161,20 @@ export default class MissionStats extends GameObject {
}
private calculateScore() {
const gems = [];
const uniqueGems = [];
for (const gem of this.inventory) {
gems.push(gem.definition.name);
if (!uniqueGems.includes(gem.definition.name)) {
uniqueGems.push(gem.definition.name);
}
}
Engine.TowerManager.towers.forEach((tower) => {
tower.slottedGems.forEach((gem) => {
gems.push(gem.definition.name);
});
});
return (
this.damageDealt * 2 +
this.hp * 10 +
(this.goldEarned - this.goldSpent) * 3 +
this.wavesSurvived * 100 +
gems.length * 100 +
1000
uniqueGems.length * 100
);
}
// Because it's a game object, must have this.
public update() {}
}

View File

@ -7,7 +7,6 @@ import Creep, { CreepEffects } from './Creep';
import Projectile, { calculateAngleToPoint, TrapProjectile, VisualLightning } from './Projectile';
import { distance, Tower } from './Tower';
import * as PIXI from 'pixi.js';
import { TowerBehaviours } from './TowerManager';
/**
* Checks the projectiles of the tower and updates or removes them based on their state.
@ -63,19 +62,17 @@ export function computeGemImprovements(tower: Tower) {
gemPierceUp += improvements.pierceUp;
let resistances = gem.currentGemResistanceModifications();
tower.totalGemResistanceModifications.physical += Number(resistances.physical.toFixed(2));
tower.totalGemResistanceModifications.ice += Number(resistances.ice.toFixed(2));
tower.totalGemResistanceModifications.fire += Number(resistances.fire.toFixed(2));
tower.totalGemResistanceModifications.divine += Number(resistances.divine.toFixed(2));
tower.totalGemResistanceModifications.frostfire += Number(resistances.frostfire.toFixed(2));
tower.totalGemResistanceModifications.physical += resistances.physical;
tower.totalGemResistanceModifications.ice += resistances.ice;
tower.totalGemResistanceModifications.fire += resistances.fire;
tower.totalGemResistanceModifications.divine += resistances.divine;
tower.totalGemResistanceModifications.frostfire += resistances.frostfire;
});
tower.computedDamageToDeal = tower.definition.stats.damage + gemDamage;
tower.computedCooldown = tower.definition.stats.cooldown - gemAttackSpeedUp;
tower.computedRange = tower.definition.stats.range + gemRangeUp;
if (tower.behaviour != TowerBehaviours.TrapperTowerBehaviour)
tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp;
else tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp * 10;
tower.computedPierce = tower.definition.stats.pierce + gemPierceUp;
// Buff tower
@ -87,21 +84,14 @@ export function computeGemImprovements(tower: Tower) {
tower.computedTimeToLive += Number((buffedBy.computedTimeToLive / 5).toFixed(1));
tower.computedPierce += Number((buffedBy.computedPierce / 4).toFixed(1));
tower.totalGemResistanceModifications.physical += Number(
(buffedBy.totalGemResistanceModifications.physical / 2).toFixed(2)
);
tower.totalGemResistanceModifications.ice += Number(
(buffedBy.totalGemResistanceModifications.ice / 2).toFixed(2)
);
tower.totalGemResistanceModifications.fire += Number(
(buffedBy.totalGemResistanceModifications.fire / 2).toFixed(2)
);
tower.totalGemResistanceModifications.divine += Number(
(buffedBy.totalGemResistanceModifications.divine / 2).toFixed(2)
);
tower.totalGemResistanceModifications.frostfire += Number(
(buffedBy.totalGemResistanceModifications.frostfire / 2).toFixed(2)
);
tower.totalGemResistanceModifications.physical +=
(buffedBy.totalGemResistanceModifications.physical * 100) / 2 / 100;
tower.totalGemResistanceModifications.ice += (buffedBy.totalGemResistanceModifications.ice * 100) / 2 / 100;
tower.totalGemResistanceModifications.fire += (buffedBy.totalGemResistanceModifications.fire * 100) / 2 / 100;
tower.totalGemResistanceModifications.divine +=
(buffedBy.totalGemResistanceModifications.divine * 100) / 2 / 100;
tower.totalGemResistanceModifications.frostfire +=
(buffedBy.totalGemResistanceModifications.frostfire * 100) / 2 / 100;
}
}

View File

@ -28,7 +28,7 @@ export default class TowerManager {
height: 64,
alpha: 0.8,
});
public towers: Tower[] = [];
private towers: Tower[] = [];
constructor() {
// TODO: Unsubscribe from events once the scene is destroyed
Engine.TowerManager = this;

View File

@ -119,9 +119,7 @@ export default class EndGameDialog extends ModalDialogBase {
override close(button?: string): void {
if (button === EndGameDialogButtons.Confirm) {
if (this.playerNameTextInput.getText().length == 0) {
MessageBox.show('Please enter your name.\n(Just start typing, input bar is automatically selected.)', [
'OK',
]);
MessageBox.show('Please enter your name.', ['OK']);
} else {
this.highScore.addScore({
playerName: this.playerNameTextInput.getText(),

View File

@ -19,15 +19,16 @@ export default class GamePausedDialog extends ModalDialogBase {
protected override createContent(): PIXI.Container {
const container = new PIXI.Container();
this.btnContinue = new Button(new PIXI.Rectangle(0, 0, 300, 60), 'Continue', ButtonTexture.Button01);
this.btnContinue.onClick = this.onContinueClick.bind(this);
container.addChild(this.btnContinue.container);
this.btnMainMenu = new Button(new PIXI.Rectangle(0, 0, 300, 60), 'Main Menu', ButtonTexture.Button01);
this.btnMainMenu.onClick = this.onMainMenuClick.bind(this);
container.addChild(this.btnMainMenu.container);
this.btnRetry = new Button(new PIXI.Rectangle(0, 70, 300, 60), 'Retry', ButtonTexture.Button01);
this.btnRetry.onClick = this.onRetryClick.bind(this);
container.addChild(this.btnRetry.container);
this.btnMainMenu = new Button(new PIXI.Rectangle(0, 140, 300, 60), 'Main Menu', ButtonTexture.Button01);
this.btnMainMenu.onClick = this.onMainMenuClick.bind(this);
container.addChild(this.btnMainMenu.container);
this.btnContinue = new Button(new PIXI.Rectangle(0, 140, 300, 60), 'Continue', ButtonTexture.Button01);
this.btnContinue.onClick = this.onContinueClick.bind(this);
container.addChild(this.btnContinue.container);
return container;
}

View File

@ -20,7 +20,7 @@ export class VisualGemSlot extends GuiObject {
let gtexture;
this.i = index;
this.container.x = 10;
this.container.y = index * (Engine.GridCellSize + 6) + 350;
this.container.y = index * (Engine.GridCellSize + 6) + 300;
this.background = new PIXI.Sprite({
texture: GameAssets.Frame01Texture,
});
@ -115,7 +115,6 @@ export default class TowerPanel extends GuiObject {
public divineResDamage: PIXI.Text;
public physicalResDamage: PIXI.Text;
private sellButton: Button;
private description: PIXI.Text;
constructor(bounds: PIXI.Rectangle) {
super(false);
@ -283,23 +282,6 @@ export default class TowerPanel extends GuiObject {
}),
});
this.container.addChild(this.physicalResDamage);
this.description = new PIXI.Text({
x: 10,
y: 270,
zIndex: 5,
style: {
fontSize: 18,
wordWrap: true,
wordWrapWidth: 245,
fill: 0x00ff00,
fontStyle: 'italic',
stroke: {
color: 0x000000,
width: 2,
},
},
});
this.container.addChild(this.description);
this.sellButton = new Button(
new PIXI.Rectangle(5, this.towerPanel.height - 70, this.towerPanel.width - 115, 60),
'Sell',
@ -366,7 +348,6 @@ export default class TowerPanel extends GuiObject {
this.frostFireResDamage.text = `+${tower.totalGemResistanceModifications.frostfire * 100}% FrostFire damage`;
this.divineResDamage.text = `+${tower.totalGemResistanceModifications.divine * 100}% Divine damage`;
this.physicalResDamage.text = `+${tower.totalGemResistanceModifications.physical * 100}% Physical damage`;
this.description.text = `"${tower.definition.description}"`;
this.sellButton.setCaption('Sell for ' + tower.definition.stats.cost + ' gold');
this.sellButton.onClick = () => {
tower.Sell();

View File

@ -48,23 +48,6 @@ import DebrisManager from './classes/game/DebrisManager';
window.addEventListener('resize', resize);
resize();
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (isMobile) {
let ttxt = new PIXI.Text({
text: 'Bastion: The Watchers Lament is currently unsupported on mobile.\nPlease play it on your computer instead.',
style: new PIXI.TextStyle({
fill: 0x333333,
fontSize: 50,
textBaseline: 'middle',
}),
});
ttxt.x = Engine.app.canvas.width / 2;
ttxt.y = Engine.app.canvas.height / 2 + 50;
ttxt.anchor.set(0.5, 0.5);
Engine.app.stage.addChild(ttxt);
return;
}
await Assets.LoadAssets();
GameUIConstants.init();
KeyboardManager.init();

View File

@ -85,8 +85,6 @@ export class GameScene extends Scene {
this.isWaveManagerFinished = true;
});
this.events.on(CreepEvents.Died, (playerAward, creepThatDied) => {
this.MissionStats.damageDealt += playerAward;
this.MissionStats.creepsKilled++;
this.MissionStats.earnGold(playerAward);
});
this.towerPanel = new TowerPanel(GameUIConstants.SidebarRect);
@ -123,7 +121,7 @@ export class GameScene extends Scene {
this.changeRoundButton.buttonIcon.texture = GameAssets.FastForwardIconTexture;
this.events.emit(WaveManagerEvents.NewWave, `${this.currentRound + 1}`);
};
this.MissionStats = new MissionStats(100, 75);
this.MissionStats = new MissionStats(100, 250);
this.events.on(GemEvents.TowerPanelSelectGem, (gem, index, tower) => {
if (gem == null) {
if (!this.MissionStats.checkIfPlayerHasAnyGems())
@ -187,13 +185,13 @@ export class GameScene extends Scene {
this.isWaveManagerFinished = false;
this.setRoundMode(RoundMode.Purchase);
this.changeRoundButton.buttonIcon.texture = GameAssets.PlayIconTexture;
this.MissionStats.wavesSurvived++;
Engine.NotificationManager.Notify(
`Round ${this.currentRound + 1}/${this.mission.rounds.length} completed.`,
'info'
);
if (this.currentRound + 1 == this.mission.rounds.length) {
Engine.NotificationManager.Notify(`Mission victory!!`, 'reward');
this.changeRoundButton.buttonIcon.texture = GameAssets.HomeIconTexture;
this.playerWon = true;
} else {
this.OfferPlayerGems();
@ -251,6 +249,7 @@ export class GameScene extends Scene {
},
},
});
// offerText.x -= offerText.width;
Engine.GameMaster.currentScene.stage.addChildAt(offerText, 0);
gemsToOffer.forEach((gType, index) => {
let _Gem = new Gem(gType, true);

View File

@ -14,7 +14,7 @@ export class MainScene extends Scene {
this.addMainBackground();
const NewGameButton = {
caption: 'Play',
caption: 'New Game',
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 0 * 70, 300, 60),
texture: ButtonTexture.Button01,