clashofclans.js 2.0.0-dev.75d755c → 2.0.0-dev.7768cb1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -5
- package/README.md +3 -2
- package/dist/client/Client.d.ts +5 -3
- package/dist/client/Client.js +14 -9
- package/dist/client/EventManager.js +16 -4
- package/dist/rest/HTTPError.d.ts +1 -3
- package/dist/rest/HTTPError.js +1 -3
- package/dist/rest/RESTManager.d.ts +26 -1
- package/dist/rest/RESTManager.js +25 -1
- package/dist/rest/RequestHandler.js +9 -5
- package/dist/rest/Throttler.d.ts +0 -4
- package/dist/struct/Clan.d.ts +2 -1
- package/dist/struct/Clan.js +2 -2
- package/dist/struct/ClanMember.d.ts +2 -1
- package/dist/struct/ClanMember.js +2 -2
- package/dist/struct/ClanWarLeagueGroup.d.ts +5 -3
- package/dist/struct/ClanWarLeagueGroup.js +8 -7
- package/dist/struct/Player.d.ts +2 -1
- package/dist/struct/Player.js +7 -5
- package/dist/struct/PlayerClan.d.ts +2 -1
- package/dist/struct/PlayerClan.js +2 -2
- package/dist/struct/Unit.d.ts +37 -4
- package/dist/struct/Unit.js +49 -9
- package/dist/types/index.d.ts +2 -4
- package/dist/util/raw.json +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
## 2.0.0
|
|
5
|
+
## 2.0.0 (2021-11-26)
|
|
6
6
|
|
|
7
7
|
This new version is a complete TypeScript rewrite to convert everything from plain (literal JSON) objects to class (constructor) objects and support a lot more features.
|
|
8
8
|
|
|
9
9
|
### Features
|
|
10
10
|
|
|
11
|
-
- EventManager and Custom Events ([#37](https://github.com/clashperk/clashofclans.js/issues/37)) ([5027ae6](https://github.com/clashperk/clashofclans.js/commit/5027ae663a8e07175e17384c7e5706f4a1a7afb4)) ([984451d](https://github.com/clashperk/clashofclans.js/commit/30ea3240c11866008d0dae514468c0fdbb34ffd0))
|
|
12
|
-
- Internal Caching Options ([#53](https://github.com/clashperk/clashofclans.js/issues/53))
|
|
13
|
-
- Email Password Login ([#31](https://github.com/clashperk/clashofclans.js/issues/31)) ([4153cd3](https://github.com/clashperk/clashofclans.js/commit/4153cd37ea0e1c71550b9e892105b84d5a407e23))
|
|
14
11
|
- API Date Parser and Request Retries ([#26](https://github.com/clashperk/clashofclans.js/issues/26)) ([94585f3](https://github.com/clashperk/clashofclans.js/commit/94585f3a84a7175b2d07872f9eb9e42372b95e12))
|
|
15
|
-
-
|
|
12
|
+
- EventManager and Custom Events ([#37](https://github.com/clashperk/clashofclans.js/issues/37)) ([5027ae6](https://github.com/clashperk/clashofclans.js/commit/5027ae663a8e07175e17384c7e5706f4a1a7afb4))
|
|
13
|
+
- Email Password Login ([#31](https://github.com/clashperk/clashofclans.js/issues/31)) ([4153cd3](https://github.com/clashperk/clashofclans.js/commit/4153cd37ea0e1c71550b9e892105b84d5a407e23))
|
|
16
14
|
- QueueThrottler and BatchThrottler ([#34](https://github.com/clashperk/clashofclans.js/issues/34)) ([3a8f051](https://github.com/clashperk/clashofclans.js/commit/3a8f051552e93b98f89bc7d524acdecddf242718))
|
|
15
|
+
- Override Request Options ([#36](https://github.com/clashperk/clashofclans.js/issues/36)) ([42d7fdd](https://github.com/clashperk/clashofclans.js/commit/42d7fdd36262cc46f23b731f8cffb9daea19d3b0))
|
|
16
|
+
- Internal Caching Options ([#53](https://github.com/clashperk/clashofclans.js/issues/53)) ([984451d](https://github.com/clashperk/clashofclans.js/commit/30ea3240c11866008d0dae514468c0fdbb34ffd0))
|
|
17
|
+
- Raw Data for Player Units ([#65](https://github.com/clashperk/clashofclans.js/pull/65)) ([aa1696](https://github.com/clashperk/clashofclans.js/commit/aa1696243d96d4fed0250b4282c60522a6482343))
|
package/README.md
CHANGED
|
@@ -39,9 +39,10 @@ const client = new Client();
|
|
|
39
39
|
```js
|
|
40
40
|
const { Client, BatchThrottler } = require('clashofclans.js');
|
|
41
41
|
const client = new Client({
|
|
42
|
+
cache: true,
|
|
42
43
|
retryLimit: 1,
|
|
43
|
-
restRequestTimeout:
|
|
44
|
-
throttler: new BatchThrottler(
|
|
44
|
+
restRequestTimeout: 5000,
|
|
45
|
+
throttler: new BatchThrottler(20)
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
client.events.addClans(['#8QU8J9LP', '#8P2QG08P']);
|
package/dist/client/Client.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export declare class Client extends EventEmitter {
|
|
|
21
21
|
constructor(options?: ClientOptions);
|
|
22
22
|
/** Contains various general-purpose utility methods. */
|
|
23
23
|
get util(): typeof Util;
|
|
24
|
+
/** Whether the API is in maintenance break. */
|
|
25
|
+
get inMaintenance(): boolean;
|
|
24
26
|
/**
|
|
25
27
|
* Initialize the client to create keys.
|
|
26
28
|
* @example
|
|
@@ -76,7 +78,7 @@ export declare class Client extends EventEmitter {
|
|
|
76
78
|
private _getClanWars;
|
|
77
79
|
/** Get information about clan war league. */
|
|
78
80
|
getClanWarLeagueGroup(clanTag: string, options?: OverrideOptions): Promise<ClanWarLeagueGroup>;
|
|
79
|
-
/** Get
|
|
81
|
+
/** Get info about a CWL round by WarTag. */
|
|
80
82
|
getClanWarLeagueRound(warTag: string | {
|
|
81
83
|
warTag: string;
|
|
82
84
|
clanTag?: string;
|
|
@@ -99,9 +101,9 @@ export declare class Client extends EventEmitter {
|
|
|
99
101
|
getClanRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedClan[]>;
|
|
100
102
|
/** Get player rankings for a specific location. */
|
|
101
103
|
getPlayerRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedPlayer[]>;
|
|
102
|
-
/** Get clan versus rankings for a specific location */
|
|
104
|
+
/** Get clan versus rankings for a specific location. */
|
|
103
105
|
getVersusClanRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedClan[]>;
|
|
104
|
-
/** Get player versus rankings for a specific location */
|
|
106
|
+
/** Get player versus rankings for a specific location. */
|
|
105
107
|
getVersusPlayerRanks(locationId: number | 'global', options?: SearchOptions): Promise<RankedPlayer[]>;
|
|
106
108
|
/** Get list of clan labels. */
|
|
107
109
|
getClanLabels(options?: SearchOptions): Promise<Label[]>;
|
package/dist/client/Client.js
CHANGED
|
@@ -25,6 +25,11 @@ class Client extends events_1.EventEmitter {
|
|
|
25
25
|
get util() {
|
|
26
26
|
return Util_1.Util;
|
|
27
27
|
}
|
|
28
|
+
/** Whether the API is in maintenance break. */
|
|
29
|
+
get inMaintenance() {
|
|
30
|
+
// @ts-expect-error
|
|
31
|
+
return this.events._inMaintenance;
|
|
32
|
+
}
|
|
28
33
|
/**
|
|
29
34
|
* Initialize the client to create keys.
|
|
30
35
|
* @example
|
|
@@ -88,7 +93,7 @@ class Client extends events_1.EventEmitter {
|
|
|
88
93
|
}
|
|
89
94
|
catch (e) {
|
|
90
95
|
if (e instanceof HTTPError_1.HTTPError && [200, 403].includes(e.status)) {
|
|
91
|
-
return this.getLeagueWar({ clanTag: args.clanTag, round: args.round });
|
|
96
|
+
return this.getLeagueWar({ clanTag: args.clanTag, round: args.round }, options);
|
|
92
97
|
}
|
|
93
98
|
throw e;
|
|
94
99
|
}
|
|
@@ -117,7 +122,7 @@ class Client extends events_1.EventEmitter {
|
|
|
117
122
|
.map((round) => round.warTags)
|
|
118
123
|
.flat()
|
|
119
124
|
.reverse();
|
|
120
|
-
const wars = await this.util.allSettled(warTags.map((warTag) => this.getClanWarLeagueRound({ warTag, clanTag: args.clanTag }, { ignoreRateLimit: true })));
|
|
125
|
+
const wars = await this.util.allSettled(warTags.map((warTag) => this.getClanWarLeagueRound({ warTag, clanTag: args.clanTag }, { ...options, ignoreRateLimit: true })));
|
|
121
126
|
if (args.round && args.round in Constants_1.CWL_ROUNDS) {
|
|
122
127
|
return wars.find((war) => war.state === state) ?? null;
|
|
123
128
|
}
|
|
@@ -126,7 +131,7 @@ class Client extends events_1.EventEmitter {
|
|
|
126
131
|
async _getCurrentLeagueWars(clanTag, options) {
|
|
127
132
|
const data = await this.getClanWarLeagueGroup(clanTag, options);
|
|
128
133
|
// @ts-expect-error
|
|
129
|
-
return data._getCurrentWars(clanTag);
|
|
134
|
+
return data._getCurrentWars(clanTag, options);
|
|
130
135
|
}
|
|
131
136
|
async _getClanWars(clanTag, options) {
|
|
132
137
|
const date = new Date().getUTCDate();
|
|
@@ -134,11 +139,11 @@ class Client extends events_1.EventEmitter {
|
|
|
134
139
|
return [await this.getClanWar(clanTag, options)];
|
|
135
140
|
}
|
|
136
141
|
try {
|
|
137
|
-
return this._getCurrentLeagueWars(clanTag);
|
|
142
|
+
return this._getCurrentLeagueWars(clanTag, options);
|
|
138
143
|
}
|
|
139
144
|
catch (e) {
|
|
140
145
|
if (e instanceof HTTPError_1.HTTPError && [404].includes(e.status)) {
|
|
141
|
-
return [await this.getClanWar(clanTag)];
|
|
146
|
+
return [await this.getClanWar(clanTag, options)];
|
|
142
147
|
}
|
|
143
148
|
throw e;
|
|
144
149
|
}
|
|
@@ -148,7 +153,7 @@ class Client extends events_1.EventEmitter {
|
|
|
148
153
|
const { data } = await this.rest.getClanWarLeagueGroup(clanTag, options);
|
|
149
154
|
return new struct_1.ClanWarLeagueGroup(this, data);
|
|
150
155
|
}
|
|
151
|
-
/** Get
|
|
156
|
+
/** Get info about a CWL round by WarTag. */
|
|
152
157
|
async getClanWarLeagueRound(warTag, options) {
|
|
153
158
|
const args = typeof warTag === 'string' ? { warTag } : { warTag: warTag.warTag, clanTag: warTag.clanTag };
|
|
154
159
|
const { data, maxAge, status, path } = await this.rest.getClanWarLeagueRound(args.warTag, options);
|
|
@@ -164,7 +169,7 @@ class Client extends events_1.EventEmitter {
|
|
|
164
169
|
}
|
|
165
170
|
/** Verify Player API token that can be found from the Game settings. */
|
|
166
171
|
async verifyPlayerToken(playerTag, token, options) {
|
|
167
|
-
const { data } = await this.rest.
|
|
172
|
+
const { data } = await this.rest.verifyPlayerToken(playerTag, token, options);
|
|
168
173
|
return data.status === 'ok';
|
|
169
174
|
}
|
|
170
175
|
/** Get list of Leagues. */
|
|
@@ -203,12 +208,12 @@ class Client extends events_1.EventEmitter {
|
|
|
203
208
|
const { data } = await this.rest.getPlayerRanks(locationId, options);
|
|
204
209
|
return data.items.map((entry) => new struct_1.RankedPlayer(this, entry));
|
|
205
210
|
}
|
|
206
|
-
/** Get clan versus rankings for a specific location */
|
|
211
|
+
/** Get clan versus rankings for a specific location. */
|
|
207
212
|
async getVersusClanRanks(locationId, options) {
|
|
208
213
|
const { data } = await this.rest.getVersusClanRanks(locationId, options);
|
|
209
214
|
return data.items.map((entry) => new struct_1.RankedClan(entry));
|
|
210
215
|
}
|
|
211
|
-
/** Get player versus rankings for a specific location */
|
|
216
|
+
/** Get player versus rankings for a specific location. */
|
|
212
217
|
async getVersusPlayerRanks(locationId, options) {
|
|
213
218
|
const { data } = await this.rest.getVersusPlayerRanks(locationId, options);
|
|
214
219
|
return data.items.map((entry) => new struct_1.RankedPlayer(this, entry));
|
|
@@ -107,6 +107,10 @@ class EventManager {
|
|
|
107
107
|
* @returns
|
|
108
108
|
*/
|
|
109
109
|
setClanEvent(event) {
|
|
110
|
+
if (!event.name)
|
|
111
|
+
throw new Error('Event name is required.');
|
|
112
|
+
if (typeof event.filter !== 'function')
|
|
113
|
+
throw new Error('Filter function is required.');
|
|
110
114
|
this._events.clans.push(event);
|
|
111
115
|
return this;
|
|
112
116
|
}
|
|
@@ -116,6 +120,10 @@ class EventManager {
|
|
|
116
120
|
* In order to emit the custom event, you must have this filter function that returns a boolean.
|
|
117
121
|
*/
|
|
118
122
|
setWarEvent(event) {
|
|
123
|
+
if (!event.name)
|
|
124
|
+
throw new Error('Event name is required.');
|
|
125
|
+
if (typeof event.filter !== 'function')
|
|
126
|
+
throw new Error('Filter function is required.');
|
|
119
127
|
this._events.wars.push(event);
|
|
120
128
|
return this;
|
|
121
129
|
}
|
|
@@ -125,6 +133,10 @@ class EventManager {
|
|
|
125
133
|
* In order to emit the custom event, you must have this filter function that returns a boolean.
|
|
126
134
|
*/
|
|
127
135
|
setPlayerEvent(event) {
|
|
136
|
+
if (!event.name)
|
|
137
|
+
throw new Error('Event name is required.');
|
|
138
|
+
if (typeof event.filter !== 'function')
|
|
139
|
+
throw new Error('Filter function is required.');
|
|
128
140
|
this._events.players.push(event);
|
|
129
141
|
return this;
|
|
130
142
|
}
|
|
@@ -134,7 +146,7 @@ class EventManager {
|
|
|
134
146
|
const res = await this.client.rest.getClans({ maxMembers: Math.floor(Math.random() * 40) + 10, limit: 1 });
|
|
135
147
|
if (res.status === 200 && this._inMaintenance) {
|
|
136
148
|
this._inMaintenance = Boolean(false);
|
|
137
|
-
const duration =
|
|
149
|
+
const duration = Date.now() - this._maintenanceStartTime.getTime();
|
|
138
150
|
this._maintenanceStartTime = null;
|
|
139
151
|
this.client.emit(Constants_1.EVENTS.MAINTENANCE_END, duration);
|
|
140
152
|
}
|
|
@@ -229,8 +241,8 @@ class EventManager {
|
|
|
229
241
|
const clanWars = await this.client._getClanWars(tag).catch(() => null);
|
|
230
242
|
if (!clanWars?.length)
|
|
231
243
|
return null;
|
|
232
|
-
clanWars.forEach(async (war,
|
|
233
|
-
const key = `${tag}:${
|
|
244
|
+
clanWars.forEach(async (war, index) => {
|
|
245
|
+
const key = `${tag}:${index}`;
|
|
234
246
|
const cached = this._wars.get(key);
|
|
235
247
|
if (!cached)
|
|
236
248
|
return this._wars.set(key, war);
|
|
@@ -245,7 +257,7 @@ class EventManager {
|
|
|
245
257
|
}
|
|
246
258
|
}
|
|
247
259
|
// check for war end
|
|
248
|
-
if (
|
|
260
|
+
if (index === 1 && cached.warTag !== war.warTag) {
|
|
249
261
|
const data = await this.client.getLeagueWar({ clanTag: tag, round: 'PREVIOUS_ROUND' }).catch(() => null);
|
|
250
262
|
if (data && data.warTag === cached.warTag) {
|
|
251
263
|
for (const { name, filter } of this._events.wars) {
|
package/dist/rest/HTTPError.d.ts
CHANGED
package/dist/rest/HTTPError.js
CHANGED
|
@@ -2,146 +2,171 @@ import { RequestHandler, SearchOptions, ClanSearchOptions, ClientOptions, Overri
|
|
|
2
2
|
import { APIClan, APIClanList, APIClanMemberList, APIClanRankingList, APIClanVersusRankingList, APIClanWar, APIClanWarLeagueGroup, APIClanWarLog, APIGoldPassSeason, APILabelList, APILeague, APILeagueList, APILeagueSeasonList, APILocation, APILocationList, APIPlayer, APIPlayerRankingList, APIPlayerSeasonRankingList, APIPlayerVersusRankingList, APIVerifyToken, APIWarLeague, APIWarLeagueList } from '../types';
|
|
3
3
|
/** Represents a REST Manager of the client. */
|
|
4
4
|
export declare class RESTManager {
|
|
5
|
+
/** Request Handler for the RESTManager. */
|
|
5
6
|
readonly handler: RequestHandler;
|
|
6
7
|
constructor(options?: ClientOptions);
|
|
8
|
+
/** Search all clans by name and/or filtering the results using various criteria. */
|
|
7
9
|
getClans(options: ClanSearchOptions): Promise<{
|
|
8
10
|
data: APIClanList;
|
|
9
11
|
maxAge: number;
|
|
10
12
|
status: number;
|
|
11
13
|
path: string;
|
|
12
14
|
}>;
|
|
15
|
+
/** Get information about a clan. */
|
|
13
16
|
getClan(clanTag: string, options?: OverrideOptions): Promise<{
|
|
14
17
|
data: APIClan;
|
|
15
18
|
maxAge: number;
|
|
16
19
|
status: number;
|
|
17
20
|
path: string;
|
|
18
21
|
}>;
|
|
22
|
+
/** Get list of clan members. */
|
|
19
23
|
getClanMembers(clanTag: string, options?: SearchOptions): Promise<{
|
|
20
24
|
data: APIClanMemberList;
|
|
21
25
|
maxAge: number;
|
|
22
26
|
status: number;
|
|
23
27
|
path: string;
|
|
24
28
|
}>;
|
|
29
|
+
/** Get clan war log. */
|
|
25
30
|
getClanWarLog(clanTag: string, options?: SearchOptions): Promise<{
|
|
26
31
|
data: APIClanWarLog;
|
|
27
32
|
maxAge: number;
|
|
28
33
|
status: number;
|
|
29
34
|
path: string;
|
|
30
35
|
}>;
|
|
36
|
+
/** Get info about currently running war in the clan. */
|
|
31
37
|
getCurrentWar(clanTag: string, options?: OverrideOptions): Promise<{
|
|
32
38
|
data: APIClanWar;
|
|
33
39
|
maxAge: number;
|
|
34
40
|
status: number;
|
|
35
41
|
path: string;
|
|
36
42
|
}>;
|
|
43
|
+
/** Get information about clan war league. */
|
|
37
44
|
getClanWarLeagueGroup(clanTag: string, options?: OverrideOptions): Promise<{
|
|
38
45
|
data: APIClanWarLeagueGroup;
|
|
39
46
|
maxAge: number;
|
|
40
47
|
status: number;
|
|
41
48
|
path: string;
|
|
42
49
|
}>;
|
|
50
|
+
/** Get info about a CWL round by WarTag. */
|
|
43
51
|
getClanWarLeagueRound(warTag: string, options?: OverrideOptions): Promise<{
|
|
44
52
|
data: APIClanWar;
|
|
45
53
|
maxAge: number;
|
|
46
54
|
status: number;
|
|
47
55
|
path: string;
|
|
48
56
|
}>;
|
|
57
|
+
/** Get information about a player by tag. */
|
|
49
58
|
getPlayer(playerTag: string, options?: OverrideOptions): Promise<{
|
|
50
59
|
data: APIPlayer;
|
|
51
60
|
maxAge: number;
|
|
52
61
|
status: number;
|
|
53
62
|
path: string;
|
|
54
63
|
}>;
|
|
55
|
-
|
|
64
|
+
/** Verify Player API token that can be found from the Game settings. */
|
|
65
|
+
verifyPlayerToken(playerTag: string, token: string, options?: OverrideOptions): Promise<{
|
|
56
66
|
data: APIVerifyToken;
|
|
57
67
|
maxAge: number;
|
|
58
68
|
status: number;
|
|
59
69
|
path: string;
|
|
60
70
|
}>;
|
|
71
|
+
/** Get list of Leagues. */
|
|
61
72
|
getLeagues(options?: SearchOptions): Promise<{
|
|
62
73
|
data: APILeagueList;
|
|
63
74
|
maxAge: number;
|
|
64
75
|
status: number;
|
|
65
76
|
path: string;
|
|
66
77
|
}>;
|
|
78
|
+
/** Get a League info. */
|
|
67
79
|
getLeague(leagueId: string | number, options?: OverrideOptions): Promise<{
|
|
68
80
|
data: APILeague;
|
|
69
81
|
maxAge: number;
|
|
70
82
|
status: number;
|
|
71
83
|
path: string;
|
|
72
84
|
}>;
|
|
85
|
+
/** Get Legend League season Ids. */
|
|
73
86
|
getLeagueSeasons(leagueId: number, options?: SearchOptions): Promise<{
|
|
74
87
|
data: APILeagueSeasonList;
|
|
75
88
|
maxAge: number;
|
|
76
89
|
status: number;
|
|
77
90
|
path: string;
|
|
78
91
|
}>;
|
|
92
|
+
/** Get Legend League season rankings by season Id. */
|
|
79
93
|
getSeasonRankings(leagueId: number, seasonId: string, options?: SearchOptions): Promise<{
|
|
80
94
|
data: APIPlayerSeasonRankingList;
|
|
81
95
|
maxAge: number;
|
|
82
96
|
status: number;
|
|
83
97
|
path: string;
|
|
84
98
|
}>;
|
|
99
|
+
/** Get list of Clan War Leagues. */
|
|
85
100
|
getWarLeagues(options?: SearchOptions): Promise<{
|
|
86
101
|
data: APIWarLeagueList;
|
|
87
102
|
maxAge: number;
|
|
88
103
|
status: number;
|
|
89
104
|
path: string;
|
|
90
105
|
}>;
|
|
106
|
+
/** Get info about a Clan War League. */
|
|
91
107
|
getWarLeague(leagueId: number, options?: OverrideOptions): Promise<{
|
|
92
108
|
data: APIWarLeague;
|
|
93
109
|
maxAge: number;
|
|
94
110
|
status: number;
|
|
95
111
|
path: string;
|
|
96
112
|
}>;
|
|
113
|
+
/** Get list of Locations. */
|
|
97
114
|
getLocations(options?: SearchOptions): Promise<{
|
|
98
115
|
data: APILocationList;
|
|
99
116
|
maxAge: number;
|
|
100
117
|
status: number;
|
|
101
118
|
path: string;
|
|
102
119
|
}>;
|
|
120
|
+
/** Get info about a Location. */
|
|
103
121
|
getLocation(locationId: number, options?: OverrideOptions): Promise<{
|
|
104
122
|
data: APILocation;
|
|
105
123
|
maxAge: number;
|
|
106
124
|
status: number;
|
|
107
125
|
path: string;
|
|
108
126
|
}>;
|
|
127
|
+
/** Get clan rankings for a specific location. */
|
|
109
128
|
getClanRanks(locationId: number | string, options?: SearchOptions): Promise<{
|
|
110
129
|
data: APIClanRankingList;
|
|
111
130
|
maxAge: number;
|
|
112
131
|
status: number;
|
|
113
132
|
path: string;
|
|
114
133
|
}>;
|
|
134
|
+
/** Get player rankings for a specific location. */
|
|
115
135
|
getPlayerRanks(locationId: number | string, options?: SearchOptions): Promise<{
|
|
116
136
|
data: APIPlayerRankingList;
|
|
117
137
|
maxAge: number;
|
|
118
138
|
status: number;
|
|
119
139
|
path: string;
|
|
120
140
|
}>;
|
|
141
|
+
/** Get clan versus rankings for a specific location. */
|
|
121
142
|
getVersusClanRanks(locationId: number | string, options?: SearchOptions): Promise<{
|
|
122
143
|
data: APIClanVersusRankingList;
|
|
123
144
|
maxAge: number;
|
|
124
145
|
status: number;
|
|
125
146
|
path: string;
|
|
126
147
|
}>;
|
|
148
|
+
/** Get player versus rankings for a specific location. */
|
|
127
149
|
getVersusPlayerRanks(locationId: number | string, options?: SearchOptions): Promise<{
|
|
128
150
|
data: APIPlayerVersusRankingList;
|
|
129
151
|
maxAge: number;
|
|
130
152
|
status: number;
|
|
131
153
|
path: string;
|
|
132
154
|
}>;
|
|
155
|
+
/** Get list of clan labels. */
|
|
133
156
|
getClanLabels(options?: SearchOptions): Promise<{
|
|
134
157
|
data: APILabelList;
|
|
135
158
|
maxAge: number;
|
|
136
159
|
status: number;
|
|
137
160
|
path: string;
|
|
138
161
|
}>;
|
|
162
|
+
/** Get list of player labels. */
|
|
139
163
|
getPlayerLabels(options?: SearchOptions): Promise<{
|
|
140
164
|
data: APILabelList;
|
|
141
165
|
maxAge: number;
|
|
142
166
|
status: number;
|
|
143
167
|
path: string;
|
|
144
168
|
}>;
|
|
169
|
+
/** Get info about gold pass season. */
|
|
145
170
|
getGoldPassSeason(options?: OverrideOptions): Promise<{
|
|
146
171
|
data: APIGoldPassSeason;
|
|
147
172
|
maxAge: number;
|
package/dist/rest/RESTManager.js
CHANGED
|
@@ -8,90 +8,114 @@ class RESTManager {
|
|
|
8
8
|
constructor(options) {
|
|
9
9
|
this.handler = new RequestHandler_1.RequestHandler(options);
|
|
10
10
|
}
|
|
11
|
+
/** Search all clans by name and/or filtering the results using various criteria. */
|
|
11
12
|
getClans(options) {
|
|
12
13
|
const query = Util_1.Util.queryString(options);
|
|
13
14
|
return this.handler.request(`/clans?${query}`);
|
|
14
15
|
}
|
|
16
|
+
/** Get information about a clan. */
|
|
15
17
|
getClan(clanTag, options) {
|
|
16
18
|
return this.handler.request(`/clans/${Util_1.Util.encodeTag(clanTag)}`, options);
|
|
17
19
|
}
|
|
20
|
+
/** Get list of clan members. */
|
|
18
21
|
getClanMembers(clanTag, options) {
|
|
19
22
|
const query = Util_1.Util.queryString(options);
|
|
20
23
|
return this.handler.request(`/clans/${Util_1.Util.encodeTag(clanTag)}/members?${query}`, options);
|
|
21
24
|
}
|
|
25
|
+
/** Get clan war log. */
|
|
22
26
|
getClanWarLog(clanTag, options) {
|
|
23
27
|
const query = Util_1.Util.queryString(options);
|
|
24
28
|
return this.handler.request(`/clans/${Util_1.Util.encodeTag(clanTag)}/warlog?${query}`, options);
|
|
25
29
|
}
|
|
30
|
+
/** Get info about currently running war in the clan. */
|
|
26
31
|
getCurrentWar(clanTag, options) {
|
|
27
32
|
return this.handler.request(`/clans/${Util_1.Util.encodeTag(clanTag)}/currentwar`, options);
|
|
28
33
|
}
|
|
34
|
+
/** Get information about clan war league. */
|
|
29
35
|
getClanWarLeagueGroup(clanTag, options) {
|
|
30
36
|
return this.handler.request(`/clans/${Util_1.Util.encodeTag(clanTag)}/currentwar/leaguegroup`, options);
|
|
31
37
|
}
|
|
38
|
+
/** Get info about a CWL round by WarTag. */
|
|
32
39
|
getClanWarLeagueRound(warTag, options) {
|
|
33
40
|
return this.handler.request(`/clanwarleagues/wars/${Util_1.Util.encodeTag(warTag)}`, options);
|
|
34
41
|
}
|
|
42
|
+
/** Get information about a player by tag. */
|
|
35
43
|
getPlayer(playerTag, options) {
|
|
36
44
|
return this.handler.request(`/players/${Util_1.Util.encodeTag(playerTag)}`, options);
|
|
37
45
|
}
|
|
38
|
-
|
|
46
|
+
/** Verify Player API token that can be found from the Game settings. */
|
|
47
|
+
verifyPlayerToken(playerTag, token, options) {
|
|
39
48
|
const opts = { method: 'POST', body: JSON.stringify({ token }), ...options };
|
|
40
49
|
return this.handler.request(`/players/${Util_1.Util.encodeTag(playerTag)}/verifytoken`, opts);
|
|
41
50
|
}
|
|
51
|
+
/** Get list of Leagues. */
|
|
42
52
|
getLeagues(options) {
|
|
43
53
|
const query = Util_1.Util.queryString(options);
|
|
44
54
|
return this.handler.request(`/leagues?${query}`, options);
|
|
45
55
|
}
|
|
56
|
+
/** Get a League info. */
|
|
46
57
|
getLeague(leagueId, options) {
|
|
47
58
|
return this.handler.request(`/leagues/${leagueId}`, options);
|
|
48
59
|
}
|
|
60
|
+
/** Get Legend League season Ids. */
|
|
49
61
|
getLeagueSeasons(leagueId, options) {
|
|
50
62
|
const query = Util_1.Util.queryString(options);
|
|
51
63
|
return this.handler.request(`/leagues/${leagueId}/seasons?${query}`, options);
|
|
52
64
|
}
|
|
65
|
+
/** Get Legend League season rankings by season Id. */
|
|
53
66
|
getSeasonRankings(leagueId, seasonId, options) {
|
|
54
67
|
const query = Util_1.Util.queryString(options);
|
|
55
68
|
return this.handler.request(`/leagues/${leagueId}/seasons/${seasonId}?${query}`, options);
|
|
56
69
|
}
|
|
70
|
+
/** Get list of Clan War Leagues. */
|
|
57
71
|
getWarLeagues(options) {
|
|
58
72
|
const query = Util_1.Util.queryString(options);
|
|
59
73
|
return this.handler.request(`/warleagues?${query}`, options);
|
|
60
74
|
}
|
|
75
|
+
/** Get info about a Clan War League. */
|
|
61
76
|
getWarLeague(leagueId, options) {
|
|
62
77
|
return this.handler.request(`/warleagues/${leagueId}`, options);
|
|
63
78
|
}
|
|
79
|
+
/** Get list of Locations. */
|
|
64
80
|
getLocations(options) {
|
|
65
81
|
const query = Util_1.Util.queryString(options);
|
|
66
82
|
return this.handler.request(`/locations?${query}`, options);
|
|
67
83
|
}
|
|
84
|
+
/** Get info about a Location. */
|
|
68
85
|
getLocation(locationId, options) {
|
|
69
86
|
return this.handler.request(`/locations/${locationId}`, options);
|
|
70
87
|
}
|
|
88
|
+
/** Get clan rankings for a specific location. */
|
|
71
89
|
getClanRanks(locationId, options) {
|
|
72
90
|
const query = Util_1.Util.queryString(options);
|
|
73
91
|
return this.handler.request(`/locations/${locationId}/rankings/clans?${query}`, options);
|
|
74
92
|
}
|
|
93
|
+
/** Get player rankings for a specific location. */
|
|
75
94
|
getPlayerRanks(locationId, options) {
|
|
76
95
|
const query = Util_1.Util.queryString(options);
|
|
77
96
|
return this.handler.request(`/locations/${locationId}/rankings/players?${query}`, options);
|
|
78
97
|
}
|
|
98
|
+
/** Get clan versus rankings for a specific location. */
|
|
79
99
|
getVersusClanRanks(locationId, options) {
|
|
80
100
|
const query = Util_1.Util.queryString(options);
|
|
81
101
|
return this.handler.request(`/locations/${locationId}/rankings/clans-versus?${query}`, options);
|
|
82
102
|
}
|
|
103
|
+
/** Get player versus rankings for a specific location. */
|
|
83
104
|
getVersusPlayerRanks(locationId, options) {
|
|
84
105
|
const query = Util_1.Util.queryString(options);
|
|
85
106
|
return this.handler.request(`/locations/${locationId}/rankings/players-versus?${query}`, options);
|
|
86
107
|
}
|
|
108
|
+
/** Get list of clan labels. */
|
|
87
109
|
getClanLabels(options) {
|
|
88
110
|
const query = Util_1.Util.queryString(options);
|
|
89
111
|
return this.handler.request(`/labels/clans?${query}`, options);
|
|
90
112
|
}
|
|
113
|
+
/** Get list of player labels. */
|
|
91
114
|
getPlayerLabels(options) {
|
|
92
115
|
const query = Util_1.Util.queryString(options);
|
|
93
116
|
return this.handler.request(`/labels/players?${query}`, options);
|
|
94
117
|
}
|
|
118
|
+
/** Get info about gold pass season. */
|
|
95
119
|
getGoldPassSeason(options) {
|
|
96
120
|
return this.handler.request('/goldpass/seasons/current', options);
|
|
97
121
|
}
|
|
@@ -74,8 +74,9 @@ class RequestHandler {
|
|
|
74
74
|
if (!res && retries < (options.retryLimit ?? this.retryLimit))
|
|
75
75
|
return this.exec(path, options, ++retries);
|
|
76
76
|
if (res?.status === 403 && data?.reason === 'accessDenied.invalidIp' && this.email && this.password) {
|
|
77
|
-
await this.login();
|
|
78
|
-
|
|
77
|
+
const keys = await this.reValidateKeys().then(() => this.login());
|
|
78
|
+
if (keys.length)
|
|
79
|
+
return this.exec(path, options, ++retries);
|
|
79
80
|
}
|
|
80
81
|
const maxAge = Number(res?.headers.get('cache-control')?.split('=')?.[1] ?? 0) * 1000;
|
|
81
82
|
if (res?.status === 403 && !data?.message)
|
|
@@ -115,6 +116,7 @@ class RequestHandler {
|
|
|
115
116
|
async login() {
|
|
116
117
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/login`, {
|
|
117
118
|
method: 'POST',
|
|
119
|
+
timeout: 10000,
|
|
118
120
|
headers: { 'Content-Type': 'application/json' },
|
|
119
121
|
body: JSON.stringify({ email: this.email, password: this.password })
|
|
120
122
|
});
|
|
@@ -127,14 +129,14 @@ class RequestHandler {
|
|
|
127
129
|
const ip = await this.getIp();
|
|
128
130
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/list`, {
|
|
129
131
|
method: 'POST',
|
|
132
|
+
timeout: 10000,
|
|
130
133
|
headers: { 'Content-Type': 'application/json', cookie }
|
|
131
134
|
});
|
|
132
135
|
const data = await res.json();
|
|
133
136
|
// Get all available keys from the developer site.
|
|
134
137
|
const keys = (data.keys ?? []);
|
|
135
138
|
// Revoke keys for specified key name but not matching current IP address.
|
|
136
|
-
const
|
|
137
|
-
for (const key of expiredKeys) {
|
|
139
|
+
for (const key of keys.filter((key) => key.name === this.keyName && !key.cidrRanges.includes(ip))) {
|
|
138
140
|
if (!(await this.revokeKey(key.id, cookie)))
|
|
139
141
|
continue;
|
|
140
142
|
const index = keys.findIndex(({ id }) => id === key.id);
|
|
@@ -167,6 +169,7 @@ class RequestHandler {
|
|
|
167
169
|
async revokeKey(keyId, cookie) {
|
|
168
170
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/revoke`, {
|
|
169
171
|
method: 'POST',
|
|
172
|
+
timeout: 10000,
|
|
170
173
|
body: JSON.stringify({ id: keyId }),
|
|
171
174
|
headers: { 'Content-Type': 'application/json', cookie }
|
|
172
175
|
});
|
|
@@ -175,6 +178,7 @@ class RequestHandler {
|
|
|
175
178
|
async createKey(cookie, ip) {
|
|
176
179
|
const res = await (0, node_fetch_1.default)(`${Constants_1.DEV_SITE_API_BASE_URL}/apikey/create`, {
|
|
177
180
|
method: 'POST',
|
|
181
|
+
timeout: 10000,
|
|
178
182
|
headers: { 'Content-Type': 'application/json', cookie },
|
|
179
183
|
body: JSON.stringify({
|
|
180
184
|
cidrRanges: [ip],
|
|
@@ -186,7 +190,7 @@ class RequestHandler {
|
|
|
186
190
|
return data.key;
|
|
187
191
|
}
|
|
188
192
|
async getIp() {
|
|
189
|
-
return (0, node_fetch_1.default)('https://api.ipify.org/').then((res) => res.text());
|
|
193
|
+
return (0, node_fetch_1.default)('https://api.ipify.org/', { timeout: 10000 }).then((res) => res.text());
|
|
190
194
|
}
|
|
191
195
|
}
|
|
192
196
|
exports.RequestHandler = RequestHandler;
|
package/dist/rest/Throttler.d.ts
CHANGED
package/dist/struct/Clan.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { ChatLanguage } from './ChatLanguage';
|
|
2
3
|
import { ClanMember } from './ClanMember';
|
|
3
4
|
import { Client } from '../client/Client';
|
|
@@ -59,5 +60,5 @@ export declare class Clan {
|
|
|
59
60
|
members: ClanMember[];
|
|
60
61
|
constructor(client: Client, data: APIClan);
|
|
61
62
|
/** Get {@link Player} information for every Player in the clan. */
|
|
62
|
-
fetchMembers(): Promise<Player[]>;
|
|
63
|
+
fetchMembers(options?: OverrideOptions): Promise<Player[]>;
|
|
63
64
|
}
|
package/dist/struct/Clan.js
CHANGED
|
@@ -35,8 +35,8 @@ class Clan {
|
|
|
35
35
|
this.members = data.memberList?.map((mem) => new ClanMember_1.ClanMember(this.client, mem)) ?? []; // eslint-disable-line
|
|
36
36
|
}
|
|
37
37
|
/** Get {@link Player} information for every Player in the clan. */
|
|
38
|
-
async fetchMembers() {
|
|
39
|
-
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ignoreRateLimit: true }))))
|
|
38
|
+
async fetchMembers(options) {
|
|
39
|
+
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ...options, ignoreRateLimit: true }))))
|
|
40
40
|
.filter((res) => res.status === 'fulfilled')
|
|
41
41
|
.map((res) => res.value);
|
|
42
42
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { Client } from '../client/Client';
|
|
2
3
|
import { APIClanMember } from '../types';
|
|
3
4
|
import { League } from './League';
|
|
@@ -27,5 +28,5 @@ export declare class ClanMember {
|
|
|
27
28
|
received: number;
|
|
28
29
|
constructor(client: Client, data: APIClanMember);
|
|
29
30
|
/** Fetch detailed clan info for the member's clan. */
|
|
30
|
-
fetch(): Promise<import("./Player").Player>;
|
|
31
|
+
fetch(options?: OverrideOptions): Promise<import("./Player").Player>;
|
|
31
32
|
}
|
|
@@ -21,8 +21,8 @@ class ClanMember {
|
|
|
21
21
|
this.received = data.donationsReceived;
|
|
22
22
|
}
|
|
23
23
|
/** Fetch detailed clan info for the member's clan. */
|
|
24
|
-
async fetch() {
|
|
25
|
-
return this.client.getPlayer(this.tag);
|
|
24
|
+
async fetch(options) {
|
|
25
|
+
return this.client.getPlayer(this.tag, options);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
exports.ClanMember = ClanMember;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { APIClanWarLeagueClan, APIClanWarLeagueClanMember, APIClanWarLeagueGroup, APIClanWarLeagueRound } from '../types';
|
|
2
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
2
3
|
import { Client } from '../client/Client';
|
|
3
4
|
import { ClanWar } from './ClanWar';
|
|
4
5
|
import { Player } from './Player';
|
|
@@ -28,7 +29,7 @@ export declare class ClanWarLeagueClan {
|
|
|
28
29
|
members: ClanWarLeagueClanMember[];
|
|
29
30
|
constructor(client: Client, data: APIClanWarLeagueClan);
|
|
30
31
|
/** Get {@link Player} information for every members that are in the CWL group. */
|
|
31
|
-
fetchMembers(): Promise<Player[]>;
|
|
32
|
+
fetchMembers(options?: OverrideOptions): Promise<Player[]>;
|
|
32
33
|
}
|
|
33
34
|
/** Represents a Round of CWL Group. */
|
|
34
35
|
export declare class ClanWarLeagueRound {
|
|
@@ -53,9 +54,10 @@ export declare class ClanWarLeagueGroup {
|
|
|
53
54
|
/**
|
|
54
55
|
* This returns an array of {@link ClanWar} which fetches all wars in parallel.
|
|
55
56
|
* @param clanTag Optional clan tag. If present, this will only return wars which belong to this clan.
|
|
57
|
+
* @param options Override options for the request.
|
|
56
58
|
*/
|
|
57
|
-
getWars(clanTag?: string): Promise<ClanWar[]>;
|
|
59
|
+
getWars(clanTag?: string, options?: OverrideOptions): Promise<ClanWar[]>;
|
|
58
60
|
private _getCurrentWars;
|
|
59
|
-
/** Returns
|
|
61
|
+
/** Returns the index of the round for this specified warTag. */
|
|
60
62
|
getRoundIndex(warTag: string): number | null;
|
|
61
63
|
}
|
|
@@ -22,8 +22,8 @@ class ClanWarLeagueClan {
|
|
|
22
22
|
this.members = data.members.map((mem) => new ClanWarLeagueClanMember(mem));
|
|
23
23
|
}
|
|
24
24
|
/** Get {@link Player} information for every members that are in the CWL group. */
|
|
25
|
-
async fetchMembers() {
|
|
26
|
-
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ignoreRateLimit: true }))))
|
|
25
|
+
async fetchMembers(options) {
|
|
26
|
+
return (await Promise.allSettled(this.members.map((m) => this.client.getPlayer(m.tag, { ...options, ignoreRateLimit: true }))))
|
|
27
27
|
.filter((res) => res.status === 'fulfilled')
|
|
28
28
|
.map((res) => res.value);
|
|
29
29
|
}
|
|
@@ -49,19 +49,20 @@ class ClanWarLeagueGroup {
|
|
|
49
49
|
/**
|
|
50
50
|
* This returns an array of {@link ClanWar} which fetches all wars in parallel.
|
|
51
51
|
* @param clanTag Optional clan tag. If present, this will only return wars which belong to this clan.
|
|
52
|
+
* @param options Override options for the request.
|
|
52
53
|
*/
|
|
53
|
-
async getWars(clanTag) {
|
|
54
|
+
async getWars(clanTag, options) {
|
|
54
55
|
const rounds = this.rounds.filter((round) => !round.warTags.includes('#0'));
|
|
55
56
|
if (!rounds.length)
|
|
56
57
|
return [];
|
|
57
58
|
const warTags = rounds.map((round) => round.warTags).flat();
|
|
58
|
-
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ignoreRateLimit: true })));
|
|
59
|
+
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ...options, ignoreRateLimit: true })));
|
|
59
60
|
return wars
|
|
60
61
|
.filter((res) => res.status === 'fulfilled')
|
|
61
62
|
.map((res) => res.value)
|
|
62
63
|
.filter((war) => (clanTag ? war.clan.tag === clanTag : true));
|
|
63
64
|
}
|
|
64
|
-
async _getCurrentWars(clanTag) {
|
|
65
|
+
async _getCurrentWars(clanTag, options) {
|
|
65
66
|
const rounds = this.rounds.filter((round) => !round.warTags.includes('#0'));
|
|
66
67
|
if (!rounds.length)
|
|
67
68
|
return [];
|
|
@@ -70,13 +71,13 @@ class ClanWarLeagueGroup {
|
|
|
70
71
|
.map((round) => round.warTags)
|
|
71
72
|
.flat()
|
|
72
73
|
.reverse();
|
|
73
|
-
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ignoreRateLimit: true })));
|
|
74
|
+
const wars = await Promise.allSettled(warTags.map((warTag) => this.client.getClanWarLeagueRound({ warTag, clanTag }, { ...options, ignoreRateLimit: true })));
|
|
74
75
|
return wars
|
|
75
76
|
.filter((res) => res.status === 'fulfilled')
|
|
76
77
|
.map((res) => res.value)
|
|
77
78
|
.filter((war) => war.clan.tag === clanTag);
|
|
78
79
|
}
|
|
79
|
-
/** Returns
|
|
80
|
+
/** Returns the index of the round for this specified warTag. */
|
|
80
81
|
getRoundIndex(warTag) {
|
|
81
82
|
return this.rounds.find((round) => round.warTags.includes(warTag))?.round ?? null;
|
|
82
83
|
}
|
package/dist/struct/Player.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { LegendStatistics } from './LegendStatistics';
|
|
2
3
|
import { Achievement } from './Achievement';
|
|
3
4
|
import { Hero, Spell, Troop } from './Unit';
|
|
@@ -63,7 +64,7 @@ export declare class Player {
|
|
|
63
64
|
heroes: Hero[];
|
|
64
65
|
constructor(client: Client, data: APIPlayer);
|
|
65
66
|
/** Fetch detailed clan info for the player's clan. */
|
|
66
|
-
fetchClan(): Promise<import("./Clan").Clan | null>;
|
|
67
|
+
fetchClan(options?: OverrideOptions): Promise<import("./Clan").Clan | null>;
|
|
67
68
|
/** An array of the player's home base troops. */
|
|
68
69
|
get homeTroops(): Troop[];
|
|
69
70
|
/** An array of the player's builder base troops. */
|
package/dist/struct/Player.js
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Player = void 0;
|
|
4
4
|
const Constants_1 = require("../util/Constants");
|
|
5
|
+
const raw_json_1 = require("../util/raw.json");
|
|
5
6
|
const LegendStatistics_1 = require("./LegendStatistics");
|
|
6
7
|
const Achievement_1 = require("./Achievement");
|
|
7
8
|
const Unit_1 = require("./Unit");
|
|
8
9
|
const PlayerClan_1 = require("./PlayerClan");
|
|
9
10
|
const League_1 = require("./League");
|
|
10
11
|
const Label_1 = require("./Label");
|
|
12
|
+
const UNIT_NAMES = [...raw_json_1.RAW_UNITS.map((unit) => unit.name), ...raw_json_1.RAW_SUPER_UNITS.map((unit) => unit.name)];
|
|
11
13
|
/** Represents a Clash of Clans Player. */
|
|
12
14
|
class Player {
|
|
13
15
|
constructor(client, data) {
|
|
@@ -36,15 +38,15 @@ class Player {
|
|
|
36
38
|
this.legendStatistics = data.legendStatistics ? new LegendStatistics_1.LegendStatistics(data.legendStatistics) : null;
|
|
37
39
|
this.achievements = data.achievements.map((data) => new Achievement_1.Achievement(data));
|
|
38
40
|
this.labels = data.labels.map((data) => new Label_1.Label(data));
|
|
39
|
-
this.troops = data.troops.map((
|
|
40
|
-
this.spells = data.spells.map((
|
|
41
|
-
this.heroes = data.heroes.map((
|
|
41
|
+
this.troops = data.troops.filter((unit) => UNIT_NAMES.includes(unit.name)).map((unit) => new Unit_1.Troop(data, unit));
|
|
42
|
+
this.spells = data.spells.filter((unit) => UNIT_NAMES.includes(unit.name)).map((unit) => new Unit_1.Spell(data, unit));
|
|
43
|
+
this.heroes = data.heroes.filter((unit) => UNIT_NAMES.includes(unit.name)).map((unit) => new Unit_1.Hero(data, unit));
|
|
42
44
|
}
|
|
43
45
|
/** Fetch detailed clan info for the player's clan. */
|
|
44
|
-
async fetchClan() {
|
|
46
|
+
async fetchClan(options) {
|
|
45
47
|
if (!this.clan)
|
|
46
48
|
return null;
|
|
47
|
-
return this.client.getClan(this.clan.tag);
|
|
49
|
+
return this.client.getClan(this.clan.tag, options);
|
|
48
50
|
}
|
|
49
51
|
/** An array of the player's home base troops. */
|
|
50
52
|
get homeTroops() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OverrideOptions } from '../rest/RequestHandler';
|
|
1
2
|
import { Client } from '../client/Client';
|
|
2
3
|
import { APIPlayerClan } from '../types';
|
|
3
4
|
import { Badge } from './Badge';
|
|
@@ -14,5 +15,5 @@ export declare class PlayerClan {
|
|
|
14
15
|
badge: Badge;
|
|
15
16
|
constructor(_client: Client, data: APIPlayerClan);
|
|
16
17
|
/** Fetch detailed clan info for the player's clan. */
|
|
17
|
-
fetch(): Promise<import("./Clan").Clan>;
|
|
18
|
+
fetch(options?: OverrideOptions): Promise<import("./Clan").Clan>;
|
|
18
19
|
}
|
|
@@ -12,8 +12,8 @@ class PlayerClan {
|
|
|
12
12
|
this.badge = new Badge_1.Badge(data.badgeUrls);
|
|
13
13
|
}
|
|
14
14
|
/** Fetch detailed clan info for the player's clan. */
|
|
15
|
-
fetch() {
|
|
16
|
-
return this._client.getClan(this.tag);
|
|
15
|
+
fetch(options) {
|
|
16
|
+
return this._client.getClan(this.tag, options);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
exports.PlayerClan = PlayerClan;
|
package/dist/struct/Unit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APIPlayerItem } from '../types';
|
|
1
|
+
import { APIPlayerItem, APIPlayer } from '../types';
|
|
2
2
|
/** Represents a player's unit. */
|
|
3
3
|
export declare class Unit {
|
|
4
4
|
/** The name of this unit. */
|
|
@@ -9,7 +9,35 @@ export declare class Unit {
|
|
|
9
9
|
maxLevel: number;
|
|
10
10
|
/** The village type of this unit. */
|
|
11
11
|
village: 'home' | 'builderBase';
|
|
12
|
-
|
|
12
|
+
/** Id of this unit. */
|
|
13
|
+
id: number;
|
|
14
|
+
/** Housing space of this unit. */
|
|
15
|
+
housingSpace: number;
|
|
16
|
+
/** Town/Builder hall's max level of this unit. */
|
|
17
|
+
hallMaxLevel: number;
|
|
18
|
+
/** Unlock Town/Builder Hall level of this unit. */
|
|
19
|
+
unlockHallLevel: number;
|
|
20
|
+
/** Unlock cost of this unit. */
|
|
21
|
+
unlockCost: number;
|
|
22
|
+
/** Unlock time of this unit. */
|
|
23
|
+
unlockTime: number;
|
|
24
|
+
/** Unlock resource of this unit. */
|
|
25
|
+
unlockResource: string;
|
|
26
|
+
/** Unlock building of this unit. */
|
|
27
|
+
unlockBuilding: string;
|
|
28
|
+
/** Unlock building level of this unit. */
|
|
29
|
+
unlockBuildingLevel: number;
|
|
30
|
+
/** Upgrade cost of this unit. */
|
|
31
|
+
upgradeCost: number;
|
|
32
|
+
/** Upgrade resource of this unit. */
|
|
33
|
+
upgradeResource: string;
|
|
34
|
+
/** Upgrade time of this unit. */
|
|
35
|
+
upgradeTime: number;
|
|
36
|
+
/** @internal */
|
|
37
|
+
minOriginalLevel: number | null;
|
|
38
|
+
/** @internal */
|
|
39
|
+
originalName: string | null;
|
|
40
|
+
constructor(data: APIPlayer, unit: APIPlayerItem);
|
|
13
41
|
/** Whether the unit belongs to the home base. */
|
|
14
42
|
get isHomeBase(): boolean;
|
|
15
43
|
/** Whether the unit belongs to the builder base. */
|
|
@@ -22,8 +50,13 @@ export declare class Unit {
|
|
|
22
50
|
/** Represents a player's troop. */
|
|
23
51
|
export declare class Troop extends Unit {
|
|
24
52
|
name: string;
|
|
25
|
-
|
|
26
|
-
|
|
53
|
+
/** Whether this troop is currently active of boosted. */
|
|
54
|
+
isActive: boolean;
|
|
55
|
+
/** Origin troop's minimum level of this super troop. */
|
|
56
|
+
minOriginalLevel: number | null;
|
|
57
|
+
/** Origin troop's name of this super troop. */
|
|
58
|
+
originalName: string | null;
|
|
59
|
+
constructor(data: APIPlayer, unit: APIPlayerItem);
|
|
27
60
|
/** Whether this troop is a Super Troop. */
|
|
28
61
|
get isSuperTroop(): boolean;
|
|
29
62
|
}
|
package/dist/struct/Unit.js
CHANGED
|
@@ -1,14 +1,52 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Hero = exports.Spell = exports.Troop = exports.Unit = void 0;
|
|
4
|
+
const raw_json_1 = require("../util/raw.json");
|
|
4
5
|
const Constants_1 = require("../util/Constants");
|
|
5
6
|
/** Represents a player's unit. */
|
|
6
7
|
class Unit {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
8
|
+
// #endregion static
|
|
9
|
+
constructor(data, unit) {
|
|
10
|
+
this.name = unit.name;
|
|
11
|
+
this.level = unit.level;
|
|
12
|
+
this.maxLevel = unit.maxLevel;
|
|
13
|
+
this.village = unit.village;
|
|
14
|
+
const rawSuperUnit = raw_json_1.RAW_SUPER_UNITS.find((unit) => unit.name === this.name && this.isHomeBase);
|
|
15
|
+
const rawUnit = raw_json_1.RAW_UNITS.find((unit) => unit.name === this.name && unit.village === this.village);
|
|
16
|
+
if (rawSuperUnit) {
|
|
17
|
+
this.id = rawSuperUnit.id;
|
|
18
|
+
this.housingSpace = rawSuperUnit.housingSpace;
|
|
19
|
+
this.originalName = rawSuperUnit.original;
|
|
20
|
+
this.minOriginalLevel = rawSuperUnit.minOriginalLevel;
|
|
21
|
+
const original = raw_json_1.RAW_UNITS.find((unit) => unit.village === 'home' && unit.name === rawSuperUnit.original);
|
|
22
|
+
this.unlockHallLevel = original.levels.findIndex((level) => level >= rawSuperUnit.minOriginalLevel) + 1;
|
|
23
|
+
this.unlockCost = original.unlock.cost;
|
|
24
|
+
this.unlockTime = original.unlock.time;
|
|
25
|
+
this.unlockResource = original.unlock.resource;
|
|
26
|
+
this.unlockBuilding = original.unlock.building;
|
|
27
|
+
this.unlockBuildingLevel = original.unlock.buildingLevel;
|
|
28
|
+
const origin = data.troops.find((troop) => troop.village === 'home' && troop.name === original.name);
|
|
29
|
+
this.level = origin.level;
|
|
30
|
+
this.maxLevel = origin.maxLevel;
|
|
31
|
+
this.upgradeCost = original.upgrade.cost[origin.level - 1] ?? 0;
|
|
32
|
+
this.upgradeResource = original.upgrade.resource;
|
|
33
|
+
this.upgradeTime = original.upgrade.time[origin.level - 1] ?? 0;
|
|
34
|
+
this.hallMaxLevel = original.levels[data.townHallLevel - 1];
|
|
35
|
+
}
|
|
36
|
+
if (rawUnit) {
|
|
37
|
+
this.id = rawUnit.id;
|
|
38
|
+
this.housingSpace = rawUnit.housingSpace;
|
|
39
|
+
this.unlockCost = rawUnit.unlock.cost;
|
|
40
|
+
this.unlockTime = rawUnit.unlock.time;
|
|
41
|
+
this.unlockResource = rawUnit.unlock.resource;
|
|
42
|
+
this.unlockBuilding = rawUnit.unlock.building;
|
|
43
|
+
this.unlockHallLevel = rawUnit.unlock.hall;
|
|
44
|
+
this.unlockBuildingLevel = rawUnit.unlock.buildingLevel;
|
|
45
|
+
this.upgradeResource = rawUnit.upgrade.resource;
|
|
46
|
+
this.upgradeCost = rawUnit.upgrade.cost[this.level - 1] ?? 0;
|
|
47
|
+
this.upgradeTime = rawUnit.upgrade.time[this.level - 1] ?? 0;
|
|
48
|
+
this.hallMaxLevel = rawUnit.levels[(this.village === 'home' ? data.townHallLevel : data.builderHallLevel) - 1];
|
|
49
|
+
}
|
|
12
50
|
}
|
|
13
51
|
/** Whether the unit belongs to the home base. */
|
|
14
52
|
get isHomeBase() {
|
|
@@ -30,13 +68,15 @@ class Unit {
|
|
|
30
68
|
exports.Unit = Unit;
|
|
31
69
|
/** Represents a player's troop. */
|
|
32
70
|
class Troop extends Unit {
|
|
33
|
-
constructor(data) {
|
|
34
|
-
super(data);
|
|
35
|
-
this.
|
|
71
|
+
constructor(data, unit) {
|
|
72
|
+
super(data, unit);
|
|
73
|
+
this.originalName = this.originalName ?? null;
|
|
74
|
+
this.isActive = unit.superTroopIsActive ?? false;
|
|
75
|
+
this.minOriginalLevel = this.minOriginalLevel ?? null;
|
|
36
76
|
}
|
|
37
77
|
/** Whether this troop is a Super Troop. */
|
|
38
78
|
get isSuperTroop() {
|
|
39
|
-
return this.
|
|
79
|
+
return this.isActive || (this.isHomeBase && Constants_1.SUPER_TROOPS.includes(this.name));
|
|
40
80
|
}
|
|
41
81
|
}
|
|
42
82
|
exports.Troop = Troop;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export declare type APIWarState = 'notInWar' | 'preparation' | 'inWar' | 'warEnded';
|
|
2
|
-
export declare type APIRole = 'member' | 'admin' | 'coLeader' | 'leader';
|
|
3
1
|
export interface APIPaging {
|
|
4
2
|
cursors?: APICursors;
|
|
5
3
|
}
|
|
@@ -62,7 +60,7 @@ export interface APIClan {
|
|
|
62
60
|
export interface APIClanMember {
|
|
63
61
|
name: string;
|
|
64
62
|
tag: string;
|
|
65
|
-
role:
|
|
63
|
+
role: 'member' | 'admin' | 'coLeader' | 'leader';
|
|
66
64
|
expLevel: number;
|
|
67
65
|
league: APILeague;
|
|
68
66
|
trophies: number;
|
|
@@ -79,7 +77,7 @@ export interface APIClanMemberList {
|
|
|
79
77
|
}
|
|
80
78
|
/** /clans/{clanTag}/currentwar and /clanwarleagues/wars/{warTag} */
|
|
81
79
|
export interface APIClanWar {
|
|
82
|
-
state:
|
|
80
|
+
state: 'notInWar' | 'preparation' | 'inWar' | 'warEnded';
|
|
83
81
|
teamSize: number;
|
|
84
82
|
startTime: string;
|
|
85
83
|
preparationStartTime: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "RAW_UNITS": [{ "id": 0, "name": "Barbarian", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 1, "cost": 100, "time": 10, "resource": "Elixir", "building": "Barracks", "buildingLevel": 1 }, "upgrade": { "cost": [25000, 100000, 300000, 1000000, 2000000, 3000000, 5000000, 9500000, 15000000], "time": [21600, 43200, 86400, 129600, 216000, 345600, 604800, 1036800, 1209600], "resource": "Elixir" }, "levels": [1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 9, 10] }, { "id": 1, "name": "Archer", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 2, "cost": 500, "time": 60, "resource": "Elixir", "building": "Barracks", "buildingLevel": 2 }, "upgrade": { "cost": [40000, 160000, 480000, 1300000, 2500000, 3500000, 5500000, 10000000, 15500000], "time": [43200, 86400, 129600, 172800, 216000, 345600, 604800, 1036800, 1209600], "resource": "Elixir" }, "levels": [0, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 9, 10] }, { "id": 2, "name": "Goblin", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 2, "cost": 5000, "time": 3600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 4 }, "upgrade": { "cost": [50000, 200000, 600000, 1200000, 2500000, 4000000, 9500000], "time": [43200, 86400, 129600, 172800, 302400, 518400, 1036800], "resource": "Elixir" }, "levels": [0, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 8] }, { "id": 3, "name": "Giant", "housingSpace": 5, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 2, "cost": 2500, "time": 600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 3 }, "upgrade": { "cost": [50000, 200000, 600000, 1500000, 2500000, 4000000, 6000000, 10500000, 15000000], "time": [32400, 64800, 129600, 216000, 345600, 432000, 777600, 1209600, 1296000], "resource": "Elixir" }, "levels": [0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10] }, { "id": 4, "name": "Wall Breaker", "housingSpace": 2, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 3, "cost": 10000, "time": 14400, "resource": "Elixir", "building": "Barracks", "buildingLevel": 5 }, "upgrade": { "cost": [100000, 250000, 750000, 1500000, 3500000, 7500000, 11500000, 14000000, 16000000], "time": [43200, 86400, 129600, 172800, 345600, 604800, 950400, 1296000, 1382400], "resource": "Elixir" }, "levels": [0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10] }, { "id": 5, "name": "Balloon", "housingSpace": 5, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 4, "cost": 80000, "time": 28800, "resource": "Elixir", "building": "Barracks", "buildingLevel": 6 }, "upgrade": { "cost": [150000, 450000, 900000, 1800000, 3500000, 7500000, 12000000, 14000000, 18000000], "time": [43200, 86400, 172800, 259200, 345600, 691200, 1209600, 1382400, 1555200], "resource": "Elixir" }, "levels": [0, 0, 0, 2, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10] }, { "id": 6, "name": "Wizard", "housingSpace": 4, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 5, "cost": 240000, "time": 43200, "resource": "Elixir", "building": "Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [150000, 350000, 650000, 1300000, 2600000, 5000000, 8000000, 10000000, 15000000], "time": [43200, 86400, 129600, 172800, 345600, 518400, 777600, 1123200, 1296000], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10] }, { "id": 7, "name": "Healer", "housingSpace": 14, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 6, "cost": 700000, "time": 57600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 8 }, "upgrade": { "cost": [500000, 1000000, 3000000, 9500000, 14500000, 17000000], "time": [129600, 216000, 345600, 1022400, 1296000, 1468800], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 6, 7] }, { "id": 8, "name": "Dragon", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 7, "cost": 1000000, "time": 86400, "resource": "Elixir", "building": "Barracks", "buildingLevel": 9 }, "upgrade": { "cost": [1750000, 2500000, 4000000, 6000000, 8000000, 10000000, 15000000, 18500000], "time": [129600, 259200, 432000, 604800, 777600, 1209600, 1382400, 1555200], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9] }, { "id": 9, "name": "P.E.K.K.A", "housingSpace": 25, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 8, "cost": 1500000, "time": 129600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 10 }, "upgrade": { "cost": [1500000, 2250000, 3200000, 4500000, 6000000, 9000000, 12000000, 15500000], "time": [172800, 302400, 388800, 518400, 604800, 864000, 1209600, 1296000], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 3, 4, 6, 7, 8, 9, 9] }, { "id": 10, "name": "Minion", "housingSpace": 2, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 7, "cost": 300000, "time": 14400, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 1 }, "upgrade": { "cost": [3000, 7000, 15000, 25000, 40000, 90000, 150000, 250000, 300000], "time": [86400, 129600, 172800, 259200, 388800, 604800, 1209600, 1339200, 1425600], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 2, 4, 5, 6, 7, 8, 9, 10] }, { "id": 11, "name": "Hog Rider", "housingSpace": 5, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 7, "cost": 600000, "time": 43200, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 2 }, "upgrade": { "cost": [5000, 9000, 16000, 30000, 50000, 100000, 150000, 240000, 280000, 320000], "time": [108000, 172800, 216000, 345600, 432000, 648000, 993600, 1209600, 1382400, 1468800], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 2, 4, 5, 6, 7, 9, 10, 11] }, { "id": 12, "name": "Valkyrie", "housingSpace": 8, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 8, "cost": 900000, "time": 64800, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 3 }, "upgrade": { "cost": [8000, 12000, 25000, 45000, 90000, 175000, 260000, 310000], "time": [194400, 259200, 345600, 518400, 734400, 1123200, 1382400, 1468800], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 6, 7, 8, 9] }, { "id": 13, "name": "Golem", "housingSpace": 30, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 8, "cost": 1300000, "time": 86400, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 4 }, "upgrade": { "cost": [10000, 20000, 30000, 50000, 75000, 110000, 160000, 200000, 270000, 320000], "time": [216000, 259200, 345600, 432000, 604800, 691200, 907200, 1209600, 1382400, 1468800], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 7, 9, 10, 11] }, { "id": 15, "name": "Witch", "housingSpace": 12, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 9, "cost": 2000000, "time": 172800, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 5 }, "upgrade": { "cost": [50000, 80000, 130000, 200000], "time": [432000, 561600, 820800, 1209600], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 5, 5] }, { "id": 17, "name": "Lava Hound", "housingSpace": 30, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 9, "cost": 2500000, "time": 259200, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 6 }, "upgrade": { "cost": [35000, 60000, 120000, 190000, 270000], "time": [216000, 432000, 777600, 1209600, 1382400], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 6] }, { "id": 22, "name": "Bowler", "housingSpace": 6, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 10, "cost": 3000000, "time": 432000, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [75000, 125000, 200000, 280000, 320000], "time": [518400, 777600, 1209600, 1382400, 1512000], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6] }, { "id": 23, "name": "Baby Dragon", "housingSpace": 10, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 9, "cost": 2000000, "time": 216000, "resource": "Elixir", "building": "Barracks", "buildingLevel": 11 }, "upgrade": { "cost": [2500000, 3500000, 4500000, 7000000, 9000000, 15000000, 17000000], "time": [259200, 432000, 604800, 777600, 1036800, 1339200, 1425600], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 6, 7, 8] }, { "id": 24, "name": "Miner", "housingSpace": 6, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 10, "cost": 3000000, "time": 345600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 12 }, "upgrade": { "cost": [3500000, 4500000, 6000000, 8000000, 10500000, 14000000, 17500000], "time": [259200, 432000, 648000, 907200, 1209600, 1339200, 1468800], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 6, 7, 8] }, { "id": 30, "name": "Ice Wizard", "housingSpace": 4, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 5, "cost": 240000, "time": 43200, "resource": "Elixir", "building": "Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [150000, 450000, 1350000, 2500000, 5000000, 7000000, 9000000, 11000000, 15000000], "time": [43200, 129600, 172800, 259200, 432000, 518400, 864000, 1209600, 1296000], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10] }, { "id": 31, "name": "Raged Barbarian", "housingSpace": 2, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 1, "cost": 1000, "time": 0, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 1 }, "upgrade": { "cost": [3500, 6000, 9000, 50000, 100000, 300000, 330000, 700000, 900000, 1000000, 1200000, 2000000, 2200000, 3000000, 3200000, 3800000, 4000000], "time": [0, 300, 900, 10800, 21600, 43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [2, 4, 6, 8, 10, 12, 14, 16, 18] }, { "id": 32, "name": "Sneaky Archer", "housingSpace": 2, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 2, "cost": 4000, "time": 60, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 2 }, "upgrade": { "cost": [5000, 8000, 12000, 60000, 120000, 320000, 350000, 800000, 1000000, 1100000, 1300000, 2100000, 2300000, 3100000, 3300000, 3900000, 4100000], "time": [180, 600, 1800, 14400, 21600, 43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 4, 6, 8, 10, 12, 14, 16, 18] }, { "id": 33, "name": "Beta Minion", "housingSpace": 2, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 3, "cost": 25000, "time": 1800, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 4 }, "upgrade": { "cost": [50000, 80000, 120000, 250000, 280000, 320000, 360000, 900000, 1100000, 1300000, 1500000, 2300000, 2500000, 3300000, 3500000, 4000000, 4200000], "time": [3600, 10800, 18000, 28800, 43200, 43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 4, 8, 10, 12, 14, 16, 18] }, { "id": 34, "name": "Boxer Giant", "housingSpace": 8, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 3, "cost": 10000, "time": 600, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 3 }, "upgrade": { "cost": [20000, 40000, 60000, 300000, 320000, 340000, 380000, 1000000, 1200000, 1300000, 1500000, 2300000, 2500000, 3300000, 3500000, 4000000, 4200000], "time": [1800, 3600, 7200, 28800, 43200, 43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 4, 8, 10, 12, 14, 16, 18] }, { "id": 35, "name": "Bomber", "housingSpace": 4, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 4, "cost": 100000, "time": 10800, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 5 }, "upgrade": { "cost": [150000, 200000, 250000, 280000, 320000, 340000, 360000, 900000, 1000000, 1200000, 1400000, 2200000, 2400000, 3200000, 3400000, 3900000, 4100000], "time": [10800, 18000, 28800, 43200, 43200, 43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 8, 10, 12, 14, 16, 18] }, { "id": 36, "name": "Super P.E.K.K.A", "housingSpace": 25, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 8, "cost": 1500000, "time": 86400, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 10 }, "upgrade": { "cost": [1600000, 1700000, 1800000, 1900000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4600000, 4800000], "time": [86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 345600, 345600, 345600, 345600, 345600, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 16, 18] }, { "id": 37, "name": "Cannon Cart", "housingSpace": 8, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 5, "cost": 300000, "time": 28800, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1400000, 1600000, 2400000, 2600000, 3400000, 3600000, 4100000, 4300000], "time": [43200, 43200, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 0, 10, 12, 14, 16, 18] }, { "id": 38, "name": "Drop Ship", "housingSpace": 5, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 7, "cost": 1000000, "time": 43200, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 9 }, "upgrade": { "cost": [1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 2000000, 2200000, 2400000, 2600000, 2800000, 3600000, 3800000, 4300000, 4500000], "time": [43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 259200, 259200, 259200, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 14, 16, 18] }, { "id": 41, "name": "Baby Dragon", "housingSpace": 10, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 4, "cost": 150000, "time": 21600, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 6 }, "upgrade": { "cost": [200000, 240000, 280000, 320000, 360000, 380000, 400000, 1000000, 1200000, 1400000, 1600000, 2400000, 2600000, 3400000, 3600000, 4100000, 4300000], "time": [18000, 28800, 43200, 43200, 43200, 43200, 43200, 86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 8, 10, 12, 14, 16, 18] }, { "id": 42, "name": "Night Witch", "housingSpace": 12, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 6, "cost": 500000, "time": 36000, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 8 }, "upgrade": { "cost": [600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1600000, 1800000, 2500000, 2700000, 3500000, 3700000, 4200000, 4400000], "time": [43200, 43200, 86400, 86400, 172800, 172800, 172800, 172800, 172800, 172800, 172800, 259200, 259200, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 0, 0, 12, 14, 16, 18] }, { "id": 45, "name": "Battle Ram", "housingSpace": 4, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 2, "cost": 2500, "time": 600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 3 }, "upgrade": { "cost": [100000], "time": [86400], "resource": "Elixir" }, "levels": [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, { "id": 47, "name": "Royal Ghost", "housingSpace": 8, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 5, "cost": 240000, "time": 43200, "resource": "Elixir", "building": "Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [5000], "time": [86400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 7, 7] }, { "id": 48, "name": "Pumpkin Barbarian", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 1, "cost": 100, "time": 10, "resource": "Elixir", "building": "Barracks", "buildingLevel": 1 }, "upgrade": { "cost": [50000, 150000, 500000, 1500000, 4500000, 6000000], "time": [21600, 86400, 259200, 432000, 864000, 1209600], "resource": "Elixir" }, "levels": [1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 7, 7, 7] }, { "id": 50, "name": "Giant Skeleton", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 2, "cost": 2500, "time": 600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 3 }, "upgrade": { "cost": [100000, 250000, 750000, 2250000, 5000000, 6000000, 9500000], "time": [86400, 172800, 259200, 432000, 864000, 1036800, 1209600], "resource": "Elixir" }, "levels": [0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8] }, { "id": 51, "name": "Wall Wrecker", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "siege", "unlock": { "hall": 12, "cost": 7500000, "time": 518400, "resource": "Elixir", "building": "Workshop", "buildingLevel": 1 }, "upgrade": { "cost": [6000000, 8000000, 14000000], "time": [691200, 864000, 1382400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4] }, { "id": 52, "name": "Battle Blimp", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "siege", "unlock": { "hall": 12, "cost": 9000000, "time": 691200, "resource": "Elixir", "building": "Workshop", "buildingLevel": 2 }, "upgrade": { "cost": [6000000, 8000000, 14000000], "time": [691200, 864000, 1382400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4] }, { "id": 53, "name": "Yeti", "housingSpace": 18, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 12, "cost": 5000000, "time": 777600, "resource": "Elixir", "building": "Barracks", "buildingLevel": 14 }, "upgrade": { "cost": [11000000, 15000000, 18000000], "time": [1209600, 1382400, 1555200], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4] }, { "id": 58, "name": "Ice Golem", "housingSpace": 15, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 11, "cost": 4000000, "time": 777600, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 8 }, "upgrade": { "cost": [80000, 120000, 160000, 200000, 320000], "time": [432000, 691200, 907200, 1209600, 1468800], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 5, 6] }, { "id": 59, "name": "Electro Dragon", "housingSpace": 30, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 11, "cost": 4000000, "time": 518400, "resource": "Elixir", "building": "Barracks", "buildingLevel": 13 }, "upgrade": { "cost": [9000000, 11000000, 16000000, 19000000], "time": [864000, 1209600, 1382400, 1555200], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5] }, { "id": 61, "name": "Skeleton Barrel", "housingSpace": 5, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 4, "cost": 80000, "time": 28800, "resource": "Elixir", "building": "Barracks", "buildingLevel": 6 }, "upgrade": { "cost": [150000, 450000, 1350000, 2500000, 6000000, 9500000, 12000000, 12000000], "time": [43200, 129600, 172800, 302400, 561600, 993600, 1209600, 1209600], "resource": "Elixir" }, "levels": [0, 0, 0, 2, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9] }, { "id": 62, "name": "Stone Slammer", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "siege", "unlock": { "hall": 12, "cost": 10500000, "time": 864000, "resource": "Elixir", "building": "Workshop", "buildingLevel": 3 }, "upgrade": { "cost": [6000000, 8000000, 14000000], "time": [691200, 864000, 1382400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4] }, { "id": 65, "name": "Dragon Rider", "housingSpace": 25, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 13, "cost": 6000000, "time": 950400, "resource": "Elixir", "building": "Barracks", "buildingLevel": 15 }, "upgrade": { "cost": [16000000, 17500000], "time": [1296000, 1468800], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3] }, { "id": 67, "name": "El Primo", "housingSpace": 10, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 5, "cost": 240000, "time": 43200, "resource": "Elixir", "building": "Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [120000], "time": [734400], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, { "id": 70, "name": "Hog Glider", "housingSpace": 5, "village": "builderBase", "category": "troop", "subCategory": "troop", "unlock": { "hall": 9, "cost": 2000000, "time": 129600, "resource": "Builder Elixir", "building": "Builder Barracks", "buildingLevel": 11 }, "upgrade": { "cost": [1600000, 1700000, 1800000, 1900000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000], "time": [86400, 86400, 172800, 172800, 259200, 259200, 345600, 345600, 345600, 345600, 345600, 345600, 345600, 345600, 345600, 432000, 432000], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 18] }, { "id": 72, "name": "Party Wizard", "housingSpace": 4, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 5, "cost": 240000, "time": 43200, "resource": "Elixir", "building": "Barracks", "buildingLevel": 7 }, "upgrade": { "cost": [null], "time": [0], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10] }, { "id": 75, "name": "Siege Barracks", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "siege", "unlock": { "hall": 13, "cost": 14500000, "time": 1209600, "resource": "Elixir", "building": "Workshop", "buildingLevel": 4 }, "upgrade": { "cost": [8000000, 11000000, 14000000], "time": [864000, 1209600, 1382400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4] }, { "id": 82, "name": "Headhunter", "housingSpace": 6, "village": "home", "category": "troop", "subCategory": "troop", "unlock": { "hall": 12, "cost": 7500000, "time": 1123200, "resource": "Elixir", "building": "Dark Barracks", "buildingLevel": 9 }, "upgrade": { "cost": [180000, 240000], "time": [1209600, 1382400], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3] }, { "id": 87, "name": "Log Launcher", "housingSpace": 1, "village": "home", "category": "troop", "subCategory": "siege", "unlock": { "hall": 13, "cost": 16000000, "time": 1382400, "resource": "Elixir", "building": "Workshop", "buildingLevel": 5 }, "upgrade": { "cost": [8000000, 11000000, 14000000], "time": [864000, 1209600, 1382400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4] }, { "id": 0, "name": "Lightning Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 5, "cost": 200000, "time": 28800, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 1 }, "upgrade": { "cost": [85000, 225000, 450000, 900000, 2000000, 4000000, 8000000, 10000000], "time": [43200, 86400, 129600, 259200, 432000, 691200, 907200, 1123200], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 4, 4, 4, 5, 6, 7, 8, 9, 9, 9] }, { "id": 1, "name": "Healing Spell", "housingSpace": 2, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 6, "cost": 400000, "time": 86400, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 2 }, "upgrade": { "cost": [75000, 300000, 600000, 1200000, 2500000, 4500000, 14000000], "time": [21600, 64800, 129600, 259200, 432000, 777600, 1382400], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 7, 7, 8, 8] }, { "id": 2, "name": "Rage Spell", "housingSpace": 2, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 7, "cost": 800000, "time": 172800, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 3 }, "upgrade": { "cost": [450000, 900000, 1800000, 3000000, 11000000], "time": [64800, 129600, 259200, 432000, 993600], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 4, 5, 5, 5, 5, 6, 6, 6] }, { "id": 3, "name": "Jump Spell", "housingSpace": 2, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 9, "cost": 1200000, "time": 302400, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 4 }, "upgrade": { "cost": [3000000, 6000000, 13000000], "time": [345600, 604800, 1296000], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4] }, { "id": 5, "name": "Freeze Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 9, "cost": 1200000, "time": 302400, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 4 }, "upgrade": { "cost": [1500000, 2500000, 4200000, 6000000, 8500000, 11000000], "time": [172800, 345600, 518400, 648000, 777600, 993600], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, 7, 7, 7] }, { "id": 4, "name": "Santa's Surprise", "housingSpace": 2, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 5, "cost": 200000, "time": 28800, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 1 }, "upgrade": { "cost": [null], "time": [null], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, { "id": 9, "name": "Poison Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 8, "cost": 250000, "time": 21600, "resource": "Elixir", "building": "Dark Spell Factory", "buildingLevel": 1 }, "upgrade": { "cost": [20000, 40000, 75000, 150000, 200000, 260000, 300000], "time": [86400, 172800, 345600, 777600, 950400, 1339200, 1512000], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8] }, { "id": 10, "name": "Earthquake Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 8, "cost": 500000, "time": 64800, "resource": "Elixir", "building": "Dark Spell Factory", "buildingLevel": 2 }, "upgrade": { "cost": [20000, 40000, 75000, 120000], "time": [172800, 345600, 648000, 950400], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 5, 5, 5] }, { "id": 11, "name": "Haste Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 9, "cost": 1000000, "time": 172800, "resource": "Elixir", "building": "Dark Spell Factory", "buildingLevel": 3 }, "upgrade": { "cost": [30000, 50000, 80000, 120000], "time": [216000, 432000, 691200, 950400], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 5, 5, 5] }, { "id": 16, "name": "Clone Spell", "housingSpace": 3, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 10, "cost": 2400000, "time": 432000, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 5 }, "upgrade": { "cost": [3000000, 4500000, 7000000, 9000000, 14000000, 16500000], "time": [259200, 388800, 561600, 993600, 1296000, 1425600], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 5, 6, 7] }, { "id": 17, "name": "Skeleton Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 9, "cost": 2000000, "time": 345600, "resource": "Elixir", "building": "Dark Spell Factory", "buildingLevel": 4 }, "upgrade": { "cost": [25000, 40000, 70000, 125000, 150000, 250000], "time": [216000, 345600, 561600, 734400, 907200, 1296000], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 6, 7, 7] }, { "id": 22, "name": "Birthday Boom", "housingSpace": 2, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 5, "cost": 200000, "time": 28800, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 1 }, "upgrade": { "cost": [null], "time": [null], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, { "id": 28, "name": "Bat Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 10, "cost": 3000000, "time": 518400, "resource": "Elixir", "building": "Dark Spell Factory", "buildingLevel": 5 }, "upgrade": { "cost": [30000, 60000, 120000, 160000], "time": [259200, 475200, 648000, 777600], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 5, 5] }, { "id": 35, "name": "Invisibility Spell", "housingSpace": 1, "village": "home", "category": "spell", "subCategory": "spell", "unlock": { "hall": 11, "cost": 4800000, "time": 604800, "resource": "Elixir", "building": "Spell Factory", "buildingLevel": 6 }, "upgrade": { "cost": [9000000, 12000000, 15000000], "time": [777600, 993600, 1339200], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 4] }, { "id": 0, "name": "Barbarian King", "housingSpace": 25, "village": "home", "category": "hero", "subCategory": "hero", "unlock": { "hall": 7, "cost": 5000, "time": 0, "resource": "Dark Elixir", "building": "Barbarian King", "buildingLevel": 1 }, "upgrade": { "cost": [6000, 7000, 8000, 10000, 11000, 12000, 13000, 14000, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 29000, 31000, 33000, 35000, 37000, 39000, 41000, 43000, 45000, 48000, 51000, 54000, 57000, 60000, 63000, 66000, 69000, 72000, 75000, 80000, 85000, 90000, 95000, 100000, 105000, 110000, 120000, 130000, 140000, 150000, 160000, 170000, 180000, 190000, 200000, 203000, 206000, 209000, 212000, 215000, 218000, 221000, 224000, 227000, 230000, 233000, 236000, 239000, 240000, 250000, 260000, 270000, 280000, 290000, 292000, 294000, 296000, 298000, 300000, 305000, 310000, 315000, 320000, 325000], "time": [14400, 21600, 28800, 36000, 43200, 50400, 57600, 64800, 72000, 79200, 86400, 115200, 144000, 172800, 172800, 172800, 172800, 172800, 259200, 259200, 259200, 259200, 259200, 302400, 302400, 302400, 302400, 302400, 345600, 345600, 345600, 345600, 345600, 432000, 432000, 432000, 432000, 432000, 518400, 518400, 518400, 518400, 518400, 561600, 561600, 561600, 561600, 561600, 561600, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 648000, 648000, 648000, 648000, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 5, 10, 30, 40, 50, 65, 75, 80] }, { "id": 1, "name": "Archer Queen", "housingSpace": 25, "village": "home", "category": "hero", "subCategory": "hero", "unlock": { "hall": 9, "cost": 10000, "time": 0, "resource": "Dark Elixir", "building": "Archer Queen", "buildingLevel": 1 }, "upgrade": { "cost": [11000, 12000, 13000, 15000, 16000, 17000, 18000, 19000, 20000, 22000, 24000, 26000, 28000, 30000, 32000, 34000, 36000, 38000, 40000, 42000, 44000, 46000, 48000, 50000, 53000, 56000, 59000, 62000, 65000, 68000, 71000, 74000, 77000, 80000, 85000, 90000, 95000, 100000, 105000, 115000, 120000, 125000, 135000, 145000, 155000, 165000, 175000, 185000, 195000, 200000, 204000, 208000, 212000, 216000, 220000, 224000, 228000, 232000, 236000, 240000, 240000, 240000, 240000, 240000, 250000, 260000, 270000, 280000, 290000, 292000, 294000, 296000, 298000, 300000, 306000, 312000, 318000, 324000, 330000], "time": [14400, 21600, 28800, 36000, 43200, 50400, 57600, 64800, 72000, 79200, 86400, 115200, 144000, 172800, 172800, 172800, 172800, 172800, 259200, 259200, 259200, 259200, 259200, 302400, 302400, 302400, 302400, 302400, 345600, 345600, 345600, 345600, 345600, 432000, 432000, 432000, 432000, 432000, 518400, 518400, 518400, 518400, 518400, 561600, 561600, 561600, 561600, 561600, 561600, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 648000, 648000, 648000, 648000, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 30, 40, 50, 65, 75, 80] }, { "id": 2, "name": "Grand Warden", "housingSpace": 25, "village": "home", "category": "hero", "subCategory": "hero", "unlock": { "hall": 11, "cost": 2000000, "time": 0, "resource": "Elixir", "building": "Grand Warden", "buildingLevel": 1 }, "upgrade": { "cost": [2250000, 2500000, 2750000, 3000000, 3300000, 3750000, 4500000, 5250000, 6000000, 7000000, 7500000, 8000000, 8400000, 8800000, 9100000, 9400000, 9600000, 9800000, 10000000, 10000000, 10200000, 10400000, 10600000, 10800000, 11000000, 11200000, 11400000, 11600000, 11800000, 12000000, 12000000, 12000000, 12000000, 12000000, 12000000, 12000000, 12000000, 12000000, 12000000, 12000000, 12500000, 13000000, 13500000, 14000000, 14500000, 15000000, 15500000, 16000000, 16500000, 17000000, 17500000, 18000000, 18500000, 19000000], "time": [14400, 28800, 43200, 86400, 129600, 172800, 259200, 345600, 388800, 432000, 475200, 518400, 561600, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 604800, 648000, 648000, 648000, 648000, 648000, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 40, 50, 55] }, { "id": 3, "name": "Battle Machine", "housingSpace": 25, "village": "builderBase", "category": "hero", "subCategory": "hero", "unlock": { "hall": 5, "cost": 900000, "time": 43200, "resource": "Builder Elixir", "building": "Battle Machine", "buildingLevel": 1 }, "upgrade": { "cost": [1000000, 1100000, 1200000, 1300000, 1500000, 1600000, 1700000, 1800000, 1900000, 2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3700000, 3800000, 3900000, 4000000, 4000000], "time": [43200, 43200, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 172800, 172800, 172800, 172800, 172800, 259200, 259200, 259200, 259200, 259200, 259200, 259200, 259200, 259200, 259200, 345600, 345600, 345600, 345600, 345600, 345600], "resource": "Builder Elixir" }, "levels": [0, 0, 0, 0, 5, 10, 20, 25, 30] }, { "id": 4, "name": "Royal Champion", "housingSpace": 25, "village": "home", "category": "hero", "subCategory": "hero", "unlock": { "hall": 13, "cost": 120000, "time": 0, "resource": "Dark Elixir", "building": "Royal Champion", "buildingLevel": 1 }, "upgrade": { "cost": [130000, 140000, 150000, 160000, 170000, 180000, 190000, 200000, 210000, 220000, 230000, 235000, 240000, 245000, 250000, 255000, 260000, 265000, 270000, 275000, 280000, 285000, 290000, 295000, 300000, 305000, 310000, 315000, 320000], "time": [86400, 129600, 172800, 216000, 259200, 302400, 345600, 388800, 432000, 475200, 518400, 561600, 604800, 604800, 648000, 648000, 648000, 648000, 648000, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 30] }, { "id": 0, "name": "L.A.S.S.I", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "pet", "unlock": { "hall": 14, "cost": 15000000, "time": 1123200, "resource": "Elixir", "building": "Pet House", "buildingLevel": 1 }, "upgrade": { "cost": [115000, 130000, 145000, 160000, 175000, 190000, 205000, 220000, 235000], "time": [259200, 345600, 432000, 475200, 518400, 561600, 604800, 648000, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10] }, { "id": 1, "name": "Mighty Yak", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "pet", "unlock": { "hall": 14, "cost": 18500000, "time": 1468800, "resource": "Elixir", "building": "Pet House", "buildingLevel": 3 }, "upgrade": { "cost": [165000, 185000, 205000, 225000, 245000, 255000, 265000, 275000, 285000], "time": [259200, 345600, 432000, 475200, 518400, 561600, 604800, 648000, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10] }, { "id": 2, "name": "Electro Owl", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "pet", "unlock": { "hall": 14, "cost": 17500000, "time": 1296000, "resource": "Elixir", "building": "Pet House", "buildingLevel": 2 }, "upgrade": { "cost": [135000, 150000, 165000, 180000, 195000, 210000, 225000, 240000, 255000], "time": [259200, 345600, 432000, 475200, 518400, 561600, 604800, 648000, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10] }, { "id": 3, "name": "Unicorn", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "pet", "unlock": { "hall": 14, "cost": 19500000, "time": 1641600, "resource": "Elixir", "building": "Pet House", "buildingLevel": 4 }, "upgrade": { "cost": [210000, 220000, 230000, 240000, 250000, 260000, 270000, 280000, 290000], "time": [259200, 345600, 432000, 475200, 518400, 561600, 604800, 648000, 691200], "resource": "Dark Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10] }, { "id": 4, "name": "", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "pet", "unlock": { "hall": 14, "cost": 15000000, "time": 1123200, "resource": "Elixir", "building": "Pet House", "buildingLevel": 1 }, "upgrade": { "cost": [4000000], "time": [432000], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] }, { "id": 4, "name": "", "housingSpace": 20, "village": "home", "category": "troop", "subCategory": "pet", "unlock": { "hall": 14, "cost": 15000000, "time": 1123200, "resource": "Elixir", "building": "Pet House", "buildingLevel": 1 }, "upgrade": { "cost": [750000], "time": [172800], "resource": "Elixir" }, "levels": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] }], "RAW_SUPER_UNITS": [{ "name": "Super Barbarian", "id": 26, "original": "Barbarian", "minOriginalLevel": 8, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 5 }, { "name": "Sneaky Goblin", "id": 55, "original": "Goblin", "minOriginalLevel": 7, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 3 }, { "name": "Super Giant", "id": 29, "original": "Giant", "minOriginalLevel": 9, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 10 }, { "name": "Super Wall Breaker", "id": 28, "original": "Wall Breaker", "minOriginalLevel": 7, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 8 }, { "name": "Super Archer", "id": 27, "original": "Archer", "minOriginalLevel": 8, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 12 }, { "name": "Super Witch", "id": 66, "original": "Witch", "minOriginalLevel": 5, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 40 }, { "name": "Inferno Dragon", "id": 63, "original": "Baby Dragon", "minOriginalLevel": 6, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 15 }, { "name": "Super Valkyrie", "id": 64, "original": "Valkyrie", "minOriginalLevel": 7, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 20 }, { "name": "Super Minion", "id": 84, "original": "Minion", "minOriginalLevel": 8, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 12 }, { "name": "Super Wizard", "id": 83, "original": "Wizard", "minOriginalLevel": 9, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 10 }, { "name": "Ice Hound", "id": 76, "original": "Lava Hound", "minOriginalLevel": 5, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 40 }, { "name": "Rocket Balloon", "id": 57, "original": "Balloon", "minOriginalLevel": 8, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 8 }, { "name": "Super Bowler", "id": 80, "original": "Bowler", "minOriginalLevel": 4, "village": "home", "duration": 259200, "cooldown": 259200, "resource": "Dark Elixir", "resourceCost": 25000, "housingSpace": 30 }] }
|
package/package.json
CHANGED