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 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
- - Override Request Options ([#36](https://github.com/clashperk/clashofclans.js/issues/36)) ([42d7fdd](https://github.com/clashperk/clashofclans.js/commit/42d7fdd36262cc46f23b731f8cffb9daea19d3b0))
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: 3000,
44
- throttler: new BatchThrottler(30)
44
+ restRequestTimeout: 5000,
45
+ throttler: new BatchThrottler(20)
45
46
  });
46
47
 
47
48
  client.events.addClans(['#8QU8J9LP', '#8P2QG08P']);
@@ -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 information about CWL round by WarTag. */
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[]>;
@@ -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 information about CWL round by WarTag. */
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.postPlayerToken(playerTag, token, options);
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 = this._maintenanceStartTime.getTime() - Date.now();
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, state) => {
233
- const key = `${tag}:${state}`;
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 (state === 1 && cached.warTag !== war.warTag) {
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) {
@@ -1,6 +1,4 @@
1
- /**
2
- * Represents an HTTP Error.
3
- */
1
+ /** Represents an HTTP Error. */
4
2
  export declare class HTTPError extends Error {
5
3
  /** The message of this error. */
6
4
  message: string;
@@ -19,9 +19,7 @@ const reasons = {
19
19
  404: 'notFound',
20
20
  504: 'requestAborted'
21
21
  };
22
- /**
23
- * Represents an HTTP Error.
24
- */
22
+ /** Represents an HTTP Error. */
25
23
  class HTTPError extends Error {
26
24
  constructor(error, status, path, maxAge, method) {
27
25
  super();
@@ -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
- postPlayerToken(playerTag: string, token: string, options?: OverrideOptions): Promise<{
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;
@@ -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
- postPlayerToken(playerTag, token, options) {
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
- return this.exec(path, options, ++retries);
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 expiredKeys = keys.filter((key) => key.name === this.keyName && !key.cidrRanges.includes(ip));
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;
@@ -29,7 +29,3 @@ export declare class BatchThrottler {
29
29
  wait(): Promise<void>;
30
30
  throttle(): Promise<void>;
31
31
  }
32
- export interface DeferredPromise {
33
- resolve(): void;
34
- promise: Promise<void>;
35
- }
@@ -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
  }
@@ -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 # (1-7) of the round for the specified warTag. */
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 # (1-7) of the round for the specified warTag. */
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
  }
@@ -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. */
@@ -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((data) => new Unit_1.Troop(data));
40
- this.spells = data.spells.map((data) => new Unit_1.Spell(data));
41
- this.heroes = data.heroes.map((data) => new Unit_1.Hero(data));
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;
@@ -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
- constructor(data: APIPlayerItem);
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
- superTroopIsActive: boolean;
26
- constructor(data: APIPlayerItem);
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
  }
@@ -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
- constructor(data) {
8
- this.name = data.name;
9
- this.level = data.level;
10
- this.maxLevel = data.maxLevel;
11
- this.village = data.village;
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.superTroopIsActive = data.superTroopIsActive ?? false;
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.superTroopIsActive || (this.isHomeBase && Constants_1.SUPER_TROOPS.includes(this.name));
79
+ return this.isActive || (this.isHomeBase && Constants_1.SUPER_TROOPS.includes(this.name));
40
80
  }
41
81
  }
42
82
  exports.Troop = Troop;
@@ -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: APIRole;
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: APIWarState;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clashofclans.js",
3
- "version": "2.0.0-dev.75d755c",
3
+ "version": "2.0.0-dev.7768cb1",
4
4
  "description": "JavaScript library for interacting with the Clash of Clans API",
5
5
  "author": "SUVAJIT <suvajit.me@gmail.com>",
6
6
  "license": "MIT",