From 8bf31f5f3d07ec3c913a4ebec9068825f5a78664 Mon Sep 17 00:00:00 2001 From: Grover-c13 Date: Tue, 26 Jul 2016 22:47:08 +0800 Subject: [PATCH] Development (#248) * Refresh the OAuth token when it expires * Fix my siliness and provide API consumers a way to provide their refresh token when using static auth * add query from hatched eggs + rewrite stuff around EggPokemon * fix the explaination for eclipse user * Level enum public for custom loggers * Publish sources jar Fixes #128 * add license to GoogleLoginSecrets * Use a reset instead of using another instance * Fix the checkstyle config to not break other modules * find Pokemon by ID update inventory after hatching eggs add missing license * Meta info on pokemon * add method the incubator * fix typo * Add a callback for when the Initial oAuth completes so that the app can automate the flow * Power up pokemon API * Add info about native google sign in * REAME.md: fix Usefull->Useful typo * README.md: fix PtcLogin classname type * fix force updating inventories * Fix incorrect static statements on point * Added iv calculator (#207) * Added iv calculator * checkstyleMain fix * Fix @returns in doc of getIVRatio() * take care that the candies actually are in the map * forgot that cancerous check style * tweak checkstyle config to be friendly (#226) * Add cause to LoginFailedExceptions. (#220) Signed-off-by: Niklas Walter * Remove printStackTrace from updateProfile (#221) updateProfile, in case of failure, would dump stacktraces to the console and then crash in the next line with a NullPointerException * Added request to add modifiers to forts, for example a lure-module on a pokestop (#217) * implemented request to add fort modifier * added @throws to javadoc for addModifier in Pokestop.java * Added SetFavoritePokemon method (#222) * add lombok to more objects (#212) * add lombok to more objects * add lombok to GoogleAuthJson * add lombok to Team * getItemsCount function (#224) * get total space used by items * get total space used by items * add javadoc * Rewrote and Refactored login logic. Now the credential providers transparently handle providing credentials and refreshing tokens. * Update the protobuf dependency (#235) Includes fix for hatched eggs IndexOutOfBoundsException * WIP: Gym/Battle (#203) * Add info about native google sign in * fix force updating inventories * REAME.md: fix Usefull->Useful typo * README.md: fix PtcLogin classname type * Start Gym + Battle API * Battle API - Example included, utility functions to get state of battle. Can only spam attack right now. * Deprecate pokemon.getFavorite, rename to pokemon.isFavorite (#230) * deprecate getFavorite, rename to isFavorite * Adhere to checkstyle * Use gradle-wrapper instead (#200) * Use gradle-wrapper instead * Changed second gradle usage to use gradlew aswell * Fix typos (#218) * Fix UTF-8 encoding * Fix typo recieved -> received * fix example * Consistently use RemoteServerException for network/server errors (#243) * Redone meta pm, lots of info available, several enums for pokemon (some may be duplicates of proto enums), fix catchable pokemon (#246) * fix #237 + #227 (#240) * Update protobufs to latest version --- .github/CONTRIBUTING.md | 4 +- .github/ISSUE_TEMPLATE.md | 4 +- README.md | 25 +- build.gradle | 14 +- config/checkstyle.xml | 23 +- gradle/wrapper/gradle-wrapper.properties | 4 +- .../java/com/pokegoapi/api/PokemonGo.java | 30 +- .../java/com/pokegoapi/api/gym/Battle.java | 257 + src/main/java/com/pokegoapi/api/gym/Gym.java | 168 + .../com/pokegoapi/api/inventory/CandyJar.java | 10 +- .../pokegoapi/api/inventory/EggIncubator.java | 55 +- .../com/pokegoapi/api/inventory/Hatchery.java | 50 +- .../pokegoapi/api/inventory/Inventories.java | 10 +- .../com/pokegoapi/api/inventory/Item.java | 12 +- .../com/pokegoapi/api/inventory/ItemBag.java | 17 + .../com/pokegoapi/api/inventory/PokeBank.java | 24 +- .../com/pokegoapi/api/inventory/Pokedex.java | 13 +- src/main/java/com/pokegoapi/api/map/Map.java | 22 +- .../java/com/pokegoapi/api/map/Point.java | 4 +- .../com/pokegoapi/api/map/fort/Pokestop.java | 28 + .../api/map/pokemon/CatchablePokemon.java | 24 +- .../pokegoapi/api/player/PlayerProfile.java | 6 +- .../java/com/pokegoapi/api/player/Team.java | 7 +- .../com/pokegoapi/api/pokemon/EggPokemon.java | 67 +- .../com/pokegoapi/api/pokemon/HatchedEgg.java | 29 + .../pokegoapi/api/pokemon/MovementType.java | 11 + .../com/pokegoapi/api/pokemon/Pokemon.java | 120 +- .../pokegoapi/api/pokemon/PokemonClass.java | 13 + .../api/pokemon/PokemonFamilyMap.java | 284 - .../pokegoapi/api/pokemon/PokemonMeta.java | 123 + .../api/pokemon/PokemonMetaRegistry.java | 5576 +++++++++++++++++ .../pokegoapi/api/pokemon/PokemonType.java | 18 + .../{Login.java => CredentialProvider.java} | 13 +- .../com/pokegoapi/auth/GoogleAuthJson.java | 53 +- .../pokegoapi/auth/GoogleAuthTokenJson.java | 63 +- .../auth/GoogleCredentialProvider.java | 277 + .../java/com/pokegoapi/auth/GoogleLogin.java | 138 - .../java/com/pokegoapi/auth/PtcAuthJson.java | 23 +- .../pokegoapi/auth/PtcCredentialProvider.java | 257 + .../java/com/pokegoapi/auth/PtcError.java | 13 +- .../java/com/pokegoapi/auth/PtcLogin.java | 201 - .../examples/CatchPokemonAtAreaExample.java | 15 +- .../pokegoapi/examples/FightGymExample.java | 103 + .../examples/TransferOnePidgeyExample.java | 14 +- .../exceptions/LoginFailedException.java | 4 + .../exceptions/RemoteServerException.java | 4 + .../com/pokegoapi/main/RequestHandler.java | 25 +- src/main/java/com/pokegoapi/util/Log.java | 2 +- src/resources/protobuf | 2 +- 49 files changed, 7387 insertions(+), 872 deletions(-) create mode 100644 src/main/java/com/pokegoapi/api/gym/Battle.java create mode 100644 src/main/java/com/pokegoapi/api/gym/Gym.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/HatchedEgg.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/MovementType.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonClass.java delete mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonFamilyMap.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java create mode 100644 src/main/java/com/pokegoapi/api/pokemon/PokemonType.java rename src/main/java/com/pokegoapi/auth/{Login.java => CredentialProvider.java} (69%) create mode 100644 src/main/java/com/pokegoapi/auth/GoogleCredentialProvider.java delete mode 100644 src/main/java/com/pokegoapi/auth/GoogleLogin.java create mode 100644 src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java delete mode 100644 src/main/java/com/pokegoapi/auth/PtcLogin.java create mode 100644 src/main/java/com/pokegoapi/examples/FightGymExample.java diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 33fc433c..52f10014 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -11,8 +11,8 @@ You may open an issue also to request new features. Make sure you describe what If you consider submitting a pull request, please note the following: 1. All pull requests **must** be submitted to the `Development` branch. The `master` branch is exclusively mutable by release. PRs against `master` will not be merged. -2. Pleae make sure you follow the projects code style. To make sure you did, you can use `./gradlew checkstyleMain`. +2. Please make sure you follow the projects code style. To make sure you did, you can use `./gradlew checkstyleMain`. 3. The project is licensed under [GNU GPLv3](../LICENSE.txt) thus all code you submit will be subject to this license. ## Contact -If you have any questions regarding the library you can ask those on the `#javaapi` channel on the [Pokemon GO Reverse Engineering Slack](https://pkre.slack.com/). You can [get your invite here](https://shielded-earth-81203.herokuapp.com/). \ No newline at end of file +If you have any questions regarding the library you can ask those on the `#javaapi` channel on the [Pokemon GO Reverse Engineering Slack](https://pkre.slack.com/). You can [get your invite here](https://shielded-earth-81203.herokuapp.com/). diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 2496eccf..90bbf771 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ **Description:** -[Short description of the issue observed. If this ia feature request you can modify the template as required.] +[Short description of the issue observed. If this is a feature request you can modify the template as required.] **Steps to reproduce:** @@ -16,4 +16,4 @@ [Please use pastebin if it's too long] **Version:** -[The version of the lib you used] \ No newline at end of file +[The version of the lib you used] diff --git a/README.md b/README.md index 8d9672d2..c359c85d 100644 --- a/README.md +++ b/README.md @@ -27,24 +27,29 @@ ___ # Build - Clone the repo and cd into the folder - `` git submodule update --init `` - - verify that you have gradle in your path - - `` gradle build bundle `` + - compile and package + - `` ./gradlew build bundle `` - you should have the api bundled in ``build/libs/PokeGOAPI-Java_bundle-0.0.1-SNAPSHOT.jar`` - PS : To eclipse user, you may build one time and add the generated java class for proto into eclipse path : Right click on the project > Build path > New Source Folder > Type 'build/generated/source/proto/main/java' > Finish + PS : To Eclipse user, you must build once : `` ./gradlew build `` and add the generated java class for proto into eclipse source path : Right click on the project > Build path > Configure Build Path > Source > Add Folder > Select `build/generated/source/proto/main/java` > Finish # Usage Include the API as jar from your own build, or use Maven/Gradle/SBT/Leiningen: https://jitpack.io/#Grover-c13/PokeGOAPI-Java/master-SNAPSHOT Mostly everything is accessed through the PokemonGo class in the API package. -The constructor of PokemonGo class requires a AuthInfo object which can be obtained from GoogleLogin().login or PTCLogin().login, and a OkHttpClient object. +The constructor of PokemonGo class requires a AuthInfo object which can be obtained from GoogleLogin().login or PtcLogin().login, and a OkHttpClient object. EG: ```java OkHttpClient httpClient = new OkHttpClient(); -AuthInfo auth = new GoogleLogin(httpClient).login("token"); -PokemonGo go = new PokemonGo(auth,httpClient); +//Use Google +//First Ever Login. Persist info when you recieve callback +PokemonGo go = new PokemonGo(new GoogleCredentialProvider(httpClient,listner),httpClient); +//Subsequently +PokemonGo go = new PokemonGo(new GoogleCredentialProvider(httpClient,refreshToken),httpClient); +//Or use PTC +PokemonGo go = new PokemonGo(new PtcCredentialProvider(httpClient,username,password),httpClient); Log.v(go.getPlayerProfile()); ``` ##Android Dev FAQ @@ -57,13 +62,17 @@ You're running the sample code on the UI thread. Strict mode policy will throw a This library is meant to be a Java implementation of the API. Google Volley is specific to Android and should not be introduced in this library. However, if you still want to refactor it, you should create it as a separate project. + - How can I use Android's native Google sign in with this library? + +You can't. The Google Identity Platform uses the SHA1 fingerprint and package name to authenticate the caller of all sign in requests. This means that Niantic would need to add your app's SHA1 fingerprint and package name to their Google API Console. If you ever requested a Google Maps API key, you went through the same process. An alternative would be using a WebView to access the web based OAuth flow. This will work with the client ID and secret provided by this library. + ## Contributing - Fork it! - Create your feature branch: `git checkout -b my-new-feature` - - Commit your changes: `git commit -am 'Usefull information about your new features'` + - Commit your changes: `git commit -am 'Useful information about your new features'` - Push to the branch: `git push origin my-new-feature` - - Submit a pull request :D + - Submit a pull request on the `Development` branch :D ## Contributors - Grover-c13 diff --git a/build.gradle b/build.gradle index 4306a6c5..9bdb1f71 100644 --- a/build.gradle +++ b/build.gradle @@ -62,11 +62,12 @@ protobuf { } } -def checkstyleOutputDir = "${project.rootDir}/build/reports/checkstyle/" +def checkstyleOutputDir = "${project.projectDir}/build/reports/checkstyle/" checkstyle { toolVersion = '7.0' - configFile = file("${project.rootDir}/config/checkstyle.xml") + configFile = file("${project.projectDir}/config/checkstyle.xml") + configProperties = [ "suppressionFile" : file("${project.projectDir}/config/suppressions.xml")] reportsDir = file(checkstyleOutputDir) ignoreFailures = false @@ -107,3 +108,12 @@ idea { sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java"); } } + +task sourcesJar(type: Jar) { + from sourceSets.main.java.srcDirs + classifier = 'sources' +} + +artifacts { + archives sourcesJar +} diff --git a/config/checkstyle.xml b/config/checkstyle.xml index 3568be96..7c2d8b1b 100644 --- a/config/checkstyle.xml +++ b/config/checkstyle.xml @@ -16,7 +16,7 @@ - + @@ -57,7 +57,6 @@ - @@ -67,10 +66,10 @@ - - + + - + - - - - - - - - - @@ -174,9 +164,6 @@ - - - @@ -204,4 +191,4 @@ - \ No newline at end of file + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8d543ffa..8e6fe481 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Jul 17 19:51:46 PDT 2016 +#Sat Jul 23 04:51:41 PDT 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip diff --git a/src/main/java/com/pokegoapi/api/PokemonGo.java b/src/main/java/com/pokegoapi/api/PokemonGo.java index 4ef858e7..a1c3171f 100644 --- a/src/main/java/com/pokegoapi/api/PokemonGo.java +++ b/src/main/java/com/pokegoapi/api/PokemonGo.java @@ -19,6 +19,7 @@ import com.pokegoapi.api.inventory.Inventories; import com.pokegoapi.api.map.Map; import com.pokegoapi.api.player.PlayerProfile; +import com.pokegoapi.auth.CredentialProvider; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.RequestHandler; @@ -49,20 +50,28 @@ public class PokemonGo { @Setter private double altitude; + private CredentialProvider credentialProvider; + + private RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo authInfo; /** * Instantiates a new Pokemon go. * - * @param auth the auth * @param client the client */ - public PokemonGo(RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth, OkHttpClient client) + public PokemonGo(CredentialProvider credentialProvider, OkHttpClient client) throws LoginFailedException, RemoteServerException { + + if (credentialProvider == null) { + throw new LoginFailedException("Credential Provider is null"); + } else { + this.credentialProvider = credentialProvider; + } + playerProfile = null; // send profile request to get the ball rolling - requestHandler = new RequestHandler(this, auth, client); - + requestHandler = new RequestHandler(this, client); playerProfile = new PlayerProfile(this); inventories = new Inventories(this); @@ -70,10 +79,21 @@ public PokemonGo(RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth, OkHttp inventories.updateInventories(); // should have proper end point now. - map = new Map(this); } + /** + * Fetches valid AuthInfo + * + * @return AuthInfo object + * @throws LoginFailedException when login fails + */ + public RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo getAuthInfo() + throws LoginFailedException, RemoteServerException { + return credentialProvider.getAuthInfo(); + } + + /** * Gets player profile. * diff --git a/src/main/java/com/pokegoapi/api/gym/Battle.java b/src/main/java/com/pokegoapi/api/gym/Battle.java new file mode 100644 index 00000000..18b1a200 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/gym/Battle.java @@ -0,0 +1,257 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.gym; + +import POGOProtos.Data.Battle.BattleActionOuterClass.BattleAction; +import POGOProtos.Data.Battle.BattleActionTypeOuterClass; +import POGOProtos.Data.Battle.BattlePokemonInfoOuterClass.BattlePokemonInfo; +import POGOProtos.Data.Battle.BattleStateOuterClass; +import POGOProtos.Data.Battle.BattleStateOuterClass.BattleState; +import POGOProtos.Data.PokemonDataOuterClass; +import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass.AttackGymMessage; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage.Builder; +import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; +import POGOProtos.Networking.Responses.AttackGymResponseOuterClass; +import POGOProtos.Networking.Responses.AttackGymResponseOuterClass.AttackGymResponse; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result; +import com.google.protobuf.InvalidProtocolBufferException; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class Battle { + private Gym gym; + private Pokemon[] team; + private List bteam; + private StartGymBattleResponse battleResponse; + private PokemonGo api; + private List gymIndex; + @Getter + private boolean concluded; + @Getter + private BattleState outcome; + + /** + * New battle to track the state of a battle. + * + */ + public Battle(PokemonGo api, Pokemon[] team, Gym gym) { + this.team = team; + this.gym = gym; + this.api = api; + + this.bteam = new ArrayList(); + this.gymIndex = new ArrayList<>(); + + for (int i = 0; i < team.length; i++) { + bteam.add(this.createBattlePokemon(team[i])); + } + } + + /** + * Start a battle. + * + * @return Result of the attempt to start + */ + public Result start() throws LoginFailedException, RemoteServerException { + + Builder builder = StartGymBattleMessageOuterClass.StartGymBattleMessage.newBuilder(); + + for (int i = 0; i < team.length; i++) { + builder.addAttackingPokemonIds(team[i].getId()); + } + + + List defenders = gym.getDefendingPokemon(); + builder.setGymId(gym.getId()); + builder.setPlayerLongitude(api.getLongitude()); + builder.setPlayerLatitude(api.getLatitude()); + builder.setDefendingPokemonId(defenders.get(0).getId()); // may need to be sorted + + ServerRequest serverRequest = new ServerRequest(RequestType.START_GYM_BATTLE, builder.build()); + api.getRequestHandler().sendServerRequests(serverRequest); + + + try { + battleResponse = StartGymBattleResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + + // need to send blank action + this.sendBlankAction(); + + + for (BattleAction action : battleResponse.getBattleLog().getBattleActionsList()) { + gymIndex.add(action.getTargetIndex()); + } + + return battleResponse.getResult(); + } + + + + + /** + * Attack a gym. + * + * @param times the amount of times to attack + * @return Battle + */ + public AttackGymResponse attack(int times) throws LoginFailedException, RemoteServerException { + + ArrayList actions = new ArrayList(); + + for (int i = 0; i < times; i++) { + BattleAction action = BattleAction + .newBuilder() + .setType(BattleActionTypeOuterClass.BattleActionType.ACTION_ATTACK) + .setActionStartMs(System.currentTimeMillis() + (100 * times)) + .setDurationMs(500) + .setTargetIndex(-1) + .build(); + actions.add(action); + } + + AttackGymResponse result = doActions(actions); + + + + return result; + } + + + /** + * Creates a battle pokemon object to send with the request. + * + * @Param Pokemon + * @return BattlePokemonInfo + */ + private BattlePokemonInfo createBattlePokemon(Pokemon pokemon) { + BattlePokemonInfo info = BattlePokemonInfo + .newBuilder() + .setCurrentEnergy(0) + .setCurrentHealth(100) + .setPokemonData(pokemon.getDefaultInstanceForType()) + .build(); + return info; + } + + /** + * Get the Pokemondata for the defenders. + * + * @param index of defender(0 to gym lever) + * @return Battle + */ + private PokemonDataOuterClass.PokemonData getDefender(int index) throws LoginFailedException, RemoteServerException { + return gym.getGymMembers().get(0).getPokemonData(); + } + + /** + * Get the last action from server. + * + * @return BattleAction + */ + private BattleAction getLastActionFromServer() { + BattleAction action; + int actionCount = battleResponse.getBattleLog().getBattleActionsCount(); + action = battleResponse.getBattleLog().getBattleActions(actionCount - 1); + return action; + } + + /** + * Send blank action, used for polling the state of the battle. (i think). + * + * @return AttackGymResponse + */ + private AttackGymResponse sendBlankAction() throws LoginFailedException, RemoteServerException { + AttackGymMessage message = AttackGymMessage + .newBuilder() + .setGymId(gym.getId()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .setBattleId(battleResponse.getBattleId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestType.ATTACK_GYM, message); + api.getRequestHandler().sendServerRequests(serverRequest); + + + try { + return AttackGymResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + } + + + /** + * Do Actions in battle. + * + * @param actions list of actions to send in this request + * @return AttackGymResponse + */ + private AttackGymResponse doActions(List actions) throws LoginFailedException, RemoteServerException { + + + AttackGymMessage.Builder message = AttackGymMessage + .newBuilder() + .setGymId(gym.getId()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .setBattleId(battleResponse.getBattleId()); + + for (BattleAction action : actions) { + message.addAttackActions(action); + } + + + + ServerRequest serverRequest = new ServerRequest(RequestType.ATTACK_GYM, message.build()); + api.getRequestHandler().sendServerRequests(serverRequest); + + + try { + AttackGymResponse response = AttackGymResponse.parseFrom(serverRequest.getData()); + + if (response.getBattleLog().getState() == BattleState.DEFEATED + || response.getBattleLog().getState() == BattleState.VICTORY + || response.getBattleLog().getState() == BattleState.TIMED_OUT) { + concluded = true; + } + + outcome = response.getBattleLog().getState(); + + + + return response; + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + + } + +} diff --git a/src/main/java/com/pokegoapi/api/gym/Gym.java b/src/main/java/com/pokegoapi/api/gym/Gym.java new file mode 100644 index 00000000..9ece4120 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/gym/Gym.java @@ -0,0 +1,168 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.gym; + +import POGOProtos.Data.Gym.GymMembershipOuterClass.GymMembership; +import POGOProtos.Data.PokemonDataOuterClass.PokemonData; +import POGOProtos.Enums.PokemonIdOuterClass; +import POGOProtos.Enums.TeamColorOuterClass; +import POGOProtos.Map.Fort.FortDataOuterClass.FortData; +import POGOProtos.Networking.Requests.Messages.GetGymDetailsMessageOuterClass.GetGymDetailsMessage; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage.Builder; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; +import POGOProtos.Networking.Responses.GetGymDetailsResponseOuterClass.GetGymDetailsResponse; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.ProtocolStringList; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; + +import java.util.ArrayList; +import java.util.List; + +public class Gym { + private FortData proto; + private GetGymDetailsResponse details; + private PokemonGo api; + + /** + * Gym object. + * + */ + public Gym(PokemonGo api, FortData proto) { + this.api = api; + this.proto = proto; + this.details = null; + } + + public String getId() { + return proto.getId(); + } + + public double getLatitude() { + return proto.getLatitude(); + } + + public double getLongitude() { + return proto.getLongitude(); + } + + public boolean getEnabled() { + return proto.getEnabled(); + } + + public TeamColorOuterClass.TeamColor getOwnedByTeam() { + return proto.getOwnedByTeam(); + } + + public PokemonIdOuterClass.PokemonId getGuardPokemonId() { + return proto.getGuardPokemonId(); + } + + public int getGuardPokemonCp() { + return proto.getGuardPokemonCp(); + } + + public boolean getIsInBattle() { + return proto.getIsInBattle(); + } + + public boolean isAttackable() throws LoginFailedException, RemoteServerException { + return this.getGymMembers().size() != 0; + } + + public Battle battle(Pokemon[] team) { + return new Battle(api, team, this); + } + + + private GetGymDetailsResponse details() throws LoginFailedException, RemoteServerException { + if (details == null) { + GetGymDetailsMessage reqMsg = GetGymDetailsMessage + .newBuilder() + .setGymId(this.getId()) + .setGymLatitude(this.getLatitude()) + .setGymLongitude(this.getLongitude()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .build(); + + + ServerRequest serverRequest = new ServerRequest(RequestType.GET_GYM_DETAILS, reqMsg); + api.getRequestHandler().sendServerRequests(serverRequest); + + try { + details = GetGymDetailsResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + + } + + return details; + } + + public String getName() throws LoginFailedException, RemoteServerException { + return details().getName(); + } + + public ProtocolStringList getUrlsList() throws LoginFailedException, RemoteServerException { + return details().getUrlsList(); + } + + public GetGymDetailsResponse.Result getResult() throws LoginFailedException, RemoteServerException { + return details().getResult(); + } + + public boolean inRange() throws LoginFailedException, RemoteServerException { + GetGymDetailsResponse.Result result = getResult(); + return ( result != GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); + } + + public String getDescription() throws LoginFailedException, RemoteServerException { + return details().getDescription(); + } + + + public List getGymMembers() throws LoginFailedException, RemoteServerException { + return details().getGymState().getMembershipsList(); + } + + /** + * Get a list of pokemon defending this gym. + * + * @return List of pokemon + */ + public List getDefendingPokemon() throws LoginFailedException, RemoteServerException { + List data = new ArrayList(); + + for (GymMembership gymMember : getGymMembers()) { + data.add(gymMember.getPokemonData()); + } + + return data; + } + + protected PokemonGo getApi() { + return api; + } + + +} diff --git a/src/main/java/com/pokegoapi/api/inventory/CandyJar.java b/src/main/java/com/pokegoapi/api/inventory/CandyJar.java index beabe355..41f7b587 100644 --- a/src/main/java/com/pokegoapi/api/inventory/CandyJar.java +++ b/src/main/java/com/pokegoapi/api/inventory/CandyJar.java @@ -28,6 +28,10 @@ public class CandyJar { private HashMap candies; public CandyJar(PokemonGo pgo) { + reset(pgo); + } + + public void reset(PokemonGo pgo) { this.pgo = pgo; candies = new HashMap<>(); } @@ -77,6 +81,10 @@ public void removeCandy(PokemonFamilyId family, int amount) { * @return number of candies in jar */ public int getCandies(PokemonFamilyId family) { - return this.candies.get(family); + if (candies.containsKey(family)) { + return this.candies.get(family); + } else { + return 0; + } } } diff --git a/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java b/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java index 1521fa89..1a179512 100644 --- a/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java +++ b/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java @@ -16,6 +16,7 @@ package com.pokegoapi.api.inventory; import POGOProtos.Inventory.EggIncubatorOuterClass; +import POGOProtos.Inventory.EggIncubatorTypeOuterClass.EggIncubatorType; import POGOProtos.Networking.Requests.Messages.UseItemEggIncubatorMessageOuterClass.UseItemEggIncubatorMessage; import POGOProtos.Networking.Requests.RequestTypeOuterClass; import POGOProtos.Networking.Responses.UseItemEggIncubatorResponseOuterClass.UseItemEggIncubatorResponse; @@ -30,8 +31,6 @@ public class EggIncubator { private final EggIncubatorOuterClass.EggIncubator proto; private final PokemonGo pgo; - @Getter - private boolean inUse = false; /** * Create new EggIncubator with given proto. @@ -42,7 +41,6 @@ public class EggIncubator { public EggIncubator(PokemonGo pgo, EggIncubatorOuterClass.EggIncubator proto) { this.pgo = pgo; this.proto = proto; - this.inUse = proto.getPokemonId() != 0; } /** @@ -64,9 +62,7 @@ public int getUsesRemaining() { */ public UseItemEggIncubatorResponse.Result hatchEgg(EggPokemon egg) throws LoginFailedException, RemoteServerException { - if (!egg.getIsEgg()) { - return null; - } + UseItemEggIncubatorMessage reqMsg = UseItemEggIncubatorMessage.newBuilder() .setItemId(proto.getId()) .setPokemonId(egg.getId()) @@ -84,8 +80,51 @@ public UseItemEggIncubatorResponse.Result hatchEgg(EggPokemon egg) pgo.getInventories().updateInventories(true); - this.inUse = true; - return response.getResult(); } + + /** + * Get incubator id. + * + * @return the id + */ + public String getId() { + return proto.getId(); + } + + /** + * Get incubator type. + * + * @return EggIncubatorType + */ + public EggIncubatorType getType() { + return proto.getIncubatorType(); + } + + /** + * Get the target distance for egg to hatch. + * + * @return km distance to hatch the egg + */ + public double getKmTarget() { + return proto.getTargetKmWalked(); + } + + /** + * Get the current distance walked with this incubator. + * + * @return km walked with an egg + */ + public double getKmWalked() { + return proto.getStartKmWalked(); + } + + /** + * Is the incubator currently being used + * + * @return currently used or not + */ + public boolean isInUse() { + return getKmTarget() > pgo.getPlayerProfile().getStats().getKmWalked(); + } } diff --git a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java index 22b3cd89..e621f885 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java +++ b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java @@ -15,9 +15,17 @@ package com.pokegoapi.api.inventory; +import POGOProtos.Networking.Requests.Messages.GetHatchedEggsMessageOuterClass.GetHatchedEggsMessage; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; +import POGOProtos.Networking.Responses.GetHatchedEggsResponseOuterClass.GetHatchedEggsResponse; +import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.pokemon.EggPokemon; -import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.api.pokemon.HatchedEgg; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; + import lombok.Getter; import java.util.ArrayList; @@ -31,12 +39,48 @@ public class Hatchery { @Getter PokemonGo instance; - public Hatchery(PokemonGo instance) { - this.instance = instance; + public Hatchery(PokemonGo pgo) { + reset(pgo); + } + + public void reset(PokemonGo pgo) { + this.instance = pgo; + eggs = new HashSet<>(); } public void addEgg(EggPokemon egg) { + egg.setPgo(instance); eggs.add(egg); } + + + /** + * Get if eggs has hatched. + * + * @return list of hatched eggs + * @throws RemoteServerException e + * @throws LoginFailedException e + */ + public List queryHatchedEggs() throws RemoteServerException, LoginFailedException { + GetHatchedEggsMessage msg = GetHatchedEggsMessage.newBuilder().build(); + ServerRequest serverRequest = new ServerRequest(RequestType.GET_HATCHED_EGGS, msg); + instance.getRequestHandler().sendServerRequests(serverRequest); + + GetHatchedEggsResponse response = null; + try { + response = GetHatchedEggsResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + instance.getInventories().updateInventories(); + List eggs = new ArrayList(); + for (int i = 0; i < response.getPokemonIdCount(); i++) { + eggs.add(new HatchedEgg(response.getPokemonId(i), + response.getExperienceAwarded(i), + response.getCandyAwarded(i), + response.getStardustAwarded(i))); + } + return eggs; + } } diff --git a/src/main/java/com/pokegoapi/api/inventory/Inventories.java b/src/main/java/com/pokegoapi/api/inventory/Inventories.java index 2918dee2..5929fe11 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Inventories.java +++ b/src/main/java/com/pokegoapi/api/inventory/Inventories.java @@ -94,12 +94,12 @@ public void updateInventories() throws LoginFailedException, RemoteServerExcepti public void updateInventories(boolean forceUpdate) throws LoginFailedException, RemoteServerException { if (forceUpdate) { lastInventoryUpdate = 0; - itemBag = new ItemBag(api); - pokebank = new PokeBank(api); - candyjar = new CandyJar(api); - pokedex = new Pokedex(api); + itemBag.reset(api); + pokebank.reset(api); + candyjar.reset(api); + pokedex.reset(api); incubators = new ArrayList<>(); - hatchery = new Hatchery(api); + hatchery.reset(api); } GetInventoryMessage invReqMsg = GetInventoryMessage.newBuilder() .setLastTimestampMs(lastInventoryUpdate) diff --git a/src/main/java/com/pokegoapi/api/inventory/Item.java b/src/main/java/com/pokegoapi/api/inventory/Item.java index 584d7dbb..f3b744cd 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Item.java +++ b/src/main/java/com/pokegoapi/api/inventory/Item.java @@ -17,9 +17,13 @@ import POGOProtos.Inventory.Item.ItemDataOuterClass; import POGOProtos.Inventory.Item.ItemIdOuterClass.ItemId; +import lombok.Getter; +import lombok.Setter; public class Item { private ItemDataOuterClass.ItemData proto; + @Getter + @Setter private int count; public Item(ItemDataOuterClass.ItemData proto) { @@ -31,14 +35,6 @@ public ItemId getItemId() { return proto.getItemId(); } - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - public boolean isUnseen() { return proto.getUnseen(); } diff --git a/src/main/java/com/pokegoapi/api/inventory/ItemBag.java b/src/main/java/com/pokegoapi/api/inventory/ItemBag.java index e36e3a25..17f18897 100644 --- a/src/main/java/com/pokegoapi/api/inventory/ItemBag.java +++ b/src/main/java/com/pokegoapi/api/inventory/ItemBag.java @@ -40,6 +40,10 @@ public class ItemBag { private HashMap items; public ItemBag(PokemonGo pgo) { + reset(pgo); + } + + public void reset(PokemonGo pgo) { this.pgo = pgo; items = new HashMap<>(); } @@ -108,4 +112,17 @@ public Item getItem(ItemId type) { public Collection getItems() { return items.values(); } + + /** + * Get used space inside of player inventory. + * + * @return used space + */ + public int getItemsCount() { + int ct = 0; + for (Item item : items.values()) { + ct += item.getCount(); + } + return ct; + } } diff --git a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java index 9f6989cb..e4e736c6 100644 --- a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java +++ b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java @@ -33,8 +33,13 @@ public class PokeBank { @Getter PokemonGo instance; - public PokeBank(PokemonGo instance) { - this.instance = instance; + public PokeBank(PokemonGo pgo) { + reset(pgo); + } + + public void reset(PokemonGo pgo) { + this.instance = pgo; + pokemons = new ArrayList<>(); } /** @@ -81,4 +86,19 @@ public boolean test(Pokemon pokemn) { } }).collect(Collectors.toList()); } + + /** + * Get a pokemon by id. + * + * @param id the id + * @return the pokemon + */ + public Pokemon getPokemonById(final Long id) { + for (Pokemon pokemon : pokemons) { + if (pokemon.getId() == id) { + return pokemon; + } + } + return null; + } } diff --git a/src/main/java/com/pokegoapi/api/inventory/Pokedex.java b/src/main/java/com/pokegoapi/api/inventory/Pokedex.java index 8f342942..bcf23b3a 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Pokedex.java +++ b/src/main/java/com/pokegoapi/api/inventory/Pokedex.java @@ -24,11 +24,16 @@ public class Pokedex { - private final PokemonGo api; - private Map pokedexMap = new HashMap(); + private PokemonGo api; + private Map pokedexMap = new HashMap<>(); - public Pokedex(PokemonGo api) { - this.api = api; + public Pokedex(PokemonGo pgo) { + reset(pgo); + } + + public void reset(PokemonGo pgo) { + this.api = pgo; + pokedexMap = new HashMap<>(); } /** diff --git a/src/main/java/com/pokegoapi/api/map/Map.java b/src/main/java/com/pokegoapi/api/map/Map.java index 44aed570..b1cf1109 100644 --- a/src/main/java/com/pokegoapi/api/map/Map.java +++ b/src/main/java/com/pokegoapi/api/map/Map.java @@ -39,9 +39,11 @@ import com.annimon.stream.Collectors; import com.annimon.stream.Stream; import com.annimon.stream.function.Function; +import com.annimon.stream.function.Predicate; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.map.fort.FortDetails; +import com.pokegoapi.api.gym.Gym; import com.pokegoapi.api.map.pokemon.CatchablePokemon; import com.pokegoapi.api.map.pokemon.NearbyPokemon; import com.pokegoapi.exceptions.LoginFailedException; @@ -150,6 +152,24 @@ public List getSpawnPoints() throws LoginFailedException, RemoteServerExc return points; } + /** + * Get a list of gyms near the current location. + * + * @return List of gyms + */ + public List getGyms() throws LoginFailedException, RemoteServerException { + List gyms = new ArrayList<>(); + MapObjects objects = getMapObjects(); + + for (FortData fortdata : objects.getGyms()) { + gyms.add(new Gym(api, fortdata)); + } + + return gyms; + } + + + /** * Returns a list of decimated spawn points at current location. * @@ -462,7 +482,7 @@ public CatchPokemonResponse catchPokemon( .setHitPokemon(true) .setNormalizedHitPosition(normalizedHitPosition) .setNormalizedReticleSize(normalizedReticleSize) - .setSpawnPointGuid(catchablePokemon.getSpawnPointId()) + .setSpawnPointId(catchablePokemon.getSpawnPointId()) .setSpinModifier(spinModifier) .setPokeball(pokeball) .build(); diff --git a/src/main/java/com/pokegoapi/api/map/Point.java b/src/main/java/com/pokegoapi/api/map/Point.java index 386f8d5c..6502190d 100644 --- a/src/main/java/com/pokegoapi/api/map/Point.java +++ b/src/main/java/com/pokegoapi/api/map/Point.java @@ -22,10 +22,10 @@ public class Point { @Getter @Setter - private static double longitude; + private double longitude; @Getter @Setter - private static double latitude; + private double latitude; public Point(double latitude, double longitude) { this.latitude = latitude; diff --git a/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java b/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java index 4b8b3e39..5ab31826 100644 --- a/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java +++ b/src/main/java/com/pokegoapi/api/map/fort/Pokestop.java @@ -15,10 +15,13 @@ package com.pokegoapi.api.map.fort; +import POGOProtos.Inventory.Item.ItemIdOuterClass; import POGOProtos.Map.Fort.FortDataOuterClass; +import POGOProtos.Networking.Requests.Messages.AddFortModifierMessageOuterClass.AddFortModifierMessage; import POGOProtos.Networking.Requests.Messages.FortDetailsMessageOuterClass.FortDetailsMessage; import POGOProtos.Networking.Requests.Messages.FortSearchMessageOuterClass.FortSearchMessage; import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Responses.AddFortModifierResponseOuterClass; import POGOProtos.Networking.Responses.FortDetailsResponseOuterClass; import POGOProtos.Networking.Responses.FortSearchResponseOuterClass; import com.google.protobuf.InvalidProtocolBufferException; @@ -126,6 +129,31 @@ public PokestopLootResult loot() throws LoginFailedException, RemoteServerExcept return new PokestopLootResult(response); } + /** + * Adds a modifier to this pokestop. (i.e. add a lure module) + * + * @param item the modifier to add to this pokestop + * @throws LoginFailedException if login failed + * @throws RemoteServerException if the server failed to respond or the modifier could not be added to this pokestop + */ + public void addModifier(ItemIdOuterClass.ItemId item) throws LoginFailedException, RemoteServerException { + AddFortModifierMessage msg = AddFortModifierMessage.newBuilder() + .setModifierType(item) + .setFortId(getId()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .build(); + ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.ADD_FORT_MODIFIER, msg); + api.getRequestHandler().sendServerRequests(serverRequest); + AddFortModifierResponseOuterClass.AddFortModifierResponse response; + try { + //sadly the server response does not contain any information to verify if the request was successful + response = AddFortModifierResponseOuterClass.AddFortModifierResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + } + /** * Get more detailed information about a pokestop. * diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java b/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java index 3f794d1f..ef773ba4 100644 --- a/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java +++ b/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java @@ -66,7 +66,7 @@ public class CatchablePokemon { /** * Instantiates a new Catchable pokemon. - * + * * @param api * the api * @param proto @@ -85,7 +85,7 @@ public CatchablePokemon(PokemonGo api, MapPokemon proto) { /** * Instantiates a new Catchable pokemon. - * + * * @param api * the api * @param proto @@ -103,7 +103,7 @@ public CatchablePokemon(PokemonGo api, WildPokemon proto) { /** * Instantiates a new Catchable pokemon. - * + * * @param api * the api * @param proto @@ -126,7 +126,7 @@ public CatchablePokemon(PokemonGo api, FortData proto) { /** * Encounter pokemon encounter result. - * + * * @return the encounter result * @throws LoginFailedException * the login failed exception @@ -187,7 +187,7 @@ public CatchResult catchPokemonWithRazzBerry() throws LoginFailedException, /** * Tries to catch a pokemon (will attempt to use a pokeball, if you have * none will use greatball etc). - * + * * @return CatchResult * @throws LoginFailedException * if failed to login @@ -216,7 +216,7 @@ public CatchResult catchPokemon() throws LoginFailedException, /** * Tries to catch a pokeball with the given type. - * + * * @param pokeball * Type of pokeball * @return CatchResult @@ -232,7 +232,7 @@ public CatchResult catchPokemon(Pokeball pokeball) /** * Tried to catch a pokemon with given pokeball and max number of pokeballs. - * + * * @param pokeball * Type of pokeball * @param amount @@ -299,7 +299,7 @@ public CatchResult catchPokemon(double normalizedHitPosition, /** * Tries to catch a pokemon. - * + * * @param normalizedHitPosition * the normalized hit position * @param normalizedReticleSize @@ -320,8 +320,8 @@ public CatchResult catchPokemon(double normalizedHitPosition, * if the server failed to respond */ public CatchResult catchPokemon(double normalizedHitPosition, - double normalizedReticleSize, double spinModifier, Pokeball type, - int amount, int razberriesLimit) throws LoginFailedException, RemoteServerException { + double normalizedReticleSize, double spinModifier, Pokeball type, + int amount, int razberriesLimit) throws LoginFailedException, RemoteServerException { if (!isEncountered()) { return new CatchResult(); } @@ -340,7 +340,7 @@ public CatchResult catchPokemon(double normalizedHitPosition, .setEncounterId(getEncounterId()).setHitPokemon(true) .setNormalizedHitPosition(normalizedHitPosition) .setNormalizedReticleSize(normalizedReticleSize) - .setSpawnPointGuid(getSpawnPointId()) + .setSpawnPointId(getSpawnPointId()) .setSpinModifier(spinModifier) .setPokeball(type.getBallType()).build(); ServerRequest serverRequest = new ServerRequest( @@ -383,7 +383,7 @@ public CatchItemResult useItem(ItemId item) throws LoginFailedException, RemoteS UseItemCaptureMessage reqMsg = UseItemCaptureMessage .newBuilder() .setEncounterId(this.getEncounterId()) - .setSpawnPointGuid(this.getSpawnPointId()) + .setSpawnPointId(this.getSpawnPointId()) .setItemId(item) .build(); diff --git a/src/main/java/com/pokegoapi/api/player/PlayerProfile.java b/src/main/java/com/pokegoapi/api/player/PlayerProfile.java index 6d36d4d7..0cb58cc3 100644 --- a/src/main/java/com/pokegoapi/api/player/PlayerProfile.java +++ b/src/main/java/com/pokegoapi/api/player/PlayerProfile.java @@ -73,7 +73,7 @@ public PlayerProfile(PokemonGo api) throws LoginFailedException, RemoteServerExc * @throws LoginFailedException the login failed exception * @throws RemoteServerException the remote server exception */ - public void updateProfile() throws LoginFailedException, RemoteServerException { + public void updateProfile() throws RemoteServerException, LoginFailedException { GetPlayerMessage getPlayerReqMsg = GetPlayerMessage.newBuilder().build(); ServerRequest getPlayerServerRequest = new ServerRequest(RequestType.GET_PLAYER, getPlayerReqMsg); api.getRequestHandler().sendServerRequests(getPlayerServerRequest); @@ -82,14 +82,14 @@ public void updateProfile() throws LoginFailedException, RemoteServerException { try { playerResponse = GetPlayerResponseOuterClass.GetPlayerResponse.parseFrom(getPlayerServerRequest.getData()); } catch (InvalidProtocolBufferException e) { - e.printStackTrace(); + throw new RemoteServerException(e); } badge = playerResponse.getPlayerData().getEquippedBadge(); creationTime = playerResponse.getPlayerData().getCreationTimestampMs(); itemStorage = playerResponse.getPlayerData().getMaxItemStorage(); pokemonStorage = playerResponse.getPlayerData().getMaxPokemonStorage(); - team = Team.values()[playerResponse.getPlayerData().getTeam()]; + team = Team.values()[playerResponse.getPlayerData().getTeamValue()]; username = playerResponse.getPlayerData().getUsername(); final PlayerAvatar avatarApi = new PlayerAvatar(); diff --git a/src/main/java/com/pokegoapi/api/player/Team.java b/src/main/java/com/pokegoapi/api/player/Team.java index c4eef4e7..07df28c0 100644 --- a/src/main/java/com/pokegoapi/api/player/Team.java +++ b/src/main/java/com/pokegoapi/api/player/Team.java @@ -15,6 +15,8 @@ package com.pokegoapi.api.player; +import lombok.Getter; + public enum Team { // VALUES CONFIRMED TEAM_NONE(0), @@ -22,13 +24,10 @@ public enum Team { TEAM_VALOR(2), TEAM_INSTINCT(3); + @Getter private int value; private Team(int value) { this.value = value; } - - public int getValue() { - return value; - } } diff --git a/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java b/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java index 120744b6..be16eb7d 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java +++ b/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java @@ -16,7 +16,15 @@ package com.pokegoapi.api.pokemon; import POGOProtos.Data.PokemonDataOuterClass.PokemonData; +import POGOProtos.Networking.Responses.UseItemEggIncubatorResponseOuterClass.UseItemEggIncubatorResponse; + +import com.annimon.stream.Stream; +import com.annimon.stream.function.Predicate; import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.inventory.EggIncubator; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; + import lombok.Setter; /** @@ -30,28 +38,65 @@ public class EggPokemon { private PokemonData proto; // API METHODS // + /** + * Incubate this egg. + * + * @param incubator : the incubator + * @return status of putting egg in incubator + * @throws LoginFailedException e + * @throws RemoteServerException e + */ + public UseItemEggIncubatorResponse.Result incubate(EggIncubator incubator) + throws LoginFailedException, RemoteServerException { + if (incubator.isInUse()) { + throw new IllegalArgumentException("Incubator already used"); + } + return incubator.hatchEgg(this); + } + + /** + * Get the current distance that has been done with this egg + * @return get distance already walked + */ + public double getEggKmWalked() { + if (!isIncubate()) + return 0; + EggIncubator incubator = Stream.of(pgo.getInventories().getIncubators()) + .filter(new Predicate() { + @Override + public boolean test(EggIncubator incub) { + return incub.getId().equals(proto.getEggIncubatorId()); + } + }).findFirst().orElse(null); + // incubator should not be null but why not eh + if (incubator == null) + return 0; + else + return proto.getEggKmWalkedTarget() + - (incubator.getKmTarget() - pgo.getPlayerProfile().getStats().getKmWalked()); + } // DELEGATE METHODS BELOW // + /** + * Build a EggPokemon wrapper from the proto. + * + * @param proto : the prototype + */ public EggPokemon(PokemonData proto) { + if (!proto.getIsEgg()) { + throw new IllegalArgumentException("You cant build a EggPokemon without a valid PokemonData."); + } this.proto = proto; } public long getId() { return proto.getId(); } - - public boolean getIsEgg() { - return proto.getIsEgg(); - } - + public double getEggKmWalkedTarget() { return proto.getEggKmWalkedTarget(); } - public double getEggKmWalkedStart() { - return proto.getEggKmWalkedStart(); - } - public long getCapturedCellId() { return proto.getCapturedCellId(); } @@ -63,6 +108,10 @@ public long getCreationTimeMs() { public String getEggIncubatorId() { return proto.getEggIncubatorId(); } + + public boolean isIncubate() { + return proto.getEggIncubatorId().length() > 0; + } @Override public int hashCode() { diff --git a/src/main/java/com/pokegoapi/api/pokemon/HatchedEgg.java b/src/main/java/com/pokegoapi/api/pokemon/HatchedEgg.java new file mode 100644 index 00000000..afe8f000 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/HatchedEgg.java @@ -0,0 +1,29 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class HatchedEgg { + + private Long id; + private int experience; + private int candy; + private int stardust; +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/MovementType.java b/src/main/java/com/pokegoapi/api/pokemon/MovementType.java new file mode 100644 index 00000000..46a6c355 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/MovementType.java @@ -0,0 +1,11 @@ +package com.pokegoapi.api.pokemon; + + +public enum MovementType { + PSYCHIC, + FLYING, + ELETRIC, + NORMAL, + HOVERING, + JUMP, ELECTRIC; +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java b/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java index b9d4c0d4..d13d6e67 100644 --- a/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java +++ b/src/main/java/com/pokegoapi/api/pokemon/Pokemon.java @@ -19,16 +19,21 @@ import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; import POGOProtos.Enums.PokemonIdOuterClass; import POGOProtos.Enums.PokemonMoveOuterClass; -import POGOProtos.Inventory.Item.ItemIdOuterClass; import POGOProtos.Inventory.Item.ItemIdOuterClass.ItemId; import POGOProtos.Networking.Requests.Messages.EvolvePokemonMessageOuterClass.EvolvePokemonMessage; import POGOProtos.Networking.Requests.Messages.NicknamePokemonMessageOuterClass.NicknamePokemonMessage; import POGOProtos.Networking.Requests.Messages.ReleasePokemonMessageOuterClass.ReleasePokemonMessage; +import POGOProtos.Networking.Requests.Messages.SetFavoritePokemonMessageOuterClass.SetFavoritePokemonMessage; +import POGOProtos.Networking.Requests.Messages.UpgradePokemonMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.UpgradePokemonMessageOuterClass.UpgradePokemonMessage; import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; import POGOProtos.Networking.Responses.EvolvePokemonResponseOuterClass.EvolvePokemonResponse; import POGOProtos.Networking.Responses.NicknamePokemonResponseOuterClass.NicknamePokemonResponse; import POGOProtos.Networking.Responses.ReleasePokemonResponseOuterClass.ReleasePokemonResponse; import POGOProtos.Networking.Responses.ReleasePokemonResponseOuterClass.ReleasePokemonResponse.Result; +import POGOProtos.Networking.Responses.SetFavoritePokemonResponseOuterClass.SetFavoritePokemonResponse; +import POGOProtos.Networking.Responses.UpgradePokemonResponseOuterClass; +import POGOProtos.Networking.Responses.UpgradePokemonResponseOuterClass.UpgradePokemonResponse; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.map.pokemon.EvolutionResult; @@ -46,6 +51,7 @@ public class Pokemon { private static final String TAG = Pokemon.class.getSimpleName(); private final PokemonGo pgo; private PokemonData proto; + private PokemonMeta meta; // API METHODS // @@ -117,6 +123,63 @@ public NicknamePokemonResponse.Result renamePokemon(String nickname) return response.getResult(); } + /** + * Function to mark the pokemon as favorite or not. + * + * @param markFavorite Mark Pokemon as Favorite? + * @return the SetFavoritePokemonResponse.Result + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public SetFavoritePokemonResponse.Result setFavoritePokemon(boolean markFavorite) + throws LoginFailedException, RemoteServerException { + SetFavoritePokemonMessage reqMsg = SetFavoritePokemonMessage.newBuilder() + .setPokemonId(getId()) + .setIsFavorite(markFavorite) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestType.SET_FAVORITE_POKEMON, reqMsg); + pgo.getRequestHandler().sendServerRequests(serverRequest); + + SetFavoritePokemonResponse response; + try { + response = SetFavoritePokemonResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + + pgo.getInventories().getPokebank().removePokemon(this); + pgo.getInventories().updateInventories(); + + return response.getResult(); + } + + /** + * Powers up a pokemon with candy and stardust. + * After powering up this pokemon object will reflect the new changes. + * + * @return The result + * @throws LoginFailedException the login failed exception + * @throws RemoteServerException the remote server exception + */ + public UpgradePokemonResponse.Result powerUp() throws LoginFailedException, RemoteServerException { + UpgradePokemonMessage reqMsg = UpgradePokemonMessage.newBuilder() + .setPokemonId(this.getId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestType.UPGRADE_POKEMON, reqMsg); + pgo.getRequestHandler().sendServerRequests(serverRequest); + + UpgradePokemonResponse response; + try { + response = UpgradePokemonResponse.parseFrom(serverRequest.getData()); + this.proto = response.getUpgradedPokemon(); + return response.getResult(); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + } + /** * Evolve evolution result. * @@ -146,12 +209,25 @@ public EvolutionResult evolve() throws LoginFailedException, RemoteServerExcepti return result; } + /** + * Get the meta info for a pokemon. + * + * @return PokemonMeta + */ + public PokemonMeta getMeta() { + if (meta == null) { + meta = PokemonMetaRegistry.getMeta(this.getPokemonId()); + } + + return meta; + } + public int getCandy() { return pgo.getInventories().getCandyjar().getCandies(getPokemonFamily()); } public PokemonFamilyId getPokemonFamily() { - return PokemonFamilyMap.getFamily(this.getPokemonId()); + return getMeta().getFamily(); } public boolean equals(Pokemon other) { @@ -190,7 +266,7 @@ public PokemonMoveOuterClass.PokemonMove getMove2() { return proto.getMove2(); } - public int getDeployedFortId() { + public String getDeployedFortId() { return proto.getDeployedFortId(); } @@ -229,6 +305,14 @@ public int getIndividualDefense() { public int getIndividualStamina() { return proto.getIndividualStamina(); } + + /** + * Calculates the pokemons IV ratio. + * @return the pokemons IV ratio as a double between 0 and 1.0, 1.0 being perfect IVs + */ + public double getIvRatio() { + return (this.getIndividualAttack() + this.getIndividualDefense() + this.getIndividualStamina()) / 45.0; + } public float getCpMultiplier() { return proto.getCpMultiplier(); @@ -257,7 +341,16 @@ public String getEggIncubatorId() { public long getCreationTimeMs() { return proto.getCreationTimeMs(); } + + /** + * Checks whether the Pokémon is set as favorite. + * @return true if the Pokémon is set as favorite + */ + public boolean isFavorite() { + return proto.getFavorite() > 0; + } + @Deprecated public boolean getFavorite() { return proto.getFavorite() > 0; } @@ -273,4 +366,25 @@ public boolean getFromFort() { public void debug() { Log.d(TAG, proto.toString()); } + + + public int getBaseStam() { + return getMeta().getBaseStamina(); + } + + public double getBaseCaptureRate() { + return getMeta().getBaseCaptureRate(); + } + + public int getCandiesToEvolve() { + return getMeta().getCandyToEvolve(); + } + + public double getBaseFleeRate() { + return getMeta().getBaseFleeRate(); + } + + public PokemonIdOuterClass.PokemonId getParent() { + return getMeta().getParentId(); + } } diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonClass.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonClass.java new file mode 100644 index 00000000..ee716cb5 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonClass.java @@ -0,0 +1,13 @@ +package com.pokegoapi.api.pokemon; + +public enum PokemonClass { + NONE, + VERY_COMMON, + COMMON, + UNCOMMON, + RARE, + VERY_RARE, + EPIC, + LEGENDARY, + MYTHIC; +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonFamilyMap.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonFamilyMap.java deleted file mode 100644 index 354150a8..00000000 --- a/src/main/java/com/pokegoapi/api/pokemon/PokemonFamilyMap.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.pokegoapi.api.pokemon; - -import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; -import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; - -import java.util.EnumMap; - -public class PokemonFamilyMap { - - private static EnumMap familys = new EnumMap<>(PokemonId.class); - private static EnumMap highestForFamily = new EnumMap<>(PokemonFamilyId.class); - - static { - familys.put(PokemonId.BULBASAUR, PokemonFamilyId.FAMILY_BULBASAUR); - familys.put(PokemonId.IVYSAUR, PokemonFamilyId.FAMILY_BULBASAUR); - familys.put(PokemonId.VENUSAUR, PokemonFamilyId.FAMILY_BULBASAUR); - highestForFamily.put(PokemonFamilyId.FAMILY_BULBASAUR, PokemonId.VENUSAUR); - familys.put(PokemonId.CHARMANDER, PokemonFamilyId.FAMILY_CHARMANDER); - familys.put(PokemonId.CHARMELEON, PokemonFamilyId.FAMILY_CHARMANDER); - familys.put(PokemonId.CHARIZARD, PokemonFamilyId.FAMILY_CHARMANDER); - highestForFamily.put(PokemonFamilyId.FAMILY_CHARMANDER, PokemonId.CHARIZARD); - familys.put(PokemonId.SQUIRTLE, PokemonFamilyId.FAMILY_SQUIRTLE); - familys.put(PokemonId.WARTORTLE, PokemonFamilyId.FAMILY_SQUIRTLE); - familys.put(PokemonId.BLASTOISE, PokemonFamilyId.FAMILY_SQUIRTLE); - highestForFamily.put(PokemonFamilyId.FAMILY_SQUIRTLE, PokemonId.BLASTOISE); - familys.put(PokemonId.CATERPIE, PokemonFamilyId.FAMILY_CATERPIE); - familys.put(PokemonId.METAPOD, PokemonFamilyId.FAMILY_CATERPIE); - familys.put(PokemonId.BUTTERFREE, PokemonFamilyId.FAMILY_CATERPIE); - highestForFamily.put(PokemonFamilyId.FAMILY_CATERPIE, PokemonId.BUTTERFREE); - familys.put(PokemonId.WEEDLE, PokemonFamilyId.FAMILY_WEEDLE); - familys.put(PokemonId.KAKUNA, PokemonFamilyId.FAMILY_WEEDLE); - familys.put(PokemonId.BEEDRILL, PokemonFamilyId.FAMILY_WEEDLE); - highestForFamily.put(PokemonFamilyId.FAMILY_WEEDLE, PokemonId.BEEDRILL); - familys.put(PokemonId.PIDGEY, PokemonFamilyId.FAMILY_PIDGEY); - familys.put(PokemonId.PIDGEOTTO, PokemonFamilyId.FAMILY_PIDGEY); - familys.put(PokemonId.PIDGEOT, PokemonFamilyId.FAMILY_PIDGEY); - highestForFamily.put(PokemonFamilyId.FAMILY_PIDGEY, PokemonId.PIDGEOT); - familys.put(PokemonId.RATTATA, PokemonFamilyId.FAMILY_RATTATA); - familys.put(PokemonId.RATICATE, PokemonFamilyId.FAMILY_RATTATA); - highestForFamily.put(PokemonFamilyId.FAMILY_RATTATA, PokemonId.RATICATE); - familys.put(PokemonId.SPEAROW, PokemonFamilyId.FAMILY_SPEAROW); - familys.put(PokemonId.FEAROW, PokemonFamilyId.FAMILY_SPEAROW); - highestForFamily.put(PokemonFamilyId.FAMILY_SPEAROW, PokemonId.FEAROW); - familys.put(PokemonId.EKANS, PokemonFamilyId.FAMILY_EKANS); - familys.put(PokemonId.ARBOK, PokemonFamilyId.FAMILY_EKANS); - highestForFamily.put(PokemonFamilyId.FAMILY_EKANS, PokemonId.ARBOK); - familys.put(PokemonId.PIKACHU, PokemonFamilyId.FAMILY_PIKACHU); - familys.put(PokemonId.RAICHU, PokemonFamilyId.FAMILY_PIKACHU); - highestForFamily.put(PokemonFamilyId.FAMILY_PIKACHU, PokemonId.RAICHU); - familys.put(PokemonId.SANDSHREW, PokemonFamilyId.FAMILY_SANDSHREW); - familys.put(PokemonId.SANDSLASH, PokemonFamilyId.FAMILY_SANDSHREW); - highestForFamily.put(PokemonFamilyId.FAMILY_SANDSHREW, PokemonId.SANDSLASH); - familys.put(PokemonId.NIDORAN_FEMALE, PokemonFamilyId.FAMILY_NIDORAN_FEMALE); - familys.put(PokemonId.NIDORINA, PokemonFamilyId.FAMILY_NIDORAN_FEMALE); - familys.put(PokemonId.NIDOQUEEN, PokemonFamilyId.FAMILY_NIDORAN_FEMALE); - highestForFamily.put(PokemonFamilyId.FAMILY_NIDORAN_FEMALE, PokemonId.NIDOQUEEN); - familys.put(PokemonId.NIDORAN_MALE, PokemonFamilyId.FAMILY_NIDORAN_MALE); - familys.put(PokemonId.NIDORINO, PokemonFamilyId.FAMILY_NIDORAN_MALE); - familys.put(PokemonId.NIDOKING, PokemonFamilyId.FAMILY_NIDORAN_MALE); - highestForFamily.put(PokemonFamilyId.FAMILY_NIDORAN_MALE, PokemonId.NIDOKING); - familys.put(PokemonId.CLEFAIRY, PokemonFamilyId.FAMILY_CLEFAIRY); - familys.put(PokemonId.CLEFABLE, PokemonFamilyId.FAMILY_CLEFAIRY); - highestForFamily.put(PokemonFamilyId.FAMILY_CLEFAIRY, PokemonId.CLEFABLE); - familys.put(PokemonId.VULPIX, PokemonFamilyId.FAMILY_VULPIX); - familys.put(PokemonId.NINETALES, PokemonFamilyId.FAMILY_VULPIX); - highestForFamily.put(PokemonFamilyId.FAMILY_VULPIX, PokemonId.NINETALES); - familys.put(PokemonId.JIGGLYPUFF, PokemonFamilyId.FAMILY_JIGGLYPUFF); - familys.put(PokemonId.WIGGLYTUFF, PokemonFamilyId.FAMILY_JIGGLYPUFF); - highestForFamily.put(PokemonFamilyId.FAMILY_JIGGLYPUFF, PokemonId.WIGGLYTUFF); - familys.put(PokemonId.ZUBAT, PokemonFamilyId.FAMILY_ZUBAT); - familys.put(PokemonId.GOLBAT, PokemonFamilyId.FAMILY_ZUBAT); - highestForFamily.put(PokemonFamilyId.FAMILY_ZUBAT, PokemonId.GOLBAT); - familys.put(PokemonId.ODDISH, PokemonFamilyId.FAMILY_ODDISH); - familys.put(PokemonId.GLOOM, PokemonFamilyId.FAMILY_ODDISH); - familys.put(PokemonId.VILEPLUME, PokemonFamilyId.FAMILY_ODDISH); - highestForFamily.put(PokemonFamilyId.FAMILY_ODDISH, PokemonId.VILEPLUME); - familys.put(PokemonId.PARAS, PokemonFamilyId.FAMILY_PARAS); - familys.put(PokemonId.PARASECT, PokemonFamilyId.FAMILY_PARAS); - highestForFamily.put(PokemonFamilyId.FAMILY_PARAS, PokemonId.PARASECT); - familys.put(PokemonId.VENONAT, PokemonFamilyId.FAMILY_VENONAT); - familys.put(PokemonId.VENOMOTH, PokemonFamilyId.FAMILY_VENONAT); - highestForFamily.put(PokemonFamilyId.FAMILY_VENONAT, PokemonId.VENOMOTH); - familys.put(PokemonId.DIGLETT, PokemonFamilyId.FAMILY_DIGLETT); - familys.put(PokemonId.DUGTRIO, PokemonFamilyId.FAMILY_DIGLETT); - highestForFamily.put(PokemonFamilyId.FAMILY_DIGLETT, PokemonId.DUGTRIO); - familys.put(PokemonId.MEOWTH, PokemonFamilyId.FAMILY_MEOWTH); - familys.put(PokemonId.PERSIAN, PokemonFamilyId.FAMILY_MEOWTH); - highestForFamily.put(PokemonFamilyId.FAMILY_MEOWTH, PokemonId.PERSIAN); - familys.put(PokemonId.PSYDUCK, PokemonFamilyId.FAMILY_PSYDUCK); - familys.put(PokemonId.GOLDUCK, PokemonFamilyId.FAMILY_PSYDUCK); - highestForFamily.put(PokemonFamilyId.FAMILY_PSYDUCK, PokemonId.GOLDUCK); - familys.put(PokemonId.MANKEY, PokemonFamilyId.FAMILY_MANKEY); - familys.put(PokemonId.PRIMEAPE, PokemonFamilyId.FAMILY_MANKEY); - highestForFamily.put(PokemonFamilyId.FAMILY_MANKEY, PokemonId.PRIMEAPE); - familys.put(PokemonId.GROWLITHE, PokemonFamilyId.FAMILY_GROWLITHE); - familys.put(PokemonId.ARCANINE, PokemonFamilyId.FAMILY_GROWLITHE); - highestForFamily.put(PokemonFamilyId.FAMILY_GROWLITHE, PokemonId.ARCANINE); - familys.put(PokemonId.POLIWAG, PokemonFamilyId.FAMILY_POLIWAG); - familys.put(PokemonId.POLIWHIRL, PokemonFamilyId.FAMILY_POLIWAG); - familys.put(PokemonId.POLIWRATH, PokemonFamilyId.FAMILY_POLIWAG); - highestForFamily.put(PokemonFamilyId.FAMILY_POLIWAG, PokemonId.POLIWRATH); - familys.put(PokemonId.ABRA, PokemonFamilyId.FAMILY_ABRA); - familys.put(PokemonId.KADABRA, PokemonFamilyId.FAMILY_ABRA); - familys.put(PokemonId.ALAKAZAM, PokemonFamilyId.FAMILY_ABRA); - highestForFamily.put(PokemonFamilyId.FAMILY_ABRA, PokemonId.ALAKAZAM); - familys.put(PokemonId.MACHOP, PokemonFamilyId.FAMILY_MACHOP); - familys.put(PokemonId.MACHOKE, PokemonFamilyId.FAMILY_MACHOP); - familys.put(PokemonId.MACHAMP, PokemonFamilyId.FAMILY_MACHOP); - highestForFamily.put(PokemonFamilyId.FAMILY_MACHOP, PokemonId.MACHAMP); - familys.put(PokemonId.BELLSPROUT, PokemonFamilyId.FAMILY_BELLSPROUT); - familys.put(PokemonId.WEEPINBELL, PokemonFamilyId.FAMILY_BELLSPROUT); - familys.put(PokemonId.VICTREEBEL, PokemonFamilyId.FAMILY_BELLSPROUT); - highestForFamily.put(PokemonFamilyId.FAMILY_BELLSPROUT, PokemonId.VICTREEBEL); - familys.put(PokemonId.TENTACOOL, PokemonFamilyId.FAMILY_TENTACOOL); - familys.put(PokemonId.TENTACRUEL, PokemonFamilyId.FAMILY_TENTACOOL); - highestForFamily.put(PokemonFamilyId.FAMILY_TENTACOOL, PokemonId.TENTACRUEL); - familys.put(PokemonId.GEODUDE, PokemonFamilyId.FAMILY_GEODUDE); - familys.put(PokemonId.GRAVELER, PokemonFamilyId.FAMILY_GEODUDE); - familys.put(PokemonId.GOLEM, PokemonFamilyId.FAMILY_GEODUDE); - highestForFamily.put(PokemonFamilyId.FAMILY_GEODUDE, PokemonId.GOLEM); - familys.put(PokemonId.PONYTA, PokemonFamilyId.FAMILY_PONYTA); - familys.put(PokemonId.RAPIDASH, PokemonFamilyId.FAMILY_PONYTA); - highestForFamily.put(PokemonFamilyId.FAMILY_PONYTA, PokemonId.RAPIDASH); - familys.put(PokemonId.SLOWPOKE, PokemonFamilyId.FAMILY_SLOWPOKE); - familys.put(PokemonId.SLOWBRO, PokemonFamilyId.FAMILY_SLOWPOKE); - highestForFamily.put(PokemonFamilyId.FAMILY_SLOWPOKE, PokemonId.SLOWBRO); - familys.put(PokemonId.MAGNEMITE, PokemonFamilyId.FAMILY_MAGNEMITE); - familys.put(PokemonId.MAGNETON, PokemonFamilyId.FAMILY_MAGNEMITE); - highestForFamily.put(PokemonFamilyId.FAMILY_MAGNEMITE, PokemonId.MAGNETON); - familys.put(PokemonId.FARFETCHD, PokemonFamilyId.FAMILY_FARFETCHD); - highestForFamily.put(PokemonFamilyId.FAMILY_FARFETCHD, PokemonId.FARFETCHD); - familys.put(PokemonId.DODUO, PokemonFamilyId.FAMILY_DODUO); - familys.put(PokemonId.DODRIO, PokemonFamilyId.FAMILY_DODUO); - highestForFamily.put(PokemonFamilyId.FAMILY_DODUO, PokemonId.DODRIO); - familys.put(PokemonId.SEEL, PokemonFamilyId.FAMILY_SEEL); - familys.put(PokemonId.DEWGONG, PokemonFamilyId.FAMILY_SEEL); - highestForFamily.put(PokemonFamilyId.FAMILY_SEEL, PokemonId.DEWGONG); - familys.put(PokemonId.GRIMER, PokemonFamilyId.FAMILY_GRIMER); - familys.put(PokemonId.MUK, PokemonFamilyId.FAMILY_GRIMER); - highestForFamily.put(PokemonFamilyId.FAMILY_GRIMER, PokemonId.MUK); - familys.put(PokemonId.SHELLDER, PokemonFamilyId.FAMILY_SHELLDER); - familys.put(PokemonId.CLOYSTER, PokemonFamilyId.FAMILY_SHELLDER); - highestForFamily.put(PokemonFamilyId.FAMILY_SHELLDER, PokemonId.CLOYSTER); - familys.put(PokemonId.GASTLY, PokemonFamilyId.FAMILY_GASTLY); - familys.put(PokemonId.HAUNTER, PokemonFamilyId.FAMILY_GASTLY); - familys.put(PokemonId.GENGAR, PokemonFamilyId.FAMILY_GASTLY); - highestForFamily.put(PokemonFamilyId.FAMILY_GASTLY, PokemonId.GENGAR); - familys.put(PokemonId.ONIX, PokemonFamilyId.FAMILY_ONIX); - highestForFamily.put(PokemonFamilyId.FAMILY_ONIX, PokemonId.ONIX); - familys.put(PokemonId.DROWZEE, PokemonFamilyId.FAMILY_DROWZEE); - highestForFamily.put(PokemonFamilyId.FAMILY_DROWZEE, PokemonId.DROWZEE); - // MISSING ENUM IN PROTO - //familys.put(PokemonId.HYPNO,PokemonFamilyId.FAMILY_HYPNO); - familys.put(PokemonId.KRABBY, PokemonFamilyId.FAMILY_KRABBY); - familys.put(PokemonId.KINGLER, PokemonFamilyId.FAMILY_KRABBY); - highestForFamily.put(PokemonFamilyId.FAMILY_KRABBY, PokemonId.KINGLER); - familys.put(PokemonId.VOLTORB, PokemonFamilyId.FAMILY_VOLTORB); - familys.put(PokemonId.ELECTRODE, PokemonFamilyId.FAMILY_VOLTORB); - highestForFamily.put(PokemonFamilyId.FAMILY_VOLTORB, PokemonId.ELECTRODE); - familys.put(PokemonId.EXEGGCUTE, PokemonFamilyId.FAMILY_EXEGGCUTE); - familys.put(PokemonId.EXEGGUTOR, PokemonFamilyId.FAMILY_EXEGGCUTE); - highestForFamily.put(PokemonFamilyId.FAMILY_EXEGGCUTE, PokemonId.EXEGGUTOR); - familys.put(PokemonId.CUBONE, PokemonFamilyId.FAMILY_CUBONE); - familys.put(PokemonId.MAROWAK, PokemonFamilyId.FAMILY_CUBONE); - highestForFamily.put(PokemonFamilyId.FAMILY_CUBONE, PokemonId.MAROWAK); - familys.put(PokemonId.HITMONLEE, PokemonFamilyId.FAMILY_HITMONLEE); - highestForFamily.put(PokemonFamilyId.FAMILY_HITMONLEE, PokemonId.HITMONLEE); - familys.put(PokemonId.HITMONCHAN, PokemonFamilyId.FAMILY_HITMONCHAN); - highestForFamily.put(PokemonFamilyId.FAMILY_HITMONCHAN, PokemonId.HITMONCHAN); - familys.put(PokemonId.LICKITUNG, PokemonFamilyId.FAMILY_LICKITUNG); - highestForFamily.put(PokemonFamilyId.FAMILY_LICKITUNG, PokemonId.LICKITUNG); - familys.put(PokemonId.KOFFING, PokemonFamilyId.FAMILY_KOFFING); - familys.put(PokemonId.WEEZING, PokemonFamilyId.FAMILY_KOFFING); - highestForFamily.put(PokemonFamilyId.FAMILY_KOFFING, PokemonId.WEEZING); - familys.put(PokemonId.RHYHORN, PokemonFamilyId.FAMILY_RHYHORN); - familys.put(PokemonId.RHYDON, PokemonFamilyId.FAMILY_RHYHORN); - highestForFamily.put(PokemonFamilyId.FAMILY_RHYHORN, PokemonId.RHYDON); - familys.put(PokemonId.CHANSEY, PokemonFamilyId.FAMILY_CHANSEY); - highestForFamily.put(PokemonFamilyId.FAMILY_CHANSEY, PokemonId.CHANSEY); - familys.put(PokemonId.TANGELA, PokemonFamilyId.FAMILY_TANGELA); - highestForFamily.put(PokemonFamilyId.FAMILY_TANGELA, PokemonId.TANGELA); - familys.put(PokemonId.KANGASKHAN, PokemonFamilyId.FAMILY_KANGASKHAN); - highestForFamily.put(PokemonFamilyId.FAMILY_KANGASKHAN, PokemonId.KANGASKHAN); - familys.put(PokemonId.HORSEA, PokemonFamilyId.FAMILY_HORSEA); - familys.put(PokemonId.SEADRA, PokemonFamilyId.FAMILY_HORSEA); - highestForFamily.put(PokemonFamilyId.FAMILY_HORSEA, PokemonId.SEADRA); - familys.put(PokemonId.GOLDEEN, PokemonFamilyId.FAMILY_GOLDEEN); - familys.put(PokemonId.SEAKING, PokemonFamilyId.FAMILY_GOLDEEN); - highestForFamily.put(PokemonFamilyId.FAMILY_GOLDEEN, PokemonId.SEAKING); - familys.put(PokemonId.STARYU, PokemonFamilyId.FAMILY_STARYU); - familys.put(PokemonId.STARMIE, PokemonFamilyId.FAMILY_STARYU); - highestForFamily.put(PokemonFamilyId.FAMILY_STARYU, PokemonId.STARMIE); - familys.put(PokemonId.MR_MIME, PokemonFamilyId.FAMILY_MR_MIME); - highestForFamily.put(PokemonFamilyId.FAMILY_MR_MIME, PokemonId.MR_MIME); - familys.put(PokemonId.SCYTHER, PokemonFamilyId.FAMILY_SCYTHER); - highestForFamily.put(PokemonFamilyId.FAMILY_SCYTHER, PokemonId.SCYTHER); - familys.put(PokemonId.JYNX, PokemonFamilyId.FAMILY_JYNX); - highestForFamily.put(PokemonFamilyId.FAMILY_JYNX, PokemonId.JYNX); - familys.put(PokemonId.ELECTABUZZ, PokemonFamilyId.FAMILY_ELECTABUZZ); - highestForFamily.put(PokemonFamilyId.FAMILY_ELECTABUZZ, PokemonId.ELECTABUZZ); - familys.put(PokemonId.MAGMAR, PokemonFamilyId.FAMILY_MAGMAR); - highestForFamily.put(PokemonFamilyId.FAMILY_MAGMAR, PokemonId.MAGMAR); - familys.put(PokemonId.PINSIR, PokemonFamilyId.FAMILY_PINSIR); - highestForFamily.put(PokemonFamilyId.FAMILY_PINSIR, PokemonId.PINSIR); - familys.put(PokemonId.TAUROS, PokemonFamilyId.FAMILY_TAUROS); - highestForFamily.put(PokemonFamilyId.FAMILY_TAUROS, PokemonId.TAUROS); - familys.put(PokemonId.MAGIKARP, PokemonFamilyId.FAMILY_MAGIKARP); - familys.put(PokemonId.GYARADOS, PokemonFamilyId.FAMILY_MAGIKARP); - highestForFamily.put(PokemonFamilyId.FAMILY_MAGIKARP, PokemonId.GYARADOS); - familys.put(PokemonId.LAPRAS, PokemonFamilyId.FAMILY_LAPRAS); - highestForFamily.put(PokemonFamilyId.FAMILY_LAPRAS, PokemonId.LAPRAS); - familys.put(PokemonId.DITTO, PokemonFamilyId.FAMILY_DITTO); - highestForFamily.put(PokemonFamilyId.FAMILY_DITTO, PokemonId.DITTO); - familys.put(PokemonId.EEVEE, PokemonFamilyId.FAMILY_EEVEE); - familys.put(PokemonId.JOLTEON, PokemonFamilyId.FAMILY_EEVEE); - familys.put(PokemonId.VAPOREON, PokemonFamilyId.FAMILY_EEVEE); - familys.put(PokemonId.FLAREON, PokemonFamilyId.FAMILY_EEVEE); - highestForFamily.put(PokemonFamilyId.FAMILY_EEVEE, PokemonId.EEVEE); - familys.put(PokemonId.PORYGON, PokemonFamilyId.FAMILY_PORYGON); - highestForFamily.put(PokemonFamilyId.FAMILY_PORYGON, PokemonId.PORYGON); - familys.put(PokemonId.OMANYTE, PokemonFamilyId.FAMILY_OMANYTE); - familys.put(PokemonId.OMASTAR, PokemonFamilyId.FAMILY_OMANYTE); - highestForFamily.put(PokemonFamilyId.FAMILY_OMANYTE, PokemonId.OMASTAR); - familys.put(PokemonId.KABUTO, PokemonFamilyId.FAMILY_KABUTO); - familys.put(PokemonId.KABUTOPS, PokemonFamilyId.FAMILY_KABUTO); - highestForFamily.put(PokemonFamilyId.FAMILY_KABUTO, PokemonId.KABUTOPS); - familys.put(PokemonId.AERODACTYL, PokemonFamilyId.FAMILY_AERODACTYL); - highestForFamily.put(PokemonFamilyId.FAMILY_AERODACTYL, PokemonId.AERODACTYL); - familys.put(PokemonId.SNORLAX, PokemonFamilyId.FAMILY_SNORLAX); - highestForFamily.put(PokemonFamilyId.FAMILY_SNORLAX, PokemonId.SNORLAX); - familys.put(PokemonId.ARTICUNO, PokemonFamilyId.FAMILY_ARTICUNO); - highestForFamily.put(PokemonFamilyId.FAMILY_ARTICUNO, PokemonId.ARTICUNO); - familys.put(PokemonId.ZAPDOS, PokemonFamilyId.FAMILY_ZAPDOS); - highestForFamily.put(PokemonFamilyId.FAMILY_ZAPDOS, PokemonId.ZAPDOS); - familys.put(PokemonId.MOLTRES, PokemonFamilyId.FAMILY_MOLTRES); - highestForFamily.put(PokemonFamilyId.FAMILY_MOLTRES, PokemonId.MOLTRES); - familys.put(PokemonId.DRATINI, PokemonFamilyId.FAMILY_DRATINI); - familys.put(PokemonId.DRAGONAIR, PokemonFamilyId.FAMILY_DRATINI); - familys.put(PokemonId.DRAGONITE, PokemonFamilyId.FAMILY_DRATINI); - highestForFamily.put(PokemonFamilyId.FAMILY_DRATINI, PokemonId.DRAGONITE); - familys.put(PokemonId.MEWTWO, PokemonFamilyId.FAMILY_MEWTWO); - highestForFamily.put(PokemonFamilyId.FAMILY_MEWTWO, PokemonId.MEWTWO); - familys.put(PokemonId.MEW, PokemonFamilyId.FAMILY_MEW); - highestForFamily.put(PokemonFamilyId.FAMILY_MEW, PokemonId.MEW); - } - - /** - * Return the FamilyId for the given PokemonId. - * - * @param id the id of the pokemon - * @return PokemonFamilyId - */ - public static PokemonFamilyId getFamily(PokemonId id) { - return familys.get(id); - } - - /** - * Return the highest evolution for given family ID. - * !!! CARE TO EVEE THAT DOESNT HAVE BETTER EVOLUTION !!! - * - * @param family the id of the pokemon family - * @return PokemonId - */ - public static PokemonId getHightestForFamily(PokemonFamilyId family) { - return highestForFamily.get(family); - } - - -} \ No newline at end of file diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java new file mode 100644 index 00000000..b0b4c9cf --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonMeta.java @@ -0,0 +1,123 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import POGOProtos.Enums.PokemonFamilyIdOuterClass; +import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; +import POGOProtos.Enums.PokemonIdOuterClass; +import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +public class PokemonMeta { + @Getter + @Setter + private String templateId; + @Getter + @Setter + private PokemonFamilyId family; + @Getter + @Setter + private PokemonClass pokemonClass; + @Getter + @Setter + private PokemonType type2; + @Getter + @Setter + private double pokedexHeightM; + @Getter + @Setter + private double heightStdDev; + @Getter + @Setter + private int baseStamina; + @Getter + @Setter + private double cylRadiusM; + @Getter + @Setter + private double baseFleeRate; + @Getter + @Setter + private int baseAttack; + @Getter + @Setter + private double diskRadiusM; + @Getter + @Setter + private double collisionRadiusM; + @Getter + @Setter + private double pokedexWeightKg; + @Getter + @Setter + private MovementType movementType; + @Getter + @Setter + private PokemonType type1; + @Getter + @Setter + private double collisionHeadRadiusM; + @Getter + @Setter + private double movementTimerS; + @Getter + @Setter + private double jumpTimeS; + @Getter + @Setter + private double modelScale; + @Getter + @Setter + private String uniqueId; + @Getter + @Setter + private int baseDefense; + @Getter + @Setter + private int attackTimerS; + @Getter + @Setter + private double weightStdDev; + @Getter + @Setter + private double cylHeightM; + @Getter + @Setter + private int candyToEvolve; + @Getter + @Setter + private double collisionHeightM; + @Getter + @Setter + private double shoulderModeScale; + @Getter + @Setter + private double baseCaptureRate; + @Getter + @Setter + private PokemonId parentId; + @Getter + @Setter + private double cylGroundM; + @Getter + @Setter + private int number; + + + +} diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java new file mode 100644 index 00000000..78cfd50e --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonMetaRegistry.java @@ -0,0 +1,5576 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId; +import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; + +import java.util.EnumMap; + +public class PokemonMetaRegistry { + + private static EnumMap highestForFamily = new EnumMap<>(PokemonFamilyId.class); + private static EnumMap meta = new EnumMap<>(PokemonId.class); + + static { + highestForFamily.put(PokemonFamilyId.FAMILY_BULBASAUR, PokemonId.VENUSAUR); + highestForFamily.put(PokemonFamilyId.FAMILY_CHARMANDER, PokemonId.CHARIZARD); + highestForFamily.put(PokemonFamilyId.FAMILY_SQUIRTLE, PokemonId.BLASTOISE); + highestForFamily.put(PokemonFamilyId.FAMILY_CATERPIE, PokemonId.BUTTERFREE); + highestForFamily.put(PokemonFamilyId.FAMILY_WEEDLE, PokemonId.BEEDRILL); + highestForFamily.put(PokemonFamilyId.FAMILY_PIDGEY, PokemonId.PIDGEOT); + highestForFamily.put(PokemonFamilyId.FAMILY_RATTATA, PokemonId.RATICATE); + highestForFamily.put(PokemonFamilyId.FAMILY_SPEAROW, PokemonId.FEAROW); + highestForFamily.put(PokemonFamilyId.FAMILY_EKANS, PokemonId.ARBOK); + highestForFamily.put(PokemonFamilyId.FAMILY_PIKACHU, PokemonId.RAICHU); + highestForFamily.put(PokemonFamilyId.FAMILY_SANDSHREW, PokemonId.SANDSLASH); + highestForFamily.put(PokemonFamilyId.FAMILY_NIDORAN_FEMALE, PokemonId.NIDOQUEEN); + highestForFamily.put(PokemonFamilyId.FAMILY_NIDORAN_MALE, PokemonId.NIDOKING); + highestForFamily.put(PokemonFamilyId.FAMILY_CLEFAIRY, PokemonId.CLEFABLE); + highestForFamily.put(PokemonFamilyId.FAMILY_VULPIX, PokemonId.NINETALES); + highestForFamily.put(PokemonFamilyId.FAMILY_JIGGLYPUFF, PokemonId.WIGGLYTUFF); + highestForFamily.put(PokemonFamilyId.FAMILY_ZUBAT, PokemonId.GOLBAT); + highestForFamily.put(PokemonFamilyId.FAMILY_ODDISH, PokemonId.VILEPLUME); + highestForFamily.put(PokemonFamilyId.FAMILY_PARAS, PokemonId.PARASECT); + highestForFamily.put(PokemonFamilyId.FAMILY_VENONAT, PokemonId.VENOMOTH); + highestForFamily.put(PokemonFamilyId.FAMILY_DIGLETT, PokemonId.DUGTRIO); + highestForFamily.put(PokemonFamilyId.FAMILY_MEOWTH, PokemonId.PERSIAN); + highestForFamily.put(PokemonFamilyId.FAMILY_PSYDUCK, PokemonId.GOLDUCK); + highestForFamily.put(PokemonFamilyId.FAMILY_MANKEY, PokemonId.PRIMEAPE); + highestForFamily.put(PokemonFamilyId.FAMILY_GROWLITHE, PokemonId.ARCANINE); + highestForFamily.put(PokemonFamilyId.FAMILY_POLIWAG, PokemonId.POLIWRATH); + highestForFamily.put(PokemonFamilyId.FAMILY_ABRA, PokemonId.ALAKAZAM); + highestForFamily.put(PokemonFamilyId.FAMILY_MACHOP, PokemonId.MACHAMP); + highestForFamily.put(PokemonFamilyId.FAMILY_BELLSPROUT, PokemonId.VICTREEBEL); + highestForFamily.put(PokemonFamilyId.FAMILY_TENTACOOL, PokemonId.TENTACRUEL); + highestForFamily.put(PokemonFamilyId.FAMILY_GEODUDE, PokemonId.GOLEM); + highestForFamily.put(PokemonFamilyId.FAMILY_PONYTA, PokemonId.RAPIDASH); + highestForFamily.put(PokemonFamilyId.FAMILY_SLOWPOKE, PokemonId.SLOWBRO); + highestForFamily.put(PokemonFamilyId.FAMILY_MAGNEMITE, PokemonId.MAGNETON); + highestForFamily.put(PokemonFamilyId.FAMILY_FARFETCHD, PokemonId.FARFETCHD); + highestForFamily.put(PokemonFamilyId.FAMILY_DODUO, PokemonId.DODRIO); + highestForFamily.put(PokemonFamilyId.FAMILY_SEEL, PokemonId.DEWGONG); + highestForFamily.put(PokemonFamilyId.FAMILY_GRIMER, PokemonId.MUK); + highestForFamily.put(PokemonFamilyId.FAMILY_SHELLDER, PokemonId.CLOYSTER); + highestForFamily.put(PokemonFamilyId.FAMILY_GASTLY, PokemonId.GENGAR); + highestForFamily.put(PokemonFamilyId.FAMILY_ONIX, PokemonId.ONIX); + highestForFamily.put(PokemonFamilyId.FAMILY_DROWZEE, PokemonId.DROWZEE); + highestForFamily.put(PokemonFamilyId.FAMILY_KRABBY, PokemonId.KINGLER); + highestForFamily.put(PokemonFamilyId.FAMILY_VOLTORB, PokemonId.ELECTRODE); + highestForFamily.put(PokemonFamilyId.FAMILY_EXEGGCUTE, PokemonId.EXEGGUTOR); + highestForFamily.put(PokemonFamilyId.FAMILY_CUBONE, PokemonId.MAROWAK); + highestForFamily.put(PokemonFamilyId.FAMILY_HITMONLEE, PokemonId.HITMONLEE); + highestForFamily.put(PokemonFamilyId.FAMILY_HITMONCHAN, PokemonId.HITMONCHAN); + highestForFamily.put(PokemonFamilyId.FAMILY_LICKITUNG, PokemonId.LICKITUNG); + highestForFamily.put(PokemonFamilyId.FAMILY_KOFFING, PokemonId.WEEZING); + highestForFamily.put(PokemonFamilyId.FAMILY_RHYHORN, PokemonId.RHYDON); + highestForFamily.put(PokemonFamilyId.FAMILY_CHANSEY, PokemonId.CHANSEY); + highestForFamily.put(PokemonFamilyId.FAMILY_TANGELA, PokemonId.TANGELA); + highestForFamily.put(PokemonFamilyId.FAMILY_KANGASKHAN, PokemonId.KANGASKHAN); + highestForFamily.put(PokemonFamilyId.FAMILY_HORSEA, PokemonId.SEADRA); + highestForFamily.put(PokemonFamilyId.FAMILY_GOLDEEN, PokemonId.SEAKING); + highestForFamily.put(PokemonFamilyId.FAMILY_STARYU, PokemonId.STARMIE); + highestForFamily.put(PokemonFamilyId.FAMILY_MR_MIME, PokemonId.MR_MIME); + highestForFamily.put(PokemonFamilyId.FAMILY_SCYTHER, PokemonId.SCYTHER); + highestForFamily.put(PokemonFamilyId.FAMILY_JYNX, PokemonId.JYNX); + highestForFamily.put(PokemonFamilyId.FAMILY_ELECTABUZZ, PokemonId.ELECTABUZZ); + highestForFamily.put(PokemonFamilyId.FAMILY_MAGMAR, PokemonId.MAGMAR); + highestForFamily.put(PokemonFamilyId.FAMILY_PINSIR, PokemonId.PINSIR); + highestForFamily.put(PokemonFamilyId.FAMILY_TAUROS, PokemonId.TAUROS); + highestForFamily.put(PokemonFamilyId.FAMILY_MAGIKARP, PokemonId.GYARADOS); + highestForFamily.put(PokemonFamilyId.FAMILY_LAPRAS, PokemonId.LAPRAS); + highestForFamily.put(PokemonFamilyId.FAMILY_DITTO, PokemonId.DITTO); + highestForFamily.put(PokemonFamilyId.FAMILY_EEVEE, PokemonId.EEVEE); + highestForFamily.put(PokemonFamilyId.FAMILY_PORYGON, PokemonId.PORYGON); + highestForFamily.put(PokemonFamilyId.FAMILY_OMANYTE, PokemonId.OMASTAR); + highestForFamily.put(PokemonFamilyId.FAMILY_KABUTO, PokemonId.KABUTOPS); + highestForFamily.put(PokemonFamilyId.FAMILY_AERODACTYL, PokemonId.AERODACTYL); + highestForFamily.put(PokemonFamilyId.FAMILY_SNORLAX, PokemonId.SNORLAX); + highestForFamily.put(PokemonFamilyId.FAMILY_ARTICUNO, PokemonId.ARTICUNO); + highestForFamily.put(PokemonFamilyId.FAMILY_ZAPDOS, PokemonId.ZAPDOS); + highestForFamily.put(PokemonFamilyId.FAMILY_MOLTRES, PokemonId.MOLTRES); + highestForFamily.put(PokemonFamilyId.FAMILY_DRATINI, PokemonId.DRAGONITE); + highestForFamily.put(PokemonFamilyId.FAMILY_MEWTWO, PokemonId.MEWTWO); + highestForFamily.put(PokemonFamilyId.FAMILY_MEW, PokemonId.MEW); + highestForFamily.put(PokemonFamilyId.FAMILY_HYPNO, PokemonId.HYPNO); + + PokemonMeta metap; + metap = new PokemonMeta(); + metap.setTemplateId(" V0001_POKEMON_BULBASAUR"); + metap.setFamily(PokemonFamilyId.FAMILY_BULBASAUR); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.7); + metap.setHeightStdDev(0.0875); + metap.setBaseStamina(90); + metap.setCylRadiusM(0.3815); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(126); + metap.setDiskRadiusM(0.5723); + metap.setCollisionRadiusM(0.3815); + metap.setPokedexWeightKg(6.9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.2725); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.15); + metap.setModelScale(1.09); + metap.setUniqueId("V0001_POKEMON_BULBASAUR"); + metap.setBaseDefense(126); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.8625); + metap.setCylHeightM(0.763); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.654); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(1); + meta.put(PokemonId.BULBASAUR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0002_POKEMON_IVYSAUR"); + metap.setFamily(PokemonFamilyId.FAMILY_BULBASAUR); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.51); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(156); + metap.setDiskRadiusM(0.765); + metap.setCollisionRadiusM(0.31875); + metap.setPokedexWeightKg(13); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.255); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1.5); + metap.setModelScale(0.85); + metap.setUniqueId("V0002_POKEMON_IVYSAUR"); + metap.setBaseDefense(158); + metap.setAttackTimerS(8); + metap.setWeightStdDev(1.625); + metap.setCylHeightM(1.0625); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.6375); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.BULBASAUR); + metap.setCylGroundM(0); + metap.setNumber(2); + meta.put(PokemonId.IVYSAUR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0003_POKEMON_VENUSAUR"); + metap.setFamily(PokemonFamilyId.FAMILY_BULBASAUR); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(2); + metap.setHeightStdDev(0.25); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.759); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(198); + metap.setDiskRadiusM(1.1385); + metap.setCollisionRadiusM(0.759); + metap.setPokedexWeightKg(100); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.3795); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.69); + metap.setUniqueId("V0003_POKEMON_VENUSAUR"); + metap.setBaseDefense(200); + metap.setAttackTimerS(4); + metap.setWeightStdDev(12.5); + metap.setCylHeightM(1.2075); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.035); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.04); + metap.setParentId(PokemonId.IVYSAUR); + metap.setCylGroundM(0); + metap.setNumber(3); + meta.put(PokemonId.VENUSAUR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0004_POKEMON_CHARMANDER"); + metap.setFamily(PokemonFamilyId.FAMILY_CHARMANDER); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(78); + metap.setCylRadiusM(0.3125); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(128); + metap.setDiskRadiusM(0.4688); + metap.setCollisionRadiusM(0.15625); + metap.setPokedexWeightKg(8.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.15625); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.25); + metap.setUniqueId("V0004_POKEMON_CHARMANDER"); + metap.setBaseDefense(108); + metap.setAttackTimerS(10); + metap.setWeightStdDev(1.0625); + metap.setCylHeightM(0.75); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.46875); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(4); + meta.put(PokemonId.CHARMANDER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0005_POKEMON_CHARMELEON"); + metap.setFamily(PokemonFamilyId.FAMILY_CHARMANDER); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(116); + metap.setCylRadiusM(0.4635); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(160); + metap.setDiskRadiusM(0.6953); + metap.setCollisionRadiusM(0.2575); + metap.setPokedexWeightKg(19); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.23175); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(1.03); + metap.setUniqueId("V0005_POKEMON_CHARMELEON"); + metap.setBaseDefense(140); + metap.setAttackTimerS(8); + metap.setWeightStdDev(2.375); + metap.setCylHeightM(1.133); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.7725); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.CHARMANDER); + metap.setCylGroundM(0); + metap.setNumber(5); + meta.put(PokemonId.CHARMELEON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0006_POKEMON_CHARIZARD"); + metap.setFamily(PokemonFamilyId.FAMILY_CHARMANDER); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.7); + metap.setHeightStdDev(0.2125); + metap.setBaseStamina(156); + metap.setCylRadiusM(0.81); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(212); + metap.setDiskRadiusM(1.215); + metap.setCollisionRadiusM(0.405); + metap.setPokedexWeightKg(90.5); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.2025); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1); + metap.setModelScale(0.81); + metap.setUniqueId("V0006_POKEMON_CHARIZARD"); + metap.setBaseDefense(182); + metap.setAttackTimerS(4); + metap.setWeightStdDev(11.3125); + metap.setCylHeightM(1.377); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.0125); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.04); + metap.setParentId(PokemonId.CHARMELEON); + metap.setCylGroundM(0.405); + metap.setNumber(6); + meta.put(PokemonId.CHARIZARD, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0007_POKEMON_SQUIRTLE"); + metap.setFamily(PokemonFamilyId.FAMILY_SQUIRTLE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(88); + metap.setCylRadiusM(0.3825); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(112); + metap.setDiskRadiusM(0.5738); + metap.setCollisionRadiusM(0.2295); + metap.setPokedexWeightKg(9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.19125); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.53); + metap.setUniqueId("V0007_POKEMON_SQUIRTLE"); + metap.setBaseDefense(142); + metap.setAttackTimerS(29); + metap.setWeightStdDev(1.125); + metap.setCylHeightM(0.64259988); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.3825); + metap.setShoulderModeScale(0.1); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(7); + meta.put(PokemonId.SQUIRTLE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0008_POKEMON_WARTORTLE"); + metap.setFamily(PokemonFamilyId.FAMILY_SQUIRTLE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(118); + metap.setCylRadiusM(0.375); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(144); + metap.setDiskRadiusM(0.5625); + metap.setCollisionRadiusM(0.25); + metap.setPokedexWeightKg(22.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.1875); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1.25); + metap.setModelScale(1); + metap.setUniqueId("V0008_POKEMON_WARTORTLE"); + metap.setBaseDefense(176); + metap.setAttackTimerS(8); + metap.setWeightStdDev(2.8125); + metap.setCylHeightM(1); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.625); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.SQUIRTLE); + metap.setCylGroundM(0); + metap.setNumber(8); + meta.put(PokemonId.WARTORTLE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0009_POKEMON_BLASTOISE"); + metap.setFamily(PokemonFamilyId.FAMILY_SQUIRTLE); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(158); + metap.setCylRadiusM(0.564); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(186); + metap.setDiskRadiusM(0.846); + metap.setCollisionRadiusM(0.564); + metap.setPokedexWeightKg(85.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.282); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.94); + metap.setUniqueId("V0009_POKEMON_BLASTOISE"); + metap.setBaseDefense(222); + metap.setAttackTimerS(5); + metap.setWeightStdDev(10.6875); + metap.setCylHeightM(1.2925); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.175); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.04); + metap.setParentId(PokemonId.WARTORTLE); + metap.setCylGroundM(0); + metap.setNumber(9); + meta.put(PokemonId.BLASTOISE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0010_POKEMON_CATERPIE"); + metap.setFamily(PokemonFamilyId.FAMILY_CATERPIE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(90); + metap.setCylRadiusM(0.306); + metap.setBaseFleeRate(0.2); + metap.setBaseAttack(62); + metap.setDiskRadiusM(0.459); + metap.setCollisionRadiusM(0.102); + metap.setPokedexWeightKg(2.9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.153); + metap.setMovementTimerS(10); + metap.setJumpTimeS(0); + metap.setModelScale(2.04); + metap.setUniqueId("V0010_POKEMON_CATERPIE"); + metap.setBaseDefense(66); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.3625); + metap.setCylHeightM(0.408); + metap.setCandyToEvolve(12); + metap.setCollisionHeightM(0.306); + metap.setShoulderModeScale(0); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(10); + meta.put(PokemonId.CATERPIE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0011_POKEMON_METAPOD"); + metap.setFamily(PokemonFamilyId.FAMILY_CATERPIE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.7); + metap.setHeightStdDev(0.0875); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.351); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(56); + metap.setDiskRadiusM(0.5265); + metap.setCollisionRadiusM(0.117); + metap.setPokedexWeightKg(9.9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.1755); + metap.setMovementTimerS(3600); + metap.setJumpTimeS(1); + metap.setModelScale(1.17); + metap.setUniqueId("V0011_POKEMON_METAPOD"); + metap.setBaseDefense(86); + metap.setAttackTimerS(3600); + metap.setWeightStdDev(1.2375); + metap.setCylHeightM(0.6435); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.6435); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.CATERPIE); + metap.setCylGroundM(0); + metap.setNumber(11); + meta.put(PokemonId.METAPOD, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0012_POKEMON_BUTTERFREE"); + metap.setFamily(PokemonFamilyId.FAMILY_CATERPIE); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.666); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(144); + metap.setDiskRadiusM(0.999); + metap.setCollisionRadiusM(0.1665); + metap.setPokedexWeightKg(32); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.1776); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(1.11); + metap.setUniqueId("V0012_POKEMON_BUTTERFREE"); + metap.setBaseDefense(144); + metap.setAttackTimerS(17); + metap.setWeightStdDev(4); + metap.setCylHeightM(1.11); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.555); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.METAPOD); + metap.setCylGroundM(0.555); + metap.setNumber(12); + meta.put(PokemonId.BUTTERFREE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0013_POKEMON_WEEDLE"); + metap.setFamily(PokemonFamilyId.FAMILY_WEEDLE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.209); + metap.setBaseFleeRate(0.2); + metap.setBaseAttack(68); + metap.setDiskRadiusM(0.3135); + metap.setCollisionRadiusM(0.1045); + metap.setPokedexWeightKg(3.2); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.15675); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.25); + metap.setModelScale(2.09); + metap.setUniqueId("V0013_POKEMON_WEEDLE"); + metap.setBaseDefense(64); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.4); + metap.setCylHeightM(0.418); + metap.setCandyToEvolve(12); + metap.setCollisionHeightM(0.209); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(13); + meta.put(PokemonId.WEEDLE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0014_POKEMON_KAKUNA"); + metap.setFamily(PokemonFamilyId.FAMILY_WEEDLE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(90); + metap.setCylRadiusM(0.25); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(62); + metap.setDiskRadiusM(0.375); + metap.setCollisionRadiusM(0.25); + metap.setPokedexWeightKg(10); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.125); + metap.setMovementTimerS(3600); + metap.setJumpTimeS(0); + metap.setModelScale(1.25); + metap.setUniqueId("V0014_POKEMON_KAKUNA"); + metap.setBaseDefense(82); + metap.setAttackTimerS(3600); + metap.setWeightStdDev(1.25); + metap.setCylHeightM(0.75); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.75); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.WEEDLE); + metap.setCylGroundM(0); + metap.setNumber(14); + meta.put(PokemonId.KAKUNA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0015_POKEMON_BEEDRILL"); + metap.setFamily(PokemonFamilyId.FAMILY_WEEDLE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.462); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(144); + metap.setDiskRadiusM(0.693); + metap.setCollisionRadiusM(0.308); + metap.setPokedexWeightKg(29.5); + metap.setMovementType(MovementType.ELECTRIC); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.231); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.77); + metap.setUniqueId("V0015_POKEMON_BEEDRILL"); + metap.setBaseDefense(130); + metap.setAttackTimerS(17); + metap.setWeightStdDev(3.6875); + metap.setCylHeightM(0.77); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.5775); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.KAKUNA); + metap.setCylGroundM(0.385); + metap.setNumber(15); + meta.put(PokemonId.BEEDRILL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0016_POKEMON_PIDGEY"); + metap.setFamily(PokemonFamilyId.FAMILY_PIDGEY); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.252); + metap.setBaseFleeRate(0.2); + metap.setBaseAttack(94); + metap.setDiskRadiusM(0.378); + metap.setCollisionRadiusM(0.1344); + metap.setPokedexWeightKg(1.8); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.126); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.4); + metap.setModelScale(1.68); + metap.setUniqueId("V0016_POKEMON_PIDGEY"); + metap.setBaseDefense(90); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.225); + metap.setCylHeightM(0.504); + metap.setCandyToEvolve(12); + metap.setCollisionHeightM(0.252); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(16); + meta.put(PokemonId.PIDGEY, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0017_POKEMON_PIDGEOTTO"); + metap.setFamily(PokemonFamilyId.FAMILY_PIDGEY); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(126); + metap.setCylRadiusM(0.474); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(126); + metap.setDiskRadiusM(0.711); + metap.setCollisionRadiusM(0.316); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.237); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(0.79); + metap.setUniqueId("V0017_POKEMON_PIDGEOTTO"); + metap.setBaseDefense(122); + metap.setAttackTimerS(29); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(0.9875); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.69125); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.PIDGEY); + metap.setCylGroundM(0.395); + metap.setNumber(17); + meta.put(PokemonId.PIDGEOTTO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0018_POKEMON_PIDGEOT"); + metap.setFamily(PokemonFamilyId.FAMILY_PIDGEY); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(166); + metap.setCylRadiusM(0.864); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(170); + metap.setDiskRadiusM(1.296); + metap.setCollisionRadiusM(0.36); + metap.setPokedexWeightKg(39.5); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.216); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.72); + metap.setUniqueId("V0018_POKEMON_PIDGEOT"); + metap.setBaseDefense(166); + metap.setAttackTimerS(17); + metap.setWeightStdDev(4.9375); + metap.setCylHeightM(1.44); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.008); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.PIDGEOTTO); + metap.setCylGroundM(0.36); + metap.setNumber(18); + meta.put(PokemonId.PIDGEOT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0019_POKEMON_RATTATA"); + metap.setFamily(PokemonFamilyId.FAMILY_RATTATA); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.252); + metap.setBaseFleeRate(0.2); + metap.setBaseAttack(92); + metap.setDiskRadiusM(0.378); + metap.setCollisionRadiusM(0.189); + metap.setPokedexWeightKg(3.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.126); + metap.setMovementTimerS(10); + metap.setJumpTimeS(0.9); + metap.setModelScale(1.26); + metap.setUniqueId("V0019_POKEMON_RATTATA"); + metap.setBaseDefense(86); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.4375); + metap.setCylHeightM(0.378); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.252); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(19); + meta.put(PokemonId.RATTATA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0020_POKEMON_RATICATE"); + metap.setFamily(PokemonFamilyId.FAMILY_RATTATA); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.7); + metap.setHeightStdDev(0.0875); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.5265); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(146); + metap.setDiskRadiusM(0.7898); + metap.setCollisionRadiusM(0.2925); + metap.setPokedexWeightKg(18.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.26325); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(1.17); + metap.setUniqueId("V0020_POKEMON_RATICATE"); + metap.setBaseDefense(150); + metap.setAttackTimerS(8); + metap.setWeightStdDev(2.3125); + metap.setCylHeightM(0.936); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.585); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.RATTATA); + metap.setCylGroundM(0); + metap.setNumber(20); + meta.put(PokemonId.RATICATE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0021_POKEMON_SPEAROW"); + metap.setFamily(PokemonFamilyId.FAMILY_SPEAROW); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.296); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(102); + metap.setDiskRadiusM(0.444); + metap.setCollisionRadiusM(0.148); + metap.setPokedexWeightKg(2); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.148); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.48); + metap.setUniqueId("V0021_POKEMON_SPEAROW"); + metap.setBaseDefense(78); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.25); + metap.setCylHeightM(0.518); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.2664); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(21); + meta.put(PokemonId.SPEAROW, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0022_POKEMON_FEAROW"); + metap.setFamily(PokemonFamilyId.FAMILY_SPEAROW); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.504); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(168); + metap.setDiskRadiusM(1.26); + metap.setCollisionRadiusM(0.252); + metap.setPokedexWeightKg(38); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.126); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.84); + metap.setUniqueId("V0022_POKEMON_FEAROW"); + metap.setBaseDefense(146); + metap.setAttackTimerS(23); + metap.setWeightStdDev(4.75); + metap.setCylHeightM(1.05); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.63); + metap.setShoulderModeScale(0.375); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.SPEAROW); + metap.setCylGroundM(0.42); + metap.setNumber(22); + meta.put(PokemonId.FEAROW, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0023_POKEMON_EKANS"); + metap.setFamily(PokemonFamilyId.FAMILY_EKANS); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(2); + metap.setHeightStdDev(0.25); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.4325); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(112); + metap.setDiskRadiusM(0.6488); + metap.setCollisionRadiusM(0.2595); + metap.setPokedexWeightKg(6.9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.1384); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.73); + metap.setUniqueId("V0023_POKEMON_EKANS"); + metap.setBaseDefense(112); + metap.setAttackTimerS(10); + metap.setWeightStdDev(0.8625); + metap.setCylHeightM(0.6055); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.346); + metap.setShoulderModeScale(0.375); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(23); + meta.put(PokemonId.EKANS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0024_POKEMON_ARBOK"); + metap.setFamily(PokemonFamilyId.FAMILY_EKANS); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(3.5); + metap.setHeightStdDev(0.4375); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.615); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(166); + metap.setDiskRadiusM(0.9225); + metap.setCollisionRadiusM(0.41); + metap.setPokedexWeightKg(65); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.164); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(0.82); + metap.setUniqueId("V0024_POKEMON_ARBOK"); + metap.setBaseDefense(166); + metap.setAttackTimerS(8); + metap.setWeightStdDev(8.125); + metap.setCylHeightM(1.353); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.353); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.EKANS); + metap.setCylGroundM(0); + metap.setNumber(24); + meta.put(PokemonId.ARBOK, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0025_POKEMON_PIKACHU"); + metap.setFamily(PokemonFamilyId.FAMILY_PIKACHU); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.37); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(124); + metap.setDiskRadiusM(0.555); + metap.setCollisionRadiusM(0.185); + metap.setPokedexWeightKg(6); + metap.setMovementType(MovementType.NORMAL); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.185); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.48); + metap.setUniqueId("V0025_POKEMON_PIKACHU"); + metap.setBaseDefense(108); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.75); + metap.setCylHeightM(0.74); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.518); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(25); + meta.put(PokemonId.PIKACHU, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0026_POKEMON_RAICHU"); + metap.setFamily(PokemonFamilyId.FAMILY_PIKACHU); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.486); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(200); + metap.setDiskRadiusM(0.729); + metap.setCollisionRadiusM(0.27); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.216); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.08); + metap.setUniqueId("V0026_POKEMON_RAICHU"); + metap.setBaseDefense(154); + metap.setAttackTimerS(17); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(1.35); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.54); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.PIKACHU); + metap.setCylGroundM(0); + metap.setNumber(26); + meta.put(PokemonId.RAICHU, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0027_POKEMON_SANDSHREW"); + metap.setFamily(PokemonFamilyId.FAMILY_SANDSHREW); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.3225); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(90); + metap.setDiskRadiusM(0.4838); + metap.setCollisionRadiusM(0.258); + metap.setPokedexWeightKg(12); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.1935); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.29); + metap.setUniqueId("V0027_POKEMON_SANDSHREW"); + metap.setBaseDefense(114); + metap.setAttackTimerS(23); + metap.setWeightStdDev(1.5); + metap.setCylHeightM(0.774); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.48375); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(27); + meta.put(PokemonId.SANDSHREW, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0028_POKEMON_SANDSLASH"); + metap.setFamily(PokemonFamilyId.FAMILY_SANDSHREW); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(150); + metap.setCylRadiusM(0.4); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(150); + metap.setDiskRadiusM(0.6); + metap.setCollisionRadiusM(0.35); + metap.setPokedexWeightKg(29.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.35); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1); + metap.setModelScale(1); + metap.setUniqueId("V0028_POKEMON_SANDSLASH"); + metap.setBaseDefense(172); + metap.setAttackTimerS(4); + metap.setWeightStdDev(3.6875); + metap.setCylHeightM(1); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.9); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.SANDSHREW); + metap.setCylGroundM(0); + metap.setNumber(28); + meta.put(PokemonId.SANDSLASH, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0029_POKEMON_NIDORAN"); + metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_FEMALE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.37); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(100); + metap.setDiskRadiusM(0.555); + metap.setCollisionRadiusM(0.185); + metap.setPokedexWeightKg(7); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.185); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.48); + metap.setUniqueId("V0029_POKEMON_NIDORAN"); + metap.setBaseDefense(104); + metap.setAttackTimerS(10); + metap.setWeightStdDev(0.875); + metap.setCylHeightM(0.666); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.37); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(29); + meta.put(PokemonId.NIDORAN_FEMALE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0030_POKEMON_NIDORINA"); + metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_FEMALE); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(140); + metap.setCylRadiusM(0.4388); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(132); + metap.setDiskRadiusM(0.6581); + metap.setCollisionRadiusM(0.2925); + metap.setPokedexWeightKg(20); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.1755); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(1.17); + metap.setUniqueId("V0030_POKEMON_NIDORINA"); + metap.setBaseDefense(136); + metap.setAttackTimerS(8); + metap.setWeightStdDev(2.5); + metap.setCylHeightM(0.87749988); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.585); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.NIDORAN_FEMALE); + metap.setCylGroundM(0); + metap.setNumber(30); + meta.put(PokemonId.NIDORINA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0031_POKEMON_NIDOQUEEN"); + metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_FEMALE); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.GROUND); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.4095); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(184); + metap.setDiskRadiusM(0.6143); + metap.setCollisionRadiusM(0.455); + metap.setPokedexWeightKg(60); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.2275); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1); + metap.setModelScale(0.91); + metap.setUniqueId("V0031_POKEMON_NIDOQUEEN"); + metap.setBaseDefense(190); + metap.setAttackTimerS(5); + metap.setWeightStdDev(7.5); + metap.setCylHeightM(1.183); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.79625); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.NIDORINA); + metap.setCylGroundM(0); + metap.setNumber(31); + meta.put(PokemonId.NIDOQUEEN, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0032_POKEMON_NIDORAN"); + metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_MALE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(92); + metap.setCylRadiusM(0.4725); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(110); + metap.setDiskRadiusM(0.7088); + metap.setCollisionRadiusM(0.252); + metap.setPokedexWeightKg(9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.1575); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1); + metap.setModelScale(1.26); + metap.setUniqueId("V0032_POKEMON_NIDORAN"); + metap.setBaseDefense(94); + metap.setAttackTimerS(10); + metap.setWeightStdDev(1.125); + metap.setCylHeightM(0.756); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.315); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(32); + meta.put(PokemonId.NIDORAN_MALE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0033_POKEMON_NIDORINO"); + metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_MALE); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.9); + metap.setHeightStdDev(0.1125); + metap.setBaseStamina(122); + metap.setCylRadiusM(0.495); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(142); + metap.setDiskRadiusM(0.7425); + metap.setCollisionRadiusM(0.297); + metap.setPokedexWeightKg(19.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.2475); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(0.99); + metap.setUniqueId("V0033_POKEMON_NIDORINO"); + metap.setBaseDefense(128); + metap.setAttackTimerS(8); + metap.setWeightStdDev(2.4375); + metap.setCylHeightM(0.792); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.594); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.NIDORAN_MALE); + metap.setCylGroundM(0); + metap.setNumber(33); + meta.put(PokemonId.NIDORINO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0034_POKEMON_NIDOKING"); + metap.setFamily(PokemonFamilyId.FAMILY_NIDORAN_MALE); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.GROUND); + metap.setPokedexHeightM(1.4); + metap.setHeightStdDev(0.175); + metap.setBaseStamina(162); + metap.setCylRadiusM(0.5481); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(204); + metap.setDiskRadiusM(0.8222); + metap.setCollisionRadiusM(0.5481); + metap.setPokedexWeightKg(62); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.27405); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1); + metap.setModelScale(0.87); + metap.setUniqueId("V0034_POKEMON_NIDOKING"); + metap.setBaseDefense(170); + metap.setAttackTimerS(5); + metap.setWeightStdDev(7.75); + metap.setCylHeightM(1.305); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.87); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.NIDORINO); + metap.setCylGroundM(0); + metap.setNumber(34); + meta.put(PokemonId.NIDOKING, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0035_POKEMON_CLEFAIRY"); + metap.setFamily(PokemonFamilyId.FAMILY_CLEFAIRY); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(140); + metap.setCylRadiusM(0.45); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(116); + metap.setDiskRadiusM(0.675); + metap.setCollisionRadiusM(0.3125); + metap.setPokedexWeightKg(7.5); + metap.setMovementType(MovementType.NORMAL); + metap.setType1(PokemonType.FAIRY); + metap.setCollisionHeadRadiusM(0.225); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.25); + metap.setUniqueId("V0035_POKEMON_CLEFAIRY"); + metap.setBaseDefense(124); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.9375); + metap.setCylHeightM(0.75); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.75); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(35); + meta.put(PokemonId.CLEFAIRY, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0036_POKEMON_CLEFABLE"); + metap.setFamily(PokemonFamilyId.FAMILY_CLEFAIRY); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(190); + metap.setCylRadiusM(0.712); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(178); + metap.setDiskRadiusM(1.1681); + metap.setCollisionRadiusM(0.445); + metap.setPokedexWeightKg(40); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FAIRY); + metap.setCollisionHeadRadiusM(0.445); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.89); + metap.setUniqueId("V0036_POKEMON_CLEFABLE"); + metap.setBaseDefense(178); + metap.setAttackTimerS(11); + metap.setWeightStdDev(5); + metap.setCylHeightM(1.44625); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.1125); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.CLEFAIRY); + metap.setCylGroundM(0); + metap.setNumber(36); + meta.put(PokemonId.CLEFABLE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0037_POKEMON_VULPIX"); + metap.setFamily(PokemonFamilyId.FAMILY_VULPIX); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(76); + metap.setCylRadiusM(0.567); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(106); + metap.setDiskRadiusM(0.8505); + metap.setCollisionRadiusM(0.315); + metap.setPokedexWeightKg(9.9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.252); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.26); + metap.setUniqueId("V0037_POKEMON_VULPIX"); + metap.setBaseDefense(118); + metap.setAttackTimerS(29); + metap.setWeightStdDev(1.2375); + metap.setCylHeightM(0.756); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.63); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(37); + meta.put(PokemonId.VULPIX, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0038_POKEMON_NINETALES"); + metap.setFamily(PokemonFamilyId.FAMILY_VULPIX); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(146); + metap.setCylRadiusM(0.864); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(176); + metap.setDiskRadiusM(1.296); + metap.setCollisionRadiusM(0.36); + metap.setPokedexWeightKg(19.9); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.24); + metap.setMovementTimerS(5); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.96); + metap.setUniqueId("V0038_POKEMON_NINETALES"); + metap.setBaseDefense(194); + metap.setAttackTimerS(14); + metap.setWeightStdDev(2.4875); + metap.setCylHeightM(1.2); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.96); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.VULPIX); + metap.setCylGroundM(0); + metap.setNumber(38); + meta.put(PokemonId.NINETALES, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0039_POKEMON_JIGGLYPUFF"); + metap.setFamily(PokemonFamilyId.FAMILY_JIGGLYPUFF); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.FAIRY); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(230); + metap.setCylRadiusM(0.512); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(98); + metap.setDiskRadiusM(0.768); + metap.setCollisionRadiusM(0.32); + metap.setPokedexWeightKg(5.5); + metap.setMovementType(MovementType.NORMAL); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.256); + metap.setMovementTimerS(10); + metap.setJumpTimeS(3); + metap.setModelScale(1.28); + metap.setUniqueId("V0039_POKEMON_JIGGLYPUFF"); + metap.setBaseDefense(54); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.6875); + metap.setCylHeightM(0.96); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.64); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(39); + meta.put(PokemonId.JIGGLYPUFF, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0040_POKEMON_WIGGLYTUFF"); + metap.setFamily(PokemonFamilyId.FAMILY_JIGGLYPUFF); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.FAIRY); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(280); + metap.setCylRadiusM(0.445); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(168); + metap.setDiskRadiusM(1.0013); + metap.setCollisionRadiusM(0.356); + metap.setPokedexWeightKg(12); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.2225); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.89); + metap.setUniqueId("V0040_POKEMON_WIGGLYTUFF"); + metap.setBaseDefense(108); + metap.setAttackTimerS(11); + metap.setWeightStdDev(1.5); + metap.setCylHeightM(1.22375); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.89); + metap.setShoulderModeScale(0.4); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.JIGGLYPUFF); + metap.setCylGroundM(0); + metap.setNumber(40); + meta.put(PokemonId.WIGGLYTUFF, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0041_POKEMON_ZUBAT"); + metap.setFamily(PokemonFamilyId.FAMILY_ZUBAT); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.642); + metap.setBaseFleeRate(0.2); + metap.setBaseAttack(88); + metap.setDiskRadiusM(0.963); + metap.setCollisionRadiusM(0.0535); + metap.setPokedexWeightKg(7.5); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.1605); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.07); + metap.setUniqueId("V0041_POKEMON_ZUBAT"); + metap.setBaseDefense(90); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.9375); + metap.setCylHeightM(0.6955); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.0535); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.535); + metap.setNumber(41); + meta.put(PokemonId.ZUBAT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0042_POKEMON_GOLBAT"); + metap.setFamily(PokemonFamilyId.FAMILY_ZUBAT); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(150); + metap.setCylRadiusM(0.75); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(164); + metap.setDiskRadiusM(1.5975); + metap.setCollisionRadiusM(0.0355); + metap.setPokedexWeightKg(55); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.355); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.71); + metap.setUniqueId("V0042_POKEMON_GOLBAT"); + metap.setBaseDefense(164); + metap.setAttackTimerS(17); + metap.setWeightStdDev(6.875); + metap.setCylHeightM(1.2425); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.0355); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.ZUBAT); + metap.setCylGroundM(1.065); + metap.setNumber(42); + meta.put(PokemonId.GOLBAT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0043_POKEMON_ODDISH"); + metap.setFamily(PokemonFamilyId.FAMILY_ODDISH); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(90); + metap.setCylRadiusM(0.405); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(134); + metap.setDiskRadiusM(0.6075); + metap.setCollisionRadiusM(0.2025); + metap.setPokedexWeightKg(5.4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.2025); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.35); + metap.setUniqueId("V0043_POKEMON_ODDISH"); + metap.setBaseDefense(130); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.675); + metap.setCylHeightM(0.81000012); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.50625); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.48); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(43); + meta.put(PokemonId.ODDISH, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0044_POKEMON_GLOOM"); + metap.setFamily(PokemonFamilyId.FAMILY_ODDISH); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.495); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(162); + metap.setDiskRadiusM(0.7425); + metap.setCollisionRadiusM(0.4125); + metap.setPokedexWeightKg(8.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.2475); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.1); + metap.setUniqueId("V0044_POKEMON_GLOOM"); + metap.setBaseDefense(158); + metap.setAttackTimerS(23); + metap.setWeightStdDev(1.075); + metap.setCylHeightM(0.88000011); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.88000011); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.ODDISH); + metap.setCylGroundM(0); + metap.setNumber(44); + meta.put(PokemonId.GLOOM, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0045_POKEMON_VILEPLUME"); + metap.setFamily(PokemonFamilyId.FAMILY_ODDISH); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(150); + metap.setCylRadiusM(0.828); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(202); + metap.setDiskRadiusM(1.242); + metap.setCollisionRadiusM(1.012); + metap.setPokedexWeightKg(18.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.552); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1); + metap.setModelScale(0.92); + metap.setUniqueId("V0045_POKEMON_VILEPLUME"); + metap.setBaseDefense(190); + metap.setAttackTimerS(4); + metap.setWeightStdDev(2.325); + metap.setCylHeightM(1.196); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.196); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.GLOOM); + metap.setCylGroundM(0); + metap.setNumber(45); + meta.put(PokemonId.VILEPLUME, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0046_POKEMON_PARAS"); + metap.setFamily(PokemonFamilyId.FAMILY_PARAS); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.GRASS); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.384); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(122); + metap.setDiskRadiusM(0.576); + metap.setCollisionRadiusM(0.192); + metap.setPokedexWeightKg(5.4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.192); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1.1); + metap.setModelScale(1.28); + metap.setUniqueId("V0046_POKEMON_PARAS"); + metap.setBaseDefense(120); + metap.setAttackTimerS(10); + metap.setWeightStdDev(0.675); + metap.setCylHeightM(0.448); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.32); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(46); + meta.put(PokemonId.PARAS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0047_POKEMON_PARASECT"); + metap.setFamily(PokemonFamilyId.FAMILY_PARAS); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.GRASS); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.6313); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(162); + metap.setDiskRadiusM(0.9469); + metap.setCollisionRadiusM(0.4545); + metap.setPokedexWeightKg(29.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.505); + metap.setMovementTimerS(17); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.01); + metap.setUniqueId("V0047_POKEMON_PARASECT"); + metap.setBaseDefense(170); + metap.setAttackTimerS(6); + metap.setWeightStdDev(3.6875); + metap.setCylHeightM(1.01); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.01); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.PARAS); + metap.setCylGroundM(0); + metap.setNumber(47); + meta.put(PokemonId.PARASECT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0048_POKEMON_VENONAT"); + metap.setFamily(PokemonFamilyId.FAMILY_VENONAT); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.5325); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(108); + metap.setDiskRadiusM(0.7988); + metap.setCollisionRadiusM(0.355); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.26625); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.71); + metap.setUniqueId("V0048_POKEMON_VENONAT"); + metap.setBaseDefense(118); + metap.setAttackTimerS(29); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(1.1715); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.71); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(48); + meta.put(PokemonId.VENONAT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0049_POKEMON_VENOMOTH"); + metap.setFamily(PokemonFamilyId.FAMILY_VENONAT); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(140); + metap.setCylRadiusM(0.576); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(172); + metap.setDiskRadiusM(0.864); + metap.setCollisionRadiusM(0.36); + metap.setPokedexWeightKg(12.5); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.288); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.72); + metap.setUniqueId("V0049_POKEMON_VENOMOTH"); + metap.setBaseDefense(154); + metap.setAttackTimerS(17); + metap.setWeightStdDev(1.5625); + metap.setCylHeightM(1.08); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.72); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.VENONAT); + metap.setCylGroundM(0.36); + metap.setNumber(49); + meta.put(PokemonId.VENOMOTH, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0050_POKEMON_DIGLETT"); + metap.setFamily(PokemonFamilyId.FAMILY_DIGLETT); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.2); + metap.setHeightStdDev(0.025); + metap.setBaseStamina(20); + metap.setCylRadiusM(0.3); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(108); + metap.setDiskRadiusM(0.45); + metap.setCollisionRadiusM(0.16); + metap.setPokedexWeightKg(0.8); + metap.setMovementType(MovementType.NORMAL); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.18); + metap.setMovementTimerS(29); + metap.setJumpTimeS(0); + metap.setModelScale(2); + metap.setUniqueId("V0050_POKEMON_DIGLETT"); + metap.setBaseDefense(86); + metap.setAttackTimerS(10); + metap.setWeightStdDev(0.1); + metap.setCylHeightM(0.4); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.4); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(50); + meta.put(PokemonId.DIGLETT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0051_POKEMON_DUGTRIO"); + metap.setFamily(PokemonFamilyId.FAMILY_DIGLETT); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.7); + metap.setHeightStdDev(0.0875); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.672); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(148); + metap.setDiskRadiusM(1.008); + metap.setCollisionRadiusM(0.448); + metap.setPokedexWeightKg(33.3); + metap.setMovementType(MovementType.NORMAL); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.336); + metap.setMovementTimerS(29); + metap.setJumpTimeS(0); + metap.setModelScale(1.12); + metap.setUniqueId("V0051_POKEMON_DUGTRIO"); + metap.setBaseDefense(140); + metap.setAttackTimerS(10); + metap.setWeightStdDev(4.1625); + metap.setCylHeightM(0.84); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.84); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.DIGLETT); + metap.setCylGroundM(0); + metap.setNumber(51); + meta.put(PokemonId.DUGTRIO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0052_POKEMON_MEOWTH"); + metap.setFamily(PokemonFamilyId.FAMILY_MEOWTH); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.4); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(104); + metap.setDiskRadiusM(0.6); + metap.setCollisionRadiusM(0.128); + metap.setPokedexWeightKg(4.2); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.2); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1); + metap.setModelScale(1.6); + metap.setUniqueId("V0052_POKEMON_MEOWTH"); + metap.setBaseDefense(94); + metap.setAttackTimerS(10); + metap.setWeightStdDev(0.525); + metap.setCylHeightM(0.64); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.4); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(52); + meta.put(PokemonId.MEOWTH, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0053_POKEMON_PERSIAN"); + metap.setFamily(PokemonFamilyId.FAMILY_MEOWTH); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.533); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(156); + metap.setDiskRadiusM(0.7995); + metap.setCollisionRadiusM(0.328); + metap.setPokedexWeightKg(32); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.164); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.82); + metap.setUniqueId("V0053_POKEMON_PERSIAN"); + metap.setBaseDefense(146); + metap.setAttackTimerS(23); + metap.setWeightStdDev(4); + metap.setCylHeightM(0.902); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.615); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.MEOWTH); + metap.setCylGroundM(0); + metap.setNumber(53); + meta.put(PokemonId.PERSIAN, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0054_POKEMON_PSYDUCK"); + metap.setFamily(PokemonFamilyId.FAMILY_PSYDUCK); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.3638); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(132); + metap.setDiskRadiusM(0.5456); + metap.setCollisionRadiusM(0.291); + metap.setPokedexWeightKg(19.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.3395); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(0.97); + metap.setUniqueId("V0054_POKEMON_PSYDUCK"); + metap.setBaseDefense(112); + metap.setAttackTimerS(29); + metap.setWeightStdDev(2.45); + metap.setCylHeightM(0.97); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.60625); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(54); + meta.put(PokemonId.PSYDUCK, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0055_POKEMON_GOLDUCK"); + metap.setFamily(PokemonFamilyId.FAMILY_PSYDUCK); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.7); + metap.setHeightStdDev(0.2125); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.465); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(194); + metap.setDiskRadiusM(0.9765); + metap.setCollisionRadiusM(0.2325); + metap.setPokedexWeightKg(76.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.2325); + metap.setMovementTimerS(5); + metap.setJumpTimeS(1); + metap.setModelScale(0.93); + metap.setUniqueId("V0055_POKEMON_GOLDUCK"); + metap.setBaseDefense(176); + metap.setAttackTimerS(14); + metap.setWeightStdDev(9.575); + metap.setCylHeightM(1.3485); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.81375); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.PSYDUCK); + metap.setCylGroundM(0); + metap.setNumber(55); + meta.put(PokemonId.GOLDUCK, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0056_POKEMON_MANKEY"); + metap.setFamily(PokemonFamilyId.FAMILY_MANKEY); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.4838); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(122); + metap.setDiskRadiusM(0.7256); + metap.setCollisionRadiusM(0.1935); + metap.setPokedexWeightKg(28); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.129); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1); + metap.setModelScale(1.29); + metap.setUniqueId("V0056_POKEMON_MANKEY"); + metap.setBaseDefense(96); + metap.setAttackTimerS(10); + metap.setWeightStdDev(3.5); + metap.setCylHeightM(0.80625); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.645); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(56); + meta.put(PokemonId.MANKEY, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0057_POKEMON_PRIMEAPE"); + metap.setFamily(PokemonFamilyId.FAMILY_MANKEY); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.46); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(178); + metap.setDiskRadiusM(0.69); + metap.setCollisionRadiusM(0.46); + metap.setPokedexWeightKg(32); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.23); + metap.setMovementTimerS(17); + metap.setJumpTimeS(1); + metap.setModelScale(0.92); + metap.setUniqueId("V0057_POKEMON_PRIMEAPE"); + metap.setBaseDefense(150); + metap.setAttackTimerS(6); + metap.setWeightStdDev(4); + metap.setCylHeightM(1.15); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.104); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.MANKEY); + metap.setCylGroundM(0); + metap.setNumber(57); + meta.put(PokemonId.PRIMEAPE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0058_POKEMON_GROWLITHE"); + metap.setFamily(PokemonFamilyId.FAMILY_GROWLITHE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.7); + metap.setHeightStdDev(0.0875); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.585); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(156); + metap.setDiskRadiusM(0.8775); + metap.setCollisionRadiusM(0.234); + metap.setPokedexWeightKg(19); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.1755); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.17); + metap.setUniqueId("V0058_POKEMON_GROWLITHE"); + metap.setBaseDefense(110); + metap.setAttackTimerS(29); + metap.setWeightStdDev(2.375); + metap.setCylHeightM(1.02375); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.585); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(58); + meta.put(PokemonId.GROWLITHE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0059_POKEMON_ARCANINE"); + metap.setFamily(PokemonFamilyId.FAMILY_GROWLITHE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.9); + metap.setHeightStdDev(0.2375); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.666); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(230); + metap.setDiskRadiusM(0.999); + metap.setCollisionRadiusM(0.37); + metap.setPokedexWeightKg(155); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.333); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.74); + metap.setUniqueId("V0059_POKEMON_ARCANINE"); + metap.setBaseDefense(180); + metap.setAttackTimerS(11); + metap.setWeightStdDev(19.375); + metap.setCylHeightM(1.48); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.74); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.GROWLITHE); + metap.setCylGroundM(0); + metap.setNumber(59); + meta.put(PokemonId.ARCANINE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0060_POKEMON_POLIWAG"); + metap.setFamily(PokemonFamilyId.FAMILY_POLIWAG); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.5); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(108); + metap.setDiskRadiusM(0.75); + metap.setCollisionRadiusM(0.3125); + metap.setPokedexWeightKg(12.4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.3125); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.25); + metap.setUniqueId("V0060_POKEMON_POLIWAG"); + metap.setBaseDefense(98); + metap.setAttackTimerS(29); + metap.setWeightStdDev(1.55); + metap.setCylHeightM(0.875); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.75); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(60); + meta.put(PokemonId.POLIWAG, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0061_POKEMON_POLIWHIRL"); + metap.setFamily(PokemonFamilyId.FAMILY_POLIWAG); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.735); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(132); + metap.setDiskRadiusM(1.1025); + metap.setCollisionRadiusM(0.49); + metap.setPokedexWeightKg(20); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.3675); + metap.setMovementTimerS(8); + metap.setJumpTimeS(0.8); + metap.setModelScale(0.98); + metap.setUniqueId("V0061_POKEMON_POLIWHIRL"); + metap.setBaseDefense(132); + metap.setAttackTimerS(23); + metap.setWeightStdDev(2.5); + metap.setCylHeightM(1.078); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.882); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.POLIWAG); + metap.setCylGroundM(0); + metap.setNumber(61); + meta.put(PokemonId.POLIWHIRL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0062_POKEMON_POLIWRATH"); + metap.setFamily(PokemonFamilyId.FAMILY_POLIWAG); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.FIGHTING); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.817); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(180); + metap.setDiskRadiusM(1.2255); + metap.setCollisionRadiusM(0.645); + metap.setPokedexWeightKg(54); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.344); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1.05); + metap.setModelScale(0.86); + metap.setUniqueId("V0062_POKEMON_POLIWRATH"); + metap.setBaseDefense(202); + metap.setAttackTimerS(4); + metap.setWeightStdDev(6.75); + metap.setCylHeightM(1.204); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.118); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.POLIWHIRL); + metap.setCylGroundM(0); + metap.setNumber(62); + meta.put(PokemonId.POLIWRATH, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0063_POKEMON_ABRA"); + metap.setFamily(PokemonFamilyId.FAMILY_ABRA); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.9); + metap.setHeightStdDev(0.1125); + metap.setBaseStamina(50); + metap.setCylRadiusM(0.448); + metap.setBaseFleeRate(0.99); + metap.setBaseAttack(110); + metap.setDiskRadiusM(0.672); + metap.setCollisionRadiusM(0.28); + metap.setPokedexWeightKg(19.5); + metap.setMovementType(MovementType.PSYCHIC); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.28); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1); + metap.setModelScale(1.12); + metap.setUniqueId("V0063_POKEMON_ABRA"); + metap.setBaseDefense(76); + metap.setAttackTimerS(10); + metap.setWeightStdDev(2.4375); + metap.setCylHeightM(0.784); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.56); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.168); + metap.setNumber(63); + meta.put(PokemonId.ABRA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0064_POKEMON_KADABRA"); + metap.setFamily(PokemonFamilyId.FAMILY_ABRA); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.6675); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(150); + metap.setDiskRadiusM(1.0013); + metap.setCollisionRadiusM(0.445); + metap.setPokedexWeightKg(56.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.33375); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.89); + metap.setUniqueId("V0064_POKEMON_KADABRA"); + metap.setBaseDefense(112); + metap.setAttackTimerS(17); + metap.setWeightStdDev(7.0625); + metap.setCylHeightM(1.157); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.89); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.ABRA); + metap.setCylGroundM(0); + metap.setNumber(64); + meta.put(PokemonId.KADABRA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0065_POKEMON_ALAKAZAM"); + metap.setFamily(PokemonFamilyId.FAMILY_ABRA); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.51); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(186); + metap.setDiskRadiusM(0.765); + metap.setCollisionRadiusM(0.425); + metap.setPokedexWeightKg(48); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.255); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1); + metap.setModelScale(0.85); + metap.setUniqueId("V0065_POKEMON_ALAKAZAM"); + metap.setBaseDefense(152); + metap.setAttackTimerS(11); + metap.setWeightStdDev(6); + metap.setCylHeightM(1.275); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.93500012); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.KADABRA); + metap.setCylGroundM(0); + metap.setNumber(65); + meta.put(PokemonId.ALAKAZAM, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0066_POKEMON_MACHOP"); + metap.setFamily(PokemonFamilyId.FAMILY_MACHOP); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(140); + metap.setCylRadiusM(0.4125); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(118); + metap.setDiskRadiusM(0.6188); + metap.setCollisionRadiusM(0.22); + metap.setPokedexWeightKg(19.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.20625); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(1.1); + metap.setUniqueId("V0066_POKEMON_MACHOP"); + metap.setBaseDefense(96); + metap.setAttackTimerS(8); + metap.setWeightStdDev(2.4375); + metap.setCylHeightM(0.88000011); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.55); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(66); + meta.put(PokemonId.MACHOP, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0067_POKEMON_MACHOKE"); + metap.setFamily(PokemonFamilyId.FAMILY_MACHOP); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.546); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(154); + metap.setDiskRadiusM(0.819); + metap.setCollisionRadiusM(0.54600012); + metap.setPokedexWeightKg(70.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.1365); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1); + metap.setModelScale(0.91); + metap.setUniqueId("V0067_POKEMON_MACHOKE"); + metap.setBaseDefense(144); + metap.setAttackTimerS(5); + metap.setWeightStdDev(8.8125); + metap.setCylHeightM(1.274); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(1.092); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.MACHOP); + metap.setCylGroundM(0); + metap.setNumber(67); + meta.put(PokemonId.MACHOKE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0068_POKEMON_MACHAMP"); + metap.setFamily(PokemonFamilyId.FAMILY_MACHOP); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.5785); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(198); + metap.setDiskRadiusM(0.8678); + metap.setCollisionRadiusM(0.5785); + metap.setPokedexWeightKg(130); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.1335); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.89); + metap.setUniqueId("V0068_POKEMON_MACHAMP"); + metap.setBaseDefense(180); + metap.setAttackTimerS(3); + metap.setWeightStdDev(16.25); + metap.setCylHeightM(1.424); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.246); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.MACHOKE); + metap.setCylGroundM(0); + metap.setNumber(68); + meta.put(PokemonId.MACHAMP, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0069_POKEMON_BELLSPROUT"); + metap.setFamily(PokemonFamilyId.FAMILY_BELLSPROUT); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.7); + metap.setHeightStdDev(0.0875); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.4515); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(158); + metap.setDiskRadiusM(0.6773); + metap.setCollisionRadiusM(0.1935); + metap.setPokedexWeightKg(4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.22575); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.2); + metap.setModelScale(1.29); + metap.setUniqueId("V0069_POKEMON_BELLSPROUT"); + metap.setBaseDefense(78); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.5); + metap.setCylHeightM(0.90299988); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.4515); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(69); + meta.put(PokemonId.BELLSPROUT, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0070_POKEMON_WEEPINBELL"); + metap.setFamily(PokemonFamilyId.FAMILY_BELLSPROUT); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.65); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(190); + metap.setDiskRadiusM(0.975); + metap.setCollisionRadiusM(0.25); + metap.setPokedexWeightKg(6.4); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.25); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1); + metap.setUniqueId("V0070_POKEMON_WEEPINBELL"); + metap.setBaseDefense(110); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.8); + metap.setCylHeightM(1); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.95); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.BELLSPROUT); + metap.setCylGroundM(0.375); + metap.setNumber(70); + meta.put(PokemonId.WEEPINBELL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0071_POKEMON_VICTREEBEL"); + metap.setFamily(PokemonFamilyId.FAMILY_BELLSPROUT); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.7); + metap.setHeightStdDev(0.2125); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.546); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(222); + metap.setDiskRadiusM(0.819); + metap.setCollisionRadiusM(0.336); + metap.setPokedexWeightKg(15.5); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.273); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1); + metap.setModelScale(0.84); + metap.setUniqueId("V0071_POKEMON_VICTREEBEL"); + metap.setBaseDefense(152); + metap.setAttackTimerS(5); + metap.setWeightStdDev(1.9375); + metap.setCylHeightM(1.428); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.428); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.WEEPINBELL); + metap.setCylGroundM(0.42); + metap.setNumber(71); + meta.put(PokemonId.VICTREEBEL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0072_POKEMON_TENTACOOL"); + metap.setFamily(PokemonFamilyId.FAMILY_TENTACOOL); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(0.9); + metap.setHeightStdDev(0.1125); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.315); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(106); + metap.setDiskRadiusM(0.4725); + metap.setCollisionRadiusM(0.21); + metap.setPokedexWeightKg(45.5); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.1575); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(1.05); + metap.setUniqueId("V0072_POKEMON_TENTACOOL"); + metap.setBaseDefense(136); + metap.setAttackTimerS(8); + metap.setWeightStdDev(5.6875); + metap.setCylHeightM(0.91874993); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.91874993); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.2625); + metap.setNumber(72); + meta.put(PokemonId.TENTACOOL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0073_POKEMON_TENTACRUEL"); + metap.setFamily(PokemonFamilyId.FAMILY_TENTACOOL); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.492); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(170); + metap.setDiskRadiusM(0.738); + metap.setCollisionRadiusM(0.492); + metap.setPokedexWeightKg(55); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.246); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1); + metap.setModelScale(0.82); + metap.setUniqueId("V0073_POKEMON_TENTACRUEL"); + metap.setBaseDefense(196); + metap.setAttackTimerS(4); + metap.setWeightStdDev(6.875); + metap.setCylHeightM(1.312); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.23); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.TENTACOOL); + metap.setCylGroundM(0.205); + metap.setNumber(73); + meta.put(PokemonId.TENTACRUEL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0074_POKEMON_GEODUDE"); + metap.setFamily(PokemonFamilyId.FAMILY_GEODUDE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.GROUND); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.3915); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(106); + metap.setDiskRadiusM(0.5873); + metap.setCollisionRadiusM(0.3915); + metap.setPokedexWeightKg(20); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.19575); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.87); + metap.setUniqueId("V0074_POKEMON_GEODUDE"); + metap.setBaseDefense(118); + metap.setAttackTimerS(23); + metap.setWeightStdDev(2.5); + metap.setCylHeightM(0.348); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.1305); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.261); + metap.setNumber(74); + meta.put(PokemonId.GEODUDE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0075_POKEMON_GRAVELER"); + metap.setFamily(PokemonFamilyId.FAMILY_GEODUDE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.GROUND); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.697); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(142); + metap.setDiskRadiusM(1.0455); + metap.setCollisionRadiusM(0.492); + metap.setPokedexWeightKg(105); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.369); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1.2); + metap.setModelScale(0.82); + metap.setUniqueId("V0075_POKEMON_GRAVELER"); + metap.setBaseDefense(156); + metap.setAttackTimerS(5); + metap.setWeightStdDev(13.125); + metap.setCylHeightM(0.82); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(0.697); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.2); + metap.setParentId(PokemonId.GEODUDE); + metap.setCylGroundM(0); + metap.setNumber(75); + meta.put(PokemonId.GRAVELER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0076_POKEMON_GOLEM"); + metap.setFamily(PokemonFamilyId.FAMILY_GEODUDE); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.GROUND); + metap.setPokedexHeightM(1.4); + metap.setHeightStdDev(0.175); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.63); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(176); + metap.setDiskRadiusM(0.945); + metap.setCollisionRadiusM(0.63); + metap.setPokedexWeightKg(300); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.315); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.2); + metap.setModelScale(0.84); + metap.setUniqueId("V0076_POKEMON_GOLEM"); + metap.setBaseDefense(198); + metap.setAttackTimerS(3); + metap.setWeightStdDev(37.5); + metap.setCylHeightM(1.092); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.092); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.1); + metap.setParentId(PokemonId.GRAVELER); + metap.setCylGroundM(0); + metap.setNumber(76); + meta.put(PokemonId.GOLEM, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0077_POKEMON_PONYTA"); + metap.setFamily(PokemonFamilyId.FAMILY_PONYTA); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.3788); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(168); + metap.setDiskRadiusM(0.5681); + metap.setCollisionRadiusM(0.2525); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.202); + metap.setMovementTimerS(8); + metap.setJumpTimeS(0.95); + metap.setModelScale(1.01); + metap.setUniqueId("V0077_POKEMON_PONYTA"); + metap.setBaseDefense(138); + metap.setAttackTimerS(23); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(1.2625); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.63125); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(77); + meta.put(PokemonId.PONYTA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0078_POKEMON_RAPIDASH"); + metap.setFamily(PokemonFamilyId.FAMILY_PONYTA); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.7); + metap.setHeightStdDev(0.2125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.405); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(200); + metap.setDiskRadiusM(0.6075); + metap.setCollisionRadiusM(0.324); + metap.setPokedexWeightKg(95); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.243); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.81); + metap.setUniqueId("V0078_POKEMON_RAPIDASH"); + metap.setBaseDefense(170); + metap.setAttackTimerS(17); + metap.setWeightStdDev(11.875); + metap.setCylHeightM(1.701); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.891); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.PONYTA); + metap.setCylGroundM(0); + metap.setNumber(78); + meta.put(PokemonId.RAPIDASH, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0079_POKEMON_SLOWPOKE"); + metap.setFamily(PokemonFamilyId.FAMILY_SLOWPOKE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.PSYCHIC); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.5925); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(110); + metap.setDiskRadiusM(1.185); + metap.setCollisionRadiusM(0.316); + metap.setPokedexWeightKg(36); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.29625); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.79); + metap.setUniqueId("V0079_POKEMON_SLOWPOKE"); + metap.setBaseDefense(110); + metap.setAttackTimerS(23); + metap.setWeightStdDev(4.5); + metap.setCylHeightM(0.94800007); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.5135); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(79); + meta.put(PokemonId.SLOWPOKE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0080_POKEMON_SLOWBRO"); + metap.setFamily(PokemonFamilyId.FAMILY_SLOWPOKE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.PSYCHIC); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(190); + metap.setCylRadiusM(0.4675); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(184); + metap.setDiskRadiusM(0.7013); + metap.setCollisionRadiusM(0.425); + metap.setPokedexWeightKg(78.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.255); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.85); + metap.setUniqueId("V0080_POKEMON_SLOWBRO"); + metap.setBaseDefense(198); + metap.setAttackTimerS(8); + metap.setWeightStdDev(9.8125); + metap.setCylHeightM(1.275); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.85); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.SLOWPOKE); + metap.setCylGroundM(0); + metap.setNumber(80); + meta.put(PokemonId.SLOWBRO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0081_POKEMON_MAGNEMITE"); + metap.setFamily(PokemonFamilyId.FAMILY_MAGNEMITE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.STEEL); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(50); + metap.setCylRadiusM(0.456); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(128); + metap.setDiskRadiusM(0.684); + metap.setCollisionRadiusM(0.456); + metap.setPokedexWeightKg(6); + metap.setMovementType(MovementType.ELECTRIC); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.228); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.52); + metap.setUniqueId("V0081_POKEMON_MAGNEMITE"); + metap.setBaseDefense(138); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.75); + metap.setCylHeightM(0.456); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.456); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.912); + metap.setNumber(81); + meta.put(PokemonId.MAGNEMITE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0082_POKEMON_MAGNETON"); + metap.setFamily(PokemonFamilyId.FAMILY_MAGNEMITE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.STEEL); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.44); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(186); + metap.setDiskRadiusM(0.66); + metap.setCollisionRadiusM(0.44); + metap.setPokedexWeightKg(60); + metap.setMovementType(MovementType.ELECTRIC); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.22); + metap.setMovementTimerS(5); + metap.setJumpTimeS(1); + metap.setModelScale(1.1); + metap.setUniqueId("V0082_POKEMON_MAGNETON"); + metap.setBaseDefense(180); + metap.setAttackTimerS(14); + metap.setWeightStdDev(7.5); + metap.setCylHeightM(1.1); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.825); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.MAGNEMITE); + metap.setCylGroundM(0.44); + metap.setNumber(82); + meta.put(PokemonId.MAGNETON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0083_POKEMON_FARFETCHD"); + metap.setFamily(PokemonFamilyId.FAMILY_FARFETCHD); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(104); + metap.setCylRadiusM(0.452); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(138); + metap.setDiskRadiusM(0.678); + metap.setCollisionRadiusM(0.2825); + metap.setPokedexWeightKg(15); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.2825); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.13); + metap.setUniqueId("V0083_POKEMON_FARFETCHD"); + metap.setBaseDefense(132); + metap.setAttackTimerS(10); + metap.setWeightStdDev(1.875); + metap.setCylHeightM(0.8475); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.42375); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(83); + meta.put(PokemonId.FARFETCHD, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0084_POKEMON_DODUO"); + metap.setFamily(PokemonFamilyId.FAMILY_DODUO); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.4); + metap.setHeightStdDev(0.175); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.396); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(126); + metap.setDiskRadiusM(0.594); + metap.setCollisionRadiusM(0.352); + metap.setPokedexWeightKg(39.2); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.198); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(0.88); + metap.setUniqueId("V0084_POKEMON_DODUO"); + metap.setBaseDefense(96); + metap.setAttackTimerS(29); + metap.setWeightStdDev(4.9); + metap.setCylHeightM(1.232); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(1.232); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(84); + meta.put(PokemonId.DODUO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0085_POKEMON_DODRIO"); + metap.setFamily(PokemonFamilyId.FAMILY_DODUO); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.8); + metap.setHeightStdDev(0.225); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.5148); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(182); + metap.setDiskRadiusM(0.7722); + metap.setCollisionRadiusM(0.39); + metap.setPokedexWeightKg(85.2); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.2574); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.78); + metap.setUniqueId("V0085_POKEMON_DODRIO"); + metap.setBaseDefense(150); + metap.setAttackTimerS(17); + metap.setWeightStdDev(10.65); + metap.setCylHeightM(1.287); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.287); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.DODUO); + metap.setCylGroundM(0); + metap.setNumber(85); + meta.put(PokemonId.DODRIO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0086_POKEMON_SEEL"); + metap.setFamily(PokemonFamilyId.FAMILY_SEEL); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.275); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(104); + metap.setDiskRadiusM(0.4125); + metap.setCollisionRadiusM(0.275); + metap.setPokedexWeightKg(90); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.22); + metap.setMovementTimerS(10); + metap.setJumpTimeS(0.9); + metap.setModelScale(1.1); + metap.setUniqueId("V0086_POKEMON_SEEL"); + metap.setBaseDefense(138); + metap.setAttackTimerS(29); + metap.setWeightStdDev(11.25); + metap.setCylHeightM(0.55); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.4125); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(86); + meta.put(PokemonId.SEEL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0087_POKEMON_DEWGONG"); + metap.setFamily(PokemonFamilyId.FAMILY_SEEL); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.ICE); + metap.setPokedexHeightM(1.7); + metap.setHeightStdDev(0.2125); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.525); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(156); + metap.setDiskRadiusM(0.7875); + metap.setCollisionRadiusM(0.315); + metap.setPokedexWeightKg(120); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.13125); + metap.setMovementTimerS(5); + metap.setJumpTimeS(1); + metap.setModelScale(1.05); + metap.setUniqueId("V0087_POKEMON_DEWGONG"); + metap.setBaseDefense(192); + metap.setAttackTimerS(14); + metap.setWeightStdDev(15); + metap.setCylHeightM(0.84); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.63); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.SEEL); + metap.setCylGroundM(0.39375); + metap.setNumber(87); + meta.put(PokemonId.DEWGONG, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0088_POKEMON_GRIMER"); + metap.setFamily(PokemonFamilyId.FAMILY_GRIMER); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.9); + metap.setHeightStdDev(0.1125); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.588); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(124); + metap.setDiskRadiusM(0.882); + metap.setCollisionRadiusM(0.49); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.294); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(0.98); + metap.setUniqueId("V0088_POKEMON_GRIMER"); + metap.setBaseDefense(110); + metap.setAttackTimerS(8); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(0.98); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.83300012); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(88); + meta.put(PokemonId.GRIMER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0089_POKEMON_MUK"); + metap.setFamily(PokemonFamilyId.FAMILY_GRIMER); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(210); + metap.setCylRadiusM(0.86); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(180); + metap.setDiskRadiusM(1.14); + metap.setCollisionRadiusM(0.76); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.38); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.76); + metap.setUniqueId("V0089_POKEMON_MUK"); + metap.setBaseDefense(188); + metap.setAttackTimerS(3); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(0.912); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.57); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.GRIMER); + metap.setCylGroundM(0); + metap.setNumber(89); + meta.put(PokemonId.MUK, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0090_POKEMON_SHELLDER"); + metap.setFamily(PokemonFamilyId.FAMILY_SHELLDER); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.3864); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(120); + metap.setDiskRadiusM(0.5796); + metap.setCollisionRadiusM(0.336); + metap.setPokedexWeightKg(4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.294); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1.2); + metap.setModelScale(1.68); + metap.setUniqueId("V0090_POKEMON_SHELLDER"); + metap.setBaseDefense(112); + metap.setAttackTimerS(8); + metap.setWeightStdDev(0.5); + metap.setCylHeightM(0.504); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.504); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(90); + meta.put(PokemonId.SHELLDER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0091_POKEMON_CLOYSTER"); + metap.setFamily(PokemonFamilyId.FAMILY_SHELLDER); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.ICE); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.63); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(196); + metap.setDiskRadiusM(0.945); + metap.setCollisionRadiusM(0.42); + metap.setPokedexWeightKg(132.5); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.54599988); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.84); + metap.setUniqueId("V0091_POKEMON_CLOYSTER"); + metap.setBaseDefense(196); + metap.setAttackTimerS(8); + metap.setWeightStdDev(16.5625); + metap.setCylHeightM(1.05); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.05); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.SHELLDER); + metap.setCylGroundM(0.42); + metap.setNumber(91); + meta.put(PokemonId.CLOYSTER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0092_POKEMON_GASTLY"); + metap.setFamily(PokemonFamilyId.FAMILY_GASTLY); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.45); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(136); + metap.setDiskRadiusM(0.675); + metap.setCollisionRadiusM(0.25); + metap.setPokedexWeightKg(0.1); + metap.setMovementType(MovementType.PSYCHIC); + metap.setType1(PokemonType.GHOST); + metap.setCollisionHeadRadiusM(0.3); + metap.setMovementTimerS(29); + metap.setJumpTimeS(1); + metap.setModelScale(1); + metap.setUniqueId("V0092_POKEMON_GASTLY"); + metap.setBaseDefense(82); + metap.setAttackTimerS(10); + metap.setWeightStdDev(0.0125); + metap.setCylHeightM(0.8); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.6); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.6); + metap.setNumber(92); + meta.put(PokemonId.GASTLY, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0093_POKEMON_HAUNTER"); + metap.setFamily(PokemonFamilyId.FAMILY_GASTLY); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(90); + metap.setCylRadiusM(0.51); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(172); + metap.setDiskRadiusM(0.765); + metap.setCollisionRadiusM(0.442); + metap.setPokedexWeightKg(0.1); + metap.setMovementType(MovementType.PSYCHIC); + metap.setType1(PokemonType.GHOST); + metap.setCollisionHeadRadiusM(0.442); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(0.68); + metap.setUniqueId("V0093_POKEMON_HAUNTER"); + metap.setBaseDefense(118); + metap.setAttackTimerS(8); + metap.setWeightStdDev(0.0125); + metap.setCylHeightM(1.088); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(1.156); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.GASTLY); + metap.setCylGroundM(0.34); + metap.setNumber(93); + meta.put(PokemonId.HAUNTER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0094_POKEMON_GENGAR"); + metap.setFamily(PokemonFamilyId.FAMILY_GASTLY); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.POISON); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.462); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(204); + metap.setDiskRadiusM(0.693); + metap.setCollisionRadiusM(0.462); + metap.setPokedexWeightKg(40.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GHOST); + metap.setCollisionHeadRadiusM(0.504); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1.3); + metap.setModelScale(0.84); + metap.setUniqueId("V0094_POKEMON_GENGAR"); + metap.setBaseDefense(156); + metap.setAttackTimerS(5); + metap.setWeightStdDev(5.0625); + metap.setCylHeightM(1.176); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.092); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.HAUNTER); + metap.setCylGroundM(0); + metap.setNumber(94); + meta.put(PokemonId.GENGAR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0095_POKEMON_ONIX"); + metap.setFamily(PokemonFamilyId.FAMILY_ONIX); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.GROUND); + metap.setPokedexHeightM(8.8); + metap.setHeightStdDev(1.1); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.658); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(90); + metap.setDiskRadiusM(0.987); + metap.setCollisionRadiusM(0.658); + metap.setPokedexWeightKg(210); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.376); + metap.setMovementTimerS(17); + metap.setJumpTimeS(1); + metap.setModelScale(0.47); + metap.setUniqueId("V0095_POKEMON_ONIX"); + metap.setBaseDefense(186); + metap.setAttackTimerS(6); + metap.setWeightStdDev(26.25); + metap.setCylHeightM(1.41); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.175); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(95); + meta.put(PokemonId.ONIX, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0096_POKEMON_DROWZEE"); + metap.setFamily(PokemonFamilyId.FAMILY_DROWZEE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.42); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(104); + metap.setDiskRadiusM(0.63); + metap.setCollisionRadiusM(0.3675); + metap.setPokedexWeightKg(32.4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.2625); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.25); + metap.setModelScale(1.05); + metap.setUniqueId("V0096_POKEMON_DROWZEE"); + metap.setBaseDefense(140); + metap.setAttackTimerS(23); + metap.setWeightStdDev(4.05); + metap.setCylHeightM(1.05); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.63); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(96); + meta.put(PokemonId.DROWZEE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0097_POKEMON_HYPNO"); + metap.setFamily(PokemonFamilyId.FAMILY_HYPNO); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(170); + metap.setCylRadiusM(0.6225); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(162); + metap.setDiskRadiusM(0.9338); + metap.setCollisionRadiusM(0.332); + metap.setPokedexWeightKg(75.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.332); + metap.setMovementTimerS(11); + metap.setJumpTimeS(0.8); + metap.setModelScale(0.83); + metap.setUniqueId("V0097_POKEMON_HYPNO"); + metap.setBaseDefense(196); + metap.setAttackTimerS(4); + metap.setWeightStdDev(9.45); + metap.setCylHeightM(1.328); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.83); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.DROWZEE); + metap.setCylGroundM(0); + metap.setNumber(97); + meta.put(PokemonId.HYPNO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0098_POKEMON_KRABBY"); + metap.setFamily(PokemonFamilyId.FAMILY_KRABBY); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.522); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(116); + metap.setDiskRadiusM(0.783); + metap.setCollisionRadiusM(0.522); + metap.setPokedexWeightKg(6.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.261); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1); + metap.setModelScale(1.16); + metap.setUniqueId("V0098_POKEMON_KRABBY"); + metap.setBaseDefense(110); + metap.setAttackTimerS(8); + metap.setWeightStdDev(0.8125); + metap.setCylHeightM(0.87); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.87); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(98); + meta.put(PokemonId.KRABBY, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0099_POKEMON_KINGLER"); + metap.setFamily(PokemonFamilyId.FAMILY_KRABBY); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.6525); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(178); + metap.setDiskRadiusM(0.9788); + metap.setCollisionRadiusM(0.6525); + metap.setPokedexWeightKg(60); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.32625); + metap.setMovementTimerS(8); + metap.setJumpTimeS(0.8); + metap.setModelScale(0.87); + metap.setUniqueId("V0099_POKEMON_KINGLER"); + metap.setBaseDefense(168); + metap.setAttackTimerS(3); + metap.setWeightStdDev(7.5); + metap.setCylHeightM(1.0005); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.0005); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.KRABBY); + metap.setCylGroundM(0); + metap.setNumber(99); + meta.put(PokemonId.KINGLER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0100_POKEMON_VOLTORB"); + metap.setFamily(PokemonFamilyId.FAMILY_VOLTORB); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.3375); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(102); + metap.setDiskRadiusM(0.5063); + metap.setCollisionRadiusM(0.3375); + metap.setPokedexWeightKg(10.4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.16875); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.2); + metap.setModelScale(1.35); + metap.setUniqueId("V0100_POKEMON_VOLTORB"); + metap.setBaseDefense(124); + metap.setAttackTimerS(29); + metap.setWeightStdDev(1.3); + metap.setCylHeightM(0.675); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.675); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(100); + meta.put(PokemonId.VOLTORB, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0101_POKEMON_ELECTRODE"); + metap.setFamily(PokemonFamilyId.FAMILY_VOLTORB); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.552); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(150); + metap.setDiskRadiusM(0.828); + metap.setCollisionRadiusM(0.552); + metap.setPokedexWeightKg(66.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.276); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.2); + metap.setModelScale(0.92); + metap.setUniqueId("V0101_POKEMON_ELECTRODE"); + metap.setBaseDefense(174); + metap.setAttackTimerS(23); + metap.setWeightStdDev(8.325); + metap.setCylHeightM(1.104); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.104); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.VOLTORB); + metap.setCylGroundM(0); + metap.setNumber(101); + meta.put(PokemonId.ELECTRODE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0102_POKEMON_EXEGGCUTE"); + metap.setFamily(PokemonFamilyId.FAMILY_EXEGGCUTE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.PSYCHIC); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.515); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(110); + metap.setDiskRadiusM(0.7725); + metap.setCollisionRadiusM(0.515); + metap.setPokedexWeightKg(2.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.2575); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.03); + metap.setUniqueId("V0102_POKEMON_EXEGGCUTE"); + metap.setBaseDefense(132); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.3125); + metap.setCylHeightM(0.412); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.412); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(102); + meta.put(PokemonId.EXEGGCUTE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0103_POKEMON_EXEGGUTOR"); + metap.setFamily(PokemonFamilyId.FAMILY_EXEGGCUTE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.PSYCHIC); + metap.setPokedexHeightM(2); + metap.setHeightStdDev(0.25); + metap.setBaseStamina(190); + metap.setCylRadiusM(0.507); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(232); + metap.setDiskRadiusM(0.7605); + metap.setCollisionRadiusM(0.507); + metap.setPokedexWeightKg(120); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.2535); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.78); + metap.setUniqueId("V0103_POKEMON_EXEGGUTOR"); + metap.setBaseDefense(164); + metap.setAttackTimerS(3); + metap.setWeightStdDev(15); + metap.setCylHeightM(1.365); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.365); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.EXEGGCUTE); + metap.setCylGroundM(0); + metap.setNumber(103); + meta.put(PokemonId.EXEGGUTOR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0104_POKEMON_CUBONE"); + metap.setFamily(PokemonFamilyId.FAMILY_CUBONE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.296); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(102); + metap.setDiskRadiusM(0.444); + metap.setCollisionRadiusM(0.222); + metap.setPokedexWeightKg(6.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.222); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.48); + metap.setUniqueId("V0104_POKEMON_CUBONE"); + metap.setBaseDefense(150); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.8125); + metap.setCylHeightM(0.592); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.37); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(104); + meta.put(PokemonId.CUBONE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0105_POKEMON_MAROWAK"); + metap.setFamily(PokemonFamilyId.FAMILY_CUBONE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.35); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(140); + metap.setDiskRadiusM(0.525); + metap.setCollisionRadiusM(0.25); + metap.setPokedexWeightKg(45); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.25); + metap.setMovementTimerS(14); + metap.setJumpTimeS(0.85); + metap.setModelScale(1); + metap.setUniqueId("V0105_POKEMON_MAROWAK"); + metap.setBaseDefense(202); + metap.setAttackTimerS(5); + metap.setWeightStdDev(5.625); + metap.setCylHeightM(1); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.75); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.CUBONE); + metap.setCylGroundM(0); + metap.setNumber(105); + meta.put(PokemonId.MAROWAK, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0106_POKEMON_HITMONLEE"); + metap.setFamily(PokemonFamilyId.FAMILY_HITMONLEE); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.415); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(148); + metap.setDiskRadiusM(0.6225); + metap.setCollisionRadiusM(0.415); + metap.setPokedexWeightKg(49.8); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.2075); + metap.setMovementTimerS(11); + metap.setJumpTimeS(0.8); + metap.setModelScale(0.83); + metap.setUniqueId("V0106_POKEMON_HITMONLEE"); + metap.setBaseDefense(172); + metap.setAttackTimerS(4); + metap.setWeightStdDev(6.225); + metap.setCylHeightM(1.245); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.245); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(106); + meta.put(PokemonId.HITMONLEE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0107_POKEMON_HITMONCHAN"); + metap.setFamily(PokemonFamilyId.FAMILY_HITMONCHAN); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.4); + metap.setHeightStdDev(0.175); + metap.setBaseStamina(100); + metap.setCylRadiusM(0.459); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(138); + metap.setDiskRadiusM(0.6885); + metap.setCollisionRadiusM(0.3315); + metap.setPokedexWeightKg(50.2); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIGHTING); + metap.setCollisionHeadRadiusM(0.255); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1.1); + metap.setModelScale(1.02); + metap.setUniqueId("V0107_POKEMON_HITMONCHAN"); + metap.setBaseDefense(204); + metap.setAttackTimerS(5); + metap.setWeightStdDev(6.275); + metap.setCylHeightM(1.428); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.02); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(107); + meta.put(PokemonId.HITMONCHAN, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0108_POKEMON_LICKITUNG"); + metap.setFamily(PokemonFamilyId.FAMILY_LICKITUNG); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.46); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(126); + metap.setDiskRadiusM(0.69); + metap.setCollisionRadiusM(0.46); + metap.setPokedexWeightKg(65.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.253); + metap.setMovementTimerS(23); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.92); + metap.setUniqueId("V0108_POKEMON_LICKITUNG"); + metap.setBaseDefense(160); + metap.setAttackTimerS(8); + metap.setWeightStdDev(8.1875); + metap.setCylHeightM(1.104); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.92); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(108); + meta.put(PokemonId.LICKITUNG, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0109_POKEMON_KOFFING"); + metap.setFamily(PokemonFamilyId.FAMILY_KOFFING); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.48); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(136); + metap.setDiskRadiusM(0.72); + metap.setCollisionRadiusM(0.36); + metap.setPokedexWeightKg(1); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.6); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.2); + metap.setUniqueId("V0109_POKEMON_KOFFING"); + metap.setBaseDefense(142); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.125); + metap.setCylHeightM(0.72); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.66); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.6); + metap.setNumber(109); + meta.put(PokemonId.KOFFING, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0110_POKEMON_WEEZING"); + metap.setFamily(PokemonFamilyId.FAMILY_KOFFING); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.62); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(190); + metap.setDiskRadiusM(0.93); + metap.setCollisionRadiusM(0.682); + metap.setPokedexWeightKg(9.5); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.POISON); + metap.setCollisionHeadRadiusM(0.465); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1); + metap.setModelScale(1.24); + metap.setUniqueId("V0110_POKEMON_WEEZING"); + metap.setBaseDefense(198); + metap.setAttackTimerS(11); + metap.setWeightStdDev(1.1875); + metap.setCylHeightM(0.744); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.744); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.KOFFING); + metap.setCylGroundM(0.62); + metap.setNumber(110); + meta.put(PokemonId.WEEZING, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0111_POKEMON_RHYHORN"); + metap.setFamily(PokemonFamilyId.FAMILY_RHYHORN); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.ROCK); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.5); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(110); + metap.setDiskRadiusM(0.75); + metap.setCollisionRadiusM(0.5); + metap.setPokedexWeightKg(115); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.3); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1.25); + metap.setModelScale(1); + metap.setUniqueId("V0111_POKEMON_RHYHORN"); + metap.setBaseDefense(116); + metap.setAttackTimerS(5); + metap.setWeightStdDev(14.375); + metap.setCylHeightM(0.85); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.85); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(111); + meta.put(PokemonId.RHYHORN, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0112_POKEMON_RHYDON"); + metap.setFamily(PokemonFamilyId.FAMILY_RHYHORN); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.ROCK); + metap.setPokedexHeightM(1.9); + metap.setHeightStdDev(0.2375); + metap.setBaseStamina(210); + metap.setCylRadiusM(0.79); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(166); + metap.setDiskRadiusM(1.185); + metap.setCollisionRadiusM(0.5925); + metap.setPokedexWeightKg(120); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GROUND); + metap.setCollisionHeadRadiusM(0.395); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.79); + metap.setUniqueId("V0112_POKEMON_RHYDON"); + metap.setBaseDefense(160); + metap.setAttackTimerS(3); + metap.setWeightStdDev(15); + metap.setCylHeightM(1.343); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.185); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.RHYHORN); + metap.setCylGroundM(0); + metap.setNumber(112); + meta.put(PokemonId.RHYDON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0113_POKEMON_CHANSEY"); + metap.setFamily(PokemonFamilyId.FAMILY_CHANSEY); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(500); + metap.setCylRadiusM(0.48); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(40); + metap.setDiskRadiusM(0.72); + metap.setCollisionRadiusM(0.48); + metap.setPokedexWeightKg(34.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.24); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.96); + metap.setUniqueId("V0113_POKEMON_CHANSEY"); + metap.setBaseDefense(60); + metap.setAttackTimerS(8); + metap.setWeightStdDev(4.325); + metap.setCylHeightM(1.056); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.056); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(113); + meta.put(PokemonId.CHANSEY, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0114_POKEMON_TANGELA"); + metap.setFamily(PokemonFamilyId.FAMILY_TANGELA); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.73); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(164); + metap.setDiskRadiusM(1.095); + metap.setCollisionRadiusM(0.5); + metap.setPokedexWeightKg(35); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.GRASS); + metap.setCollisionHeadRadiusM(0.365); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.25); + metap.setModelScale(1); + metap.setUniqueId("V0114_POKEMON_TANGELA"); + metap.setBaseDefense(152); + metap.setAttackTimerS(11); + metap.setWeightStdDev(4.375); + metap.setCylHeightM(1); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.9); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(114); + meta.put(PokemonId.TANGELA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0115_POKEMON_KANGASKHAN"); + metap.setFamily(PokemonFamilyId.FAMILY_KANGASKHAN); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(2.2); + metap.setHeightStdDev(0.275); + metap.setBaseStamina(210); + metap.setCylRadiusM(0.576); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(142); + metap.setDiskRadiusM(0.864); + metap.setCollisionRadiusM(0.504); + metap.setPokedexWeightKg(80); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.36); + metap.setMovementTimerS(11); + metap.setJumpTimeS(0.7); + metap.setModelScale(0.72); + metap.setUniqueId("V0115_POKEMON_KANGASKHAN"); + metap.setBaseDefense(178); + metap.setAttackTimerS(4); + metap.setWeightStdDev(10); + metap.setCylHeightM(1.584); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.26); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(115); + meta.put(PokemonId.KANGASKHAN, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0116_POKEMON_HORSEA"); + metap.setFamily(PokemonFamilyId.FAMILY_HORSEA); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.25); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(122); + metap.setDiskRadiusM(0.2775); + metap.setCollisionRadiusM(0.148); + metap.setPokedexWeightKg(8); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.185); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.48); + metap.setUniqueId("V0116_POKEMON_HORSEA"); + metap.setBaseDefense(100); + metap.setAttackTimerS(29); + metap.setWeightStdDev(1); + metap.setCylHeightM(0.74); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.444); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.185); + metap.setNumber(116); + meta.put(PokemonId.HORSEA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0117_POKEMON_SEADRA"); + metap.setFamily(PokemonFamilyId.FAMILY_HORSEA); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.2); + metap.setHeightStdDev(0.15); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.46); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(176); + metap.setDiskRadiusM(0.69); + metap.setCollisionRadiusM(0.322); + metap.setPokedexWeightKg(25); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.414); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.92); + metap.setUniqueId("V0117_POKEMON_SEADRA"); + metap.setBaseDefense(150); + metap.setAttackTimerS(17); + metap.setWeightStdDev(3.125); + metap.setCylHeightM(1.15); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.46); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.HORSEA); + metap.setCylGroundM(0.46); + metap.setNumber(117); + meta.put(PokemonId.SEADRA, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0118_POKEMON_GOLDEEN"); + metap.setFamily(PokemonFamilyId.FAMILY_GOLDEEN); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.6); + metap.setHeightStdDev(0.075); + metap.setBaseStamina(90); + metap.setCylRadiusM(0.27); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(112); + metap.setDiskRadiusM(0.405); + metap.setCollisionRadiusM(0.135); + metap.setPokedexWeightKg(15); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.16875); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1); + metap.setModelScale(1.35); + metap.setUniqueId("V0118_POKEMON_GOLDEEN"); + metap.setBaseDefense(126); + metap.setAttackTimerS(29); + metap.setWeightStdDev(1.875); + metap.setCylHeightM(0.3375); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.16875); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.3375); + metap.setNumber(118); + meta.put(PokemonId.GOLDEEN, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0119_POKEMON_SEAKING"); + metap.setFamily(PokemonFamilyId.FAMILY_GOLDEEN); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.396); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(172); + metap.setDiskRadiusM(0.594); + metap.setCollisionRadiusM(0.044); + metap.setPokedexWeightKg(39); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.242); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1); + metap.setModelScale(0.88); + metap.setUniqueId("V0119_POKEMON_SEAKING"); + metap.setBaseDefense(160); + metap.setAttackTimerS(5); + metap.setWeightStdDev(4.875); + metap.setCylHeightM(0.748); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.044); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.GOLDEEN); + metap.setCylGroundM(0.33); + metap.setNumber(119); + meta.put(PokemonId.SEAKING, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0120_POKEMON_STARYU"); + metap.setFamily(PokemonFamilyId.FAMILY_STARYU); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.4125); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(130); + metap.setDiskRadiusM(0.6188); + metap.setCollisionRadiusM(0.4125); + metap.setPokedexWeightKg(34.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.20625); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.35); + metap.setModelScale(1.1); + metap.setUniqueId("V0120_POKEMON_STARYU"); + metap.setBaseDefense(128); + metap.setAttackTimerS(29); + metap.setWeightStdDev(4.3125); + metap.setCylHeightM(0.88000011); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.88000011); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.4); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(120); + meta.put(PokemonId.STARYU, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0121_POKEMON_STARMIE"); + metap.setFamily(PokemonFamilyId.FAMILY_STARYU); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.PSYCHIC); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.485); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(194); + metap.setDiskRadiusM(0.7275); + metap.setCollisionRadiusM(0.485); + metap.setPokedexWeightKg(80); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.2425); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1.6); + metap.setModelScale(0.97); + metap.setUniqueId("V0121_POKEMON_STARMIE"); + metap.setBaseDefense(192); + metap.setAttackTimerS(17); + metap.setWeightStdDev(10); + metap.setCylHeightM(1.067); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.067); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.STARYU); + metap.setCylGroundM(0); + metap.setNumber(121); + meta.put(PokemonId.STARMIE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0122_POKEMON_MR_MIME"); + metap.setFamily(PokemonFamilyId.FAMILY_MR_MIME); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.FAIRY); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(80); + metap.setCylRadiusM(0.445); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(154); + metap.setDiskRadiusM(0.6675); + metap.setCollisionRadiusM(0.267); + metap.setPokedexWeightKg(54.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.267); + metap.setMovementTimerS(5); + metap.setJumpTimeS(1); + metap.setModelScale(0.89); + metap.setUniqueId("V0122_POKEMON_MR_MIME"); + metap.setBaseDefense(196); + metap.setAttackTimerS(14); + metap.setWeightStdDev(6.8125); + metap.setCylHeightM(1.157); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.6675); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(122); + meta.put(PokemonId.MR_MIME, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0123_POKEMON_SCYTHER"); + metap.setFamily(PokemonFamilyId.FAMILY_SCYTHER); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(140); + metap.setCylRadiusM(0.76); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(176); + metap.setDiskRadiusM(1.14); + metap.setCollisionRadiusM(0.4); + metap.setPokedexWeightKg(56); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.2); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1); + metap.setModelScale(0.8); + metap.setUniqueId("V0123_POKEMON_SCYTHER"); + metap.setBaseDefense(180); + metap.setAttackTimerS(5); + metap.setWeightStdDev(7); + metap.setCylHeightM(1.2); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.4); + metap.setNumber(123); + meta.put(PokemonId.SCYTHER, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0124_POKEMON_JYNX"); + metap.setFamily(PokemonFamilyId.FAMILY_JYNX); + metap.setPokemonClass(PokemonClass.COMMON); + metap.setType2(PokemonType.PSYCHIC); + metap.setPokedexHeightM(1.4); + metap.setHeightStdDev(0.175); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.6525); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(172); + metap.setDiskRadiusM(0.9788); + metap.setCollisionRadiusM(0.435); + metap.setPokedexWeightKg(40.6); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ICE); + metap.setCollisionHeadRadiusM(0.522); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.87); + metap.setUniqueId("V0124_POKEMON_JYNX"); + metap.setBaseDefense(134); + metap.setAttackTimerS(11); + metap.setWeightStdDev(5.075); + metap.setCylHeightM(1.218); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.87); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(124); + meta.put(PokemonId.JYNX, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0125_POKEMON_ELECTABUZZ"); + metap.setFamily(PokemonFamilyId.FAMILY_ELECTABUZZ); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.1); + metap.setHeightStdDev(0.1375); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.5635); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(198); + metap.setDiskRadiusM(0.8453); + metap.setCollisionRadiusM(0.392); + metap.setPokedexWeightKg(30); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.28175); + metap.setMovementTimerS(6); + metap.setJumpTimeS(1); + metap.setModelScale(0.98); + metap.setUniqueId("V0125_POKEMON_ELECTABUZZ"); + metap.setBaseDefense(160); + metap.setAttackTimerS(17); + metap.setWeightStdDev(3.75); + metap.setCylHeightM(0.98); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.735); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(125); + meta.put(PokemonId.ELECTABUZZ, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0126_POKEMON_MAGMAR"); + metap.setFamily(PokemonFamilyId.FAMILY_MAGMAR); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.66); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(214); + metap.setDiskRadiusM(0.99); + metap.setCollisionRadiusM(0.44); + metap.setPokedexWeightKg(44.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.33); + metap.setMovementTimerS(14); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.88); + metap.setUniqueId("V0126_POKEMON_MAGMAR"); + metap.setBaseDefense(158); + metap.setAttackTimerS(5); + metap.setWeightStdDev(5.5625); + metap.setCylHeightM(1.144); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.88); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(126); + meta.put(PokemonId.MAGMAR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0127_POKEMON_PINSIR"); + metap.setFamily(PokemonFamilyId.FAMILY_PINSIR); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.5); + metap.setHeightStdDev(0.1875); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.348); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(184); + metap.setDiskRadiusM(0.522); + metap.setCollisionRadiusM(0.348); + metap.setPokedexWeightKg(55); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.BUG); + metap.setCollisionHeadRadiusM(0.348); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.87); + metap.setUniqueId("V0127_POKEMON_PINSIR"); + metap.setBaseDefense(186); + metap.setAttackTimerS(3); + metap.setWeightStdDev(6.875); + metap.setCylHeightM(1.131); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.87); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(127); + meta.put(PokemonId.PINSIR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0128_POKEMON_TAUROS"); + metap.setFamily(PokemonFamilyId.FAMILY_TAUROS); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.4); + metap.setHeightStdDev(0.175); + metap.setBaseStamina(150); + metap.setCylRadiusM(0.5742); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(148); + metap.setDiskRadiusM(0.8613); + metap.setCollisionRadiusM(0.435); + metap.setPokedexWeightKg(88.4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.2871); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.2); + metap.setModelScale(0.87); + metap.setUniqueId("V0128_POKEMON_TAUROS"); + metap.setBaseDefense(184); + metap.setAttackTimerS(11); + metap.setWeightStdDev(11.05); + metap.setCylHeightM(1.19625); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.19625); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.24); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(128); + meta.put(PokemonId.TAUROS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0129_POKEMON_MAGIKARP"); + metap.setFamily(PokemonFamilyId.FAMILY_MAGIKARP); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.9); + metap.setHeightStdDev(0.1125); + metap.setBaseStamina(40); + metap.setCylRadiusM(0.428); + metap.setBaseFleeRate(0.15); + metap.setBaseAttack(42); + metap.setDiskRadiusM(0.642); + metap.setCollisionRadiusM(0.2675); + metap.setPokedexWeightKg(10); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.321); + metap.setMovementTimerS(3600); + metap.setJumpTimeS(1.3); + metap.setModelScale(1.07); + metap.setUniqueId("V0129_POKEMON_MAGIKARP"); + metap.setBaseDefense(84); + metap.setAttackTimerS(3600); + metap.setWeightStdDev(1.25); + metap.setCylHeightM(0.535); + metap.setCandyToEvolve(400); + metap.setCollisionHeightM(0.4815); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.56); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(129); + meta.put(PokemonId.MAGIKARP, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0130_POKEMON_GYARADOS"); + metap.setFamily(PokemonFamilyId.FAMILY_MAGIKARP); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(6.5); + metap.setHeightStdDev(0.8125); + metap.setBaseStamina(190); + metap.setCylRadiusM(0.48); + metap.setBaseFleeRate(0.07); + metap.setBaseAttack(192); + metap.setDiskRadiusM(0.72); + metap.setCollisionRadiusM(0.24); + metap.setPokedexWeightKg(235); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.36); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(0.48); + metap.setUniqueId("V0130_POKEMON_GYARADOS"); + metap.setBaseDefense(196); + metap.setAttackTimerS(3); + metap.setWeightStdDev(29.375); + metap.setCylHeightM(1.2); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.48); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.MAGIKARP); + metap.setCylGroundM(0.48); + metap.setNumber(130); + meta.put(PokemonId.GYARADOS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0131_POKEMON_LAPRAS"); + metap.setFamily(PokemonFamilyId.FAMILY_LAPRAS); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.ICE); + metap.setPokedexHeightM(2.5); + metap.setHeightStdDev(0.3125); + metap.setBaseStamina(260); + metap.setCylRadiusM(0.7); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(186); + metap.setDiskRadiusM(1.05); + metap.setCollisionRadiusM(0.525); + metap.setPokedexWeightKg(220); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.35); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1.2); + metap.setModelScale(0.7); + metap.setUniqueId("V0131_POKEMON_LAPRAS"); + metap.setBaseDefense(190); + metap.setAttackTimerS(8); + metap.setWeightStdDev(27.5); + metap.setCylHeightM(1.75); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.7); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(131); + meta.put(PokemonId.LAPRAS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0132_POKEMON_DITTO"); + metap.setFamily(PokemonFamilyId.FAMILY_DITTO); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(96); + metap.setCylRadiusM(0.4025); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(110); + metap.setDiskRadiusM(0.6038); + metap.setCollisionRadiusM(0.4025); + metap.setPokedexWeightKg(4); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.20125); + metap.setMovementTimerS(3600); + metap.setJumpTimeS(1); + metap.setModelScale(1.61); + metap.setUniqueId("V0132_POKEMON_DITTO"); + metap.setBaseDefense(110); + metap.setAttackTimerS(3600); + metap.setWeightStdDev(0.5); + metap.setCylHeightM(0.52325); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.52325); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(132); + meta.put(PokemonId.DITTO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0133_POKEMON_EEVEE"); + metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); + metap.setPokemonClass(PokemonClass.VERY_COMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.3); + metap.setHeightStdDev(0.0375); + metap.setBaseStamina(110); + metap.setCylRadiusM(0.42); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(114); + metap.setDiskRadiusM(0.63); + metap.setCollisionRadiusM(0.252); + metap.setPokedexWeightKg(6.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.252); + metap.setMovementTimerS(10); + metap.setJumpTimeS(1.35); + metap.setModelScale(1.68); + metap.setUniqueId("V0133_POKEMON_EEVEE"); + metap.setBaseDefense(128); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.8125); + metap.setCylHeightM(0.504); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.336); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(133); + meta.put(PokemonId.EEVEE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0134_POKEMON_VAPOREON"); + metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(260); + metap.setCylRadiusM(0.3465); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(186); + metap.setDiskRadiusM(0.5198); + metap.setCollisionRadiusM(0.21); + metap.setPokedexWeightKg(29); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.WATER); + metap.setCollisionHeadRadiusM(0.2625); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(1.05); + metap.setUniqueId("V0134_POKEMON_VAPOREON"); + metap.setBaseDefense(168); + metap.setAttackTimerS(8); + metap.setWeightStdDev(3.625); + metap.setCylHeightM(0.94499987); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.525); + metap.setShoulderModeScale(0.4); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.EEVEE); + metap.setCylGroundM(0); + metap.setNumber(134); + meta.put(PokemonId.VAPOREON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0135_POKEMON_JOLTEON"); + metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.33); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(192); + metap.setDiskRadiusM(0.495); + metap.setCollisionRadiusM(0.22); + metap.setPokedexWeightKg(24.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.22); + metap.setMovementTimerS(4); + metap.setJumpTimeS(1.3); + metap.setModelScale(1.1); + metap.setUniqueId("V0135_POKEMON_JOLTEON"); + metap.setBaseDefense(174); + metap.setAttackTimerS(11); + metap.setWeightStdDev(3.0625); + metap.setCylHeightM(0.88000011); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.55); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.EEVEE); + metap.setCylGroundM(0); + metap.setNumber(135); + meta.put(PokemonId.JOLTEON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0136_POKEMON_FLAREON"); + metap.setFamily(PokemonFamilyId.FAMILY_EEVEE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.9); + metap.setHeightStdDev(0.1125); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.3045); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(238); + metap.setDiskRadiusM(0.4568); + metap.setCollisionRadiusM(0.2175); + metap.setPokedexWeightKg(25); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.19575); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1.35); + metap.setModelScale(0.87); + metap.setUniqueId("V0136_POKEMON_FLAREON"); + metap.setBaseDefense(178); + metap.setAttackTimerS(8); + metap.setWeightStdDev(3.125); + metap.setCylHeightM(0.783); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.522); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.EEVEE); + metap.setCylGroundM(0); + metap.setNumber(136); + meta.put(PokemonId.FLAREON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0137_POKEMON_PORYGON"); + metap.setFamily(PokemonFamilyId.FAMILY_PORYGON); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.8); + metap.setHeightStdDev(0.1); + metap.setBaseStamina(130); + metap.setCylRadiusM(0.55); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(156); + metap.setDiskRadiusM(0.825); + metap.setCollisionRadiusM(0.385); + metap.setPokedexWeightKg(36.5); + metap.setMovementType(MovementType.HOVERING); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.33); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1); + metap.setModelScale(1.1); + metap.setUniqueId("V0137_POKEMON_PORYGON"); + metap.setBaseDefense(158); + metap.setAttackTimerS(23); + metap.setWeightStdDev(4.5625); + metap.setCylHeightM(0.93500012); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.55); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.55); + metap.setNumber(137); + meta.put(PokemonId.PORYGON, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0138_POKEMON_OMANYTE"); + metap.setFamily(PokemonFamilyId.FAMILY_OMANYTE); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.WATER); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(70); + metap.setCylRadiusM(0.222); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(132); + metap.setDiskRadiusM(0.333); + metap.setCollisionRadiusM(0.222); + metap.setPokedexWeightKg(7.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.111); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.3); + metap.setModelScale(1.48); + metap.setUniqueId("V0138_POKEMON_OMANYTE"); + metap.setBaseDefense(160); + metap.setAttackTimerS(23); + metap.setWeightStdDev(0.9375); + metap.setCylHeightM(0.592); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.592); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(138); + meta.put(PokemonId.OMANYTE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0139_POKEMON_OMASTAR"); + metap.setFamily(PokemonFamilyId.FAMILY_OMANYTE); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.WATER); + metap.setPokedexHeightM(1); + metap.setHeightStdDev(0.125); + metap.setBaseStamina(140); + metap.setCylRadiusM(0.375); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(180); + metap.setDiskRadiusM(0.5625); + metap.setCollisionRadiusM(0.25); + metap.setPokedexWeightKg(35); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.1875); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1.25); + metap.setModelScale(1); + metap.setUniqueId("V0139_POKEMON_OMASTAR"); + metap.setBaseDefense(202); + metap.setAttackTimerS(8); + metap.setWeightStdDev(4.375); + metap.setCylHeightM(1); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.9); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.OMANYTE); + metap.setCylGroundM(0); + metap.setNumber(139); + meta.put(PokemonId.OMASTAR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0140_POKEMON_KABUTO"); + metap.setFamily(PokemonFamilyId.FAMILY_KABUTO); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.WATER); + metap.setPokedexHeightM(0.5); + metap.setHeightStdDev(0.0625); + metap.setBaseStamina(60); + metap.setCylRadiusM(0.3375); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(148); + metap.setDiskRadiusM(0.5063); + metap.setCollisionRadiusM(0.3375); + metap.setPokedexWeightKg(11.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.16875); + metap.setMovementTimerS(8); + metap.setJumpTimeS(0.9); + metap.setModelScale(1.35); + metap.setUniqueId("V0140_POKEMON_KABUTO"); + metap.setBaseDefense(142); + metap.setAttackTimerS(23); + metap.setWeightStdDev(1.4375); + metap.setCylHeightM(0.50625); + metap.setCandyToEvolve(50); + metap.setCollisionHeightM(0.50625); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(140); + meta.put(PokemonId.KABUTO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0141_POKEMON_KABUTOPS"); + metap.setFamily(PokemonFamilyId.FAMILY_KABUTO); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.WATER); + metap.setPokedexHeightM(1.3); + metap.setHeightStdDev(0.1625); + metap.setBaseStamina(120); + metap.setCylRadiusM(0.455); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(190); + metap.setDiskRadiusM(0.6825); + metap.setCollisionRadiusM(0.364); + metap.setPokedexWeightKg(40.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.3185); + metap.setMovementTimerS(11); + metap.setJumpTimeS(1); + metap.setModelScale(0.91); + metap.setUniqueId("V0141_POKEMON_KABUTOPS"); + metap.setBaseDefense(190); + metap.setAttackTimerS(4); + metap.setWeightStdDev(5.0625); + metap.setCylHeightM(1.1375); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.91); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.12); + metap.setParentId(PokemonId.KABUTO); + metap.setCylGroundM(0); + metap.setNumber(141); + meta.put(PokemonId.KABUTOPS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0142_POKEMON_AERODACTYL"); + metap.setFamily(PokemonFamilyId.FAMILY_AERODACTYL); + metap.setPokemonClass(PokemonClass.VERY_RARE); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.8); + metap.setHeightStdDev(0.225); + metap.setBaseStamina(160); + metap.setCylRadiusM(0.399); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(182); + metap.setDiskRadiusM(0.5985); + metap.setCollisionRadiusM(0.285); + metap.setPokedexWeightKg(59); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.ROCK); + metap.setCollisionHeadRadiusM(0.285); + metap.setMovementTimerS(5); + metap.setJumpTimeS(1); + metap.setModelScale(0.57); + metap.setUniqueId("V0142_POKEMON_AERODACTYL"); + metap.setBaseDefense(162); + metap.setAttackTimerS(14); + metap.setWeightStdDev(7.375); + metap.setCylHeightM(0.9975); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.9975); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.855); + metap.setNumber(142); + meta.put(PokemonId.AERODACTYL, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0143_POKEMON_SNORLAX"); + metap.setFamily(PokemonFamilyId.FAMILY_SNORLAX); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(2.1); + metap.setHeightStdDev(0.2625); + metap.setBaseStamina(320); + metap.setCylRadiusM(0.74); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(180); + metap.setDiskRadiusM(1.11); + metap.setCollisionRadiusM(0.74); + metap.setPokedexWeightKg(460); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.NORMAL); + metap.setCollisionHeadRadiusM(0.481); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.74); + metap.setUniqueId("V0143_POKEMON_SNORLAX"); + metap.setBaseDefense(180); + metap.setAttackTimerS(8); + metap.setWeightStdDev(57.5); + metap.setCylHeightM(1.48); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.11); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.16); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(143); + meta.put(PokemonId.SNORLAX, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0144_POKEMON_ARTICUNO"); + metap.setFamily(PokemonFamilyId.FAMILY_ARTICUNO); + metap.setPokemonClass(PokemonClass.LEGENDARY); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.7); + metap.setHeightStdDev(0.2125); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.396); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(198); + metap.setDiskRadiusM(0.594); + metap.setCollisionRadiusM(0.231); + metap.setPokedexWeightKg(55.4); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.ICE); + metap.setCollisionHeadRadiusM(0.231); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.66); + metap.setUniqueId("V0144_POKEMON_ARTICUNO"); + metap.setBaseDefense(242); + metap.setAttackTimerS(8); + metap.setWeightStdDev(6.925); + metap.setCylHeightM(0.99); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.66); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.66); + metap.setNumber(144); + meta.put(PokemonId.ARTICUNO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0145_POKEMON_ZAPDOS"); + metap.setFamily(PokemonFamilyId.FAMILY_ZAPDOS); + metap.setPokemonClass(PokemonClass.LEGENDARY); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(1.6); + metap.setHeightStdDev(0.2); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.5175); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(232); + metap.setDiskRadiusM(0.7763); + metap.setCollisionRadiusM(0.4485); + metap.setPokedexWeightKg(52.6); + metap.setMovementType(MovementType.ELECTRIC); + metap.setType1(PokemonType.ELECTRIC); + metap.setCollisionHeadRadiusM(0.276); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.69); + metap.setUniqueId("V0145_POKEMON_ZAPDOS"); + metap.setBaseDefense(194); + metap.setAttackTimerS(8); + metap.setWeightStdDev(6.575); + metap.setCylHeightM(1.035); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.759); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.8625); + metap.setNumber(145); + meta.put(PokemonId.ZAPDOS, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0146_POKEMON_MOLTRES"); + metap.setFamily(PokemonFamilyId.FAMILY_MOLTRES); + metap.setPokemonClass(PokemonClass.LEGENDARY); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(2); + metap.setHeightStdDev(0.25); + metap.setBaseStamina(180); + metap.setCylRadiusM(0.62); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(242); + metap.setDiskRadiusM(0.93); + metap.setCollisionRadiusM(0.403); + metap.setPokedexWeightKg(60); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.FIRE); + metap.setCollisionHeadRadiusM(0.217); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.62); + metap.setUniqueId("V0146_POKEMON_MOLTRES"); + metap.setBaseDefense(194); + metap.setAttackTimerS(8); + metap.setWeightStdDev(7.5); + metap.setCylHeightM(1.395); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.93); + metap.setShoulderModeScale(0.25); + metap.setBaseCaptureRate(0.00); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.93); + metap.setNumber(146); + meta.put(PokemonId.MOLTRES, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0147_POKEMON_DRATINI"); + metap.setFamily(PokemonFamilyId.FAMILY_DRATINI); + metap.setPokemonClass(PokemonClass.UNCOMMON); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(1.8); + metap.setHeightStdDev(0.225); + metap.setBaseStamina(82); + metap.setCylRadiusM(0.2775); + metap.setBaseFleeRate(0.09); + metap.setBaseAttack(128); + metap.setDiskRadiusM(0.4163); + metap.setCollisionRadiusM(0.2775); + metap.setPokedexWeightKg(3.3); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.DRAGON); + metap.setCollisionHeadRadiusM(0.19425); + metap.setMovementTimerS(10); + metap.setJumpTimeS(0.85); + metap.setModelScale(1.11); + metap.setUniqueId("V0147_POKEMON_DRATINI"); + metap.setBaseDefense(110); + metap.setAttackTimerS(29); + metap.setWeightStdDev(0.4125); + metap.setCylHeightM(0.8325); + metap.setCandyToEvolve(25); + metap.setCollisionHeightM(0.555); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.32); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(147); + meta.put(PokemonId.DRATINI, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0148_POKEMON_DRAGONAIR"); + metap.setFamily(PokemonFamilyId.FAMILY_DRATINI); + metap.setPokemonClass(PokemonClass.RARE); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(4); + metap.setHeightStdDev(0.5); + metap.setBaseStamina(122); + metap.setCylRadiusM(0.5625); + metap.setBaseFleeRate(0.06); + metap.setBaseAttack(170); + metap.setDiskRadiusM(0.8438); + metap.setCollisionRadiusM(0.375); + metap.setPokedexWeightKg(16.5); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.DRAGON); + metap.setCollisionHeadRadiusM(0.28125); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.25); + metap.setModelScale(0.75); + metap.setUniqueId("V0148_POKEMON_DRAGONAIR"); + metap.setBaseDefense(152); + metap.setAttackTimerS(23); + metap.setWeightStdDev(2.0625); + metap.setCylHeightM(1.5); + metap.setCandyToEvolve(100); + metap.setCollisionHeightM(1.125); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.08); + metap.setParentId(PokemonId.DRATINI); + metap.setCylGroundM(0); + metap.setNumber(148); + meta.put(PokemonId.DRAGONAIR, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0149_POKEMON_DRAGONITE"); + metap.setFamily(PokemonFamilyId.FAMILY_DRATINI); + metap.setPokemonClass(PokemonClass.EPIC); + metap.setType2(PokemonType.FLYING); + metap.setPokedexHeightM(2.2); + metap.setHeightStdDev(0.275); + metap.setBaseStamina(182); + metap.setCylRadiusM(0.42); + metap.setBaseFleeRate(0.05); + metap.setBaseAttack(250); + metap.setDiskRadiusM(0.63); + metap.setCollisionRadiusM(0.42); + metap.setPokedexWeightKg(210); + metap.setMovementType(MovementType.FLYING); + metap.setType1(PokemonType.DRAGON); + metap.setCollisionHeadRadiusM(0.245); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(0.7); + metap.setUniqueId("V0149_POKEMON_DRAGONITE"); + metap.setBaseDefense(212); + metap.setAttackTimerS(8); + metap.setWeightStdDev(26.25); + metap.setCylHeightM(1.47); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.05); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0.04); + metap.setParentId(PokemonId.DRAGONAIR); + metap.setCylGroundM(0.595); + metap.setNumber(149); + meta.put(PokemonId.DRAGONITE, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0150_POKEMON_MEWTWO"); + metap.setFamily(PokemonFamilyId.FAMILY_MEWTWO); + metap.setPokemonClass(PokemonClass.LEGENDARY); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(2); + metap.setHeightStdDev(0.25); + metap.setBaseStamina(212); + metap.setCylRadiusM(0.37); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(284); + metap.setDiskRadiusM(0.555); + metap.setCollisionRadiusM(0.37); + metap.setPokedexWeightKg(122); + metap.setMovementType(MovementType.JUMP); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.185); + metap.setMovementTimerS(8); + metap.setJumpTimeS(1.2); + metap.setModelScale(0.74); + metap.setUniqueId("V0150_POKEMON_MEWTWO"); + metap.setBaseDefense(202); + metap.setAttackTimerS(3); + metap.setWeightStdDev(15.25); + metap.setCylHeightM(1.48); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(1.184); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0); + metap.setNumber(150); + meta.put(PokemonId.MEWTWO, metap); + + + + metap = new PokemonMeta(); + metap.setTemplateId(" V0151_POKEMON_MEW"); + metap.setFamily(PokemonFamilyId.FAMILY_MEWTWO); + metap.setPokemonClass(PokemonClass.MYTHIC); + metap.setType2(PokemonType.NONE); + metap.setPokedexHeightM(0.4); + metap.setHeightStdDev(0.05); + metap.setBaseStamina(200); + metap.setCylRadiusM(0.282); + metap.setBaseFleeRate(0.1); + metap.setBaseAttack(220); + metap.setDiskRadiusM(0.423); + metap.setCollisionRadiusM(0.141); + metap.setPokedexWeightKg(4); + metap.setMovementType(MovementType.PSYCHIC); + metap.setType1(PokemonType.PSYCHIC); + metap.setCollisionHeadRadiusM(0.17625); + metap.setMovementTimerS(3); + metap.setJumpTimeS(1); + metap.setModelScale(1.41); + metap.setUniqueId("V0151_POKEMON_MEW"); + metap.setBaseDefense(220); + metap.setAttackTimerS(8); + metap.setWeightStdDev(0.5); + metap.setCylHeightM(0.7755); + metap.setCandyToEvolve(0); + metap.setCollisionHeightM(0.564); + metap.setShoulderModeScale(0.5); + metap.setBaseCaptureRate(0); + metap.setParentId(PokemonId.UNRECOGNIZED); + metap.setCylGroundM(0.0705); + metap.setNumber(151); + meta.put(PokemonId.MEW, metap); + + + + + + + } + + + + /** + * Return PokemonMeta object containing meta info about a pokemon. + * + * @param id the id of the pokemon + * @return PokemonMeta + */ + public static PokemonMeta getMeta(PokemonId id) { + return meta.get(id); + } + + /** + * Return the highest evolution for given family ID. + * !!! CARE TO EVEE THAT DOESNT HAVE BETTER EVOLUTION !!! + * + * @param family the id of the pokemon family + * @return PokemonId + */ + public static PokemonId getHightestForFamily(PokemonFamilyId family) { + return highestForFamily.get(family); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java b/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java new file mode 100644 index 00000000..c63d9e12 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/PokemonType.java @@ -0,0 +1,18 @@ +package com.pokegoapi.api.pokemon; + + +public enum PokemonType { + NONE, + GRASS, + FIRE, + WATER, + BUG, + ELECTRIC, + POISON, + FAIRY, + NORMAL, + PSYCHIC, + FIGHTING, + DRAGON, + FLYING, ICE, ROCK, GROUND, GHOST, STEEL; +} diff --git a/src/main/java/com/pokegoapi/auth/Login.java b/src/main/java/com/pokegoapi/auth/CredentialProvider.java similarity index 69% rename from src/main/java/com/pokegoapi/auth/Login.java rename to src/main/java/com/pokegoapi/auth/CredentialProvider.java index fef733a2..f661de6d 100644 --- a/src/main/java/com/pokegoapi/auth/Login.java +++ b/src/main/java/com/pokegoapi/auth/CredentialProvider.java @@ -16,13 +16,18 @@ package com.pokegoapi.auth; import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; -import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; -public abstract class Login { +/** + * Any Credential Provider can extend this. + */ +public abstract class CredentialProvider { - public abstract AuthInfo login(String username, String password) throws LoginFailedException; + public abstract String getTokenId() throws LoginFailedException, RemoteServerException; - public abstract AuthInfo login(String token) throws LoginFailedException; + public abstract AuthInfo getAuthInfo() throws LoginFailedException, RemoteServerException; + public abstract boolean isTokenIdExpired(); } diff --git a/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java b/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java index be71193b..5f8cb59a 100644 --- a/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java +++ b/src/main/java/com/pokegoapi/auth/GoogleAuthJson.java @@ -17,55 +17,28 @@ import com.squareup.moshi.Json; +import lombok.Getter; +import lombok.Setter; + public class GoogleAuthJson { + @Getter + @Setter @Json(name = "device_code") String deviceCode; + @Getter + @Setter @Json(name = "user_code") String userCode; + @Getter + @Setter @Json(name = "verification_url") String verificationUrl; + @Getter + @Setter @Json(name = "expires_in") int expiresIn; + @Getter + @Setter @Json(name = "interval") int interval; - - public String getDeviceCode() { - return deviceCode; - } - - public void setDeviceCode(String deviceCode) { - this.deviceCode = deviceCode; - } - - public String getUserCode() { - return userCode; - } - - public void setUserCode(String userCode) { - this.userCode = userCode; - } - - public String getVerificationUrl() { - return verificationUrl; - } - - public void setVerificationUrl(String verificationUrl) { - this.verificationUrl = verificationUrl; - } - - public int getExpiresIn() { - return expiresIn; - } - - public void setExpiresIn(int expiresIn) { - this.expiresIn = expiresIn; - } - - public int getInterval() { - return interval; - } - - public void setInterval(int interval) { - this.interval = interval; - } } diff --git a/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java b/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java index 4d0b58e7..d31c5efc 100644 --- a/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java +++ b/src/main/java/com/pokegoapi/auth/GoogleAuthTokenJson.java @@ -17,64 +17,31 @@ import com.squareup.moshi.Json; +import lombok.Getter; +import lombok.Setter; + public class GoogleAuthTokenJson { + @Getter + @Setter private String error; + @Getter + @Setter @Json(name = "access_token") private String accessToken; + @Getter + @Setter @Json(name = "token_type") private String tokenType; + @Getter + @Setter @Json(name = "expires_in") private int expiresIn; + @Getter + @Setter @Json(name = "refresh_token") private String refreshToken; + @Getter + @Setter @Json(name = "id_token") private String idToken; - - public String getError() { - return error; - } - - public void setError(String error) { - this.error = error; - } - - public String getAccessToken() { - return accessToken; - } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - public String getTokenType() { - return tokenType; - } - - public void setTokenType(String tokenType) { - this.tokenType = tokenType; - } - - public int getExpiresIn() { - return expiresIn; - } - - public void setExpiresIn(int expiresIn) { - this.expiresIn = expiresIn; - } - - public String getRefreshToken() { - return refreshToken; - } - - public void setRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - } - - public String getIdToken() { - return idToken; - } - - public void setIdToken(String idToken) { - this.idToken = idToken; - } } diff --git a/src/main/java/com/pokegoapi/auth/GoogleCredentialProvider.java b/src/main/java/com/pokegoapi/auth/GoogleCredentialProvider.java new file mode 100644 index 00000000..60518fd8 --- /dev/null +++ b/src/main/java/com/pokegoapi/auth/GoogleCredentialProvider.java @@ -0,0 +1,277 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.auth; + +import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.Log; +import com.squareup.moshi.Moshi; +import lombok.Getter; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +import java.io.IOException; +import java.net.URISyntaxException; + +public class GoogleCredentialProvider extends CredentialProvider { + + public static final String SECRET = "NCjF1TLi2CcY6t5mt0ZveuL7"; + public static final String CLIENT_ID = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com"; + public static final String OAUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/device/code"; + public static final String OAUTH_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token"; + private static final String TAG = GoogleCredentialProvider.class.getSimpleName(); + //We try and refresh token 5 minutes before it actually expires + private static final long REFRESH_TOKEN_BUFFER_TIME = 5 * 60 * 1000; + private final OkHttpClient client; + + private final OnGoogleLoginOAuthCompleteListener onGoogleLoginOAuthCompleteListener; + + private long expiresTimestamp; + + private String tokenId; + + @Getter + private String refreshToken; + + private AuthInfo.Builder authbuilder; + + /** + * Used for logging in when one has a persisted refreshToken. + * + * @param client OkHttp client + * @param refreshToken Refresh Token Persisted by user + * @throws LoginFailedException When login fails + */ + public GoogleCredentialProvider(OkHttpClient client, String refreshToken) + throws LoginFailedException, RemoteServerException { + this.client = client; + this.refreshToken = refreshToken; + onGoogleLoginOAuthCompleteListener = null; + refreshToken(refreshToken); + authbuilder = AuthInfo.newBuilder(); + } + + /** + * Used for logging in when you dont have a persisted refresh token. + * + * @param client OkHttp client + * @param onGoogleLoginOAuthCompleteListener Callback to know verification url and also persist refresh token + * @throws LoginFailedException When login fails + */ + public GoogleCredentialProvider(OkHttpClient client, + OnGoogleLoginOAuthCompleteListener onGoogleLoginOAuthCompleteListener) + throws LoginFailedException { + this.client = client; + if (onGoogleLoginOAuthCompleteListener != null) { + this.onGoogleLoginOAuthCompleteListener = onGoogleLoginOAuthCompleteListener; + } else { + throw new LoginFailedException("You need to implement OnGoogleLoginOAuthCompleteListener"); + } + login(); + authbuilder = AuthInfo.newBuilder(); + } + + /** + * Given the refresh token fetches a new access token and returns AuthInfo. + * + * @param refreshToken Refresh token persisted by the user after initial login + * @throws LoginFailedException If we fail to get tokenId + */ + public void refreshToken(String refreshToken) throws LoginFailedException, RemoteServerException { + HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() + .addQueryParameter("client_id", CLIENT_ID) + .addQueryParameter("client_secret", SECRET) + .addQueryParameter("refresh_token", refreshToken) + .addQueryParameter("grant_type", "refresh_token") + .build(); + //Empty request body + RequestBody reqBody = RequestBody.create(null, new byte[0]); + Request request = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + + Response response = null; + try { + response = client.newCall(request).execute(); + } catch (IOException e) { + throw new RemoteServerException("Network Request failed to fetch refreshed tokenId", e); + } + Moshi moshi = new Moshi.Builder().build(); + GoogleAuthTokenJson googleAuthTokenJson = null; + try { + googleAuthTokenJson = moshi.adapter(GoogleAuthTokenJson.class).fromJson(response.body().string()); + Log.d(TAG, "" + googleAuthTokenJson.getExpiresIn()); + } catch (IOException e) { + throw new RemoteServerException("Failed to unmarshal the Json response to fetch refreshed tokenId", e); + } + if (googleAuthTokenJson.getError() != null) { + throw new LoginFailedException(googleAuthTokenJson.getError()); + } else { + Log.d(TAG, "Refreshed Token " + googleAuthTokenJson.getIdToken()); + expiresTimestamp = System.currentTimeMillis() + + (googleAuthTokenJson.getExpiresIn() * 1000 - REFRESH_TOKEN_BUFFER_TIME); + tokenId = googleAuthTokenJson.getIdToken(); + } + } + + /** + * Starts a login flow for google using googles device oauth endpoint. + */ + public void login() throws LoginFailedException { + + HttpUrl url = HttpUrl.parse(OAUTH_ENDPOINT).newBuilder() + .addQueryParameter("client_id", CLIENT_ID) + .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") + .build(); + + //Create empty body + RequestBody reqBody = RequestBody.create(null, new byte[0]); + + Request request = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + Response response = null; + try { + response = client.newCall(request).execute(); + } catch (IOException e) { + throw new LoginFailedException("Network Request failed to fetch tokenId", e); + } + + Moshi moshi = new Moshi.Builder().build(); + + GoogleAuthJson googleAuth = null; + try { + googleAuth = moshi.adapter(GoogleAuthJson.class).fromJson(response.body().string()); + Log.d(TAG, "" + googleAuth.getExpiresIn()); + } catch (IOException e) { + throw new LoginFailedException("Failed to unmarshell the Json response to fetch tokenId", e); + } + Log.d(TAG, "Get user to go to:" + + googleAuth.getVerificationUrl() + + " and enter code:" + googleAuth.getUserCode()); + onGoogleLoginOAuthCompleteListener.onInitialOAuthComplete(googleAuth); + + GoogleAuthTokenJson googleAuthTokenJson; + try { + while ((googleAuthTokenJson = poll(googleAuth)) == null) { + Thread.sleep(googleAuth.getInterval() * 1000); + } + } catch (InterruptedException e) { + throw new LoginFailedException("Sleeping was interrupted", e); + } catch (IOException e) { + throw new LoginFailedException(e); + } catch (URISyntaxException e) { + throw new LoginFailedException(e); + } + + Log.d(TAG, "Got token: " + googleAuthTokenJson.getIdToken()); + onGoogleLoginOAuthCompleteListener.onTokenIdReceived(googleAuthTokenJson); + expiresTimestamp = System.currentTimeMillis() + + (googleAuthTokenJson.getExpiresIn() * 1000 - REFRESH_TOKEN_BUFFER_TIME); + tokenId = googleAuthTokenJson.getIdToken(); + refreshToken = googleAuthTokenJson.getRefreshToken(); + } + + + private GoogleAuthTokenJson poll(GoogleAuthJson json) throws URISyntaxException, IOException, LoginFailedException { + HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() + .addQueryParameter("client_id", CLIENT_ID) + .addQueryParameter("client_secret", SECRET) + .addQueryParameter("code", json.getDeviceCode()) + .addQueryParameter("grant_type", "http://oauth.net/grant_type/device/1.0") + .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") + .build(); + + //Empty request body + RequestBody reqBody = RequestBody.create(null, new byte[0]); + Request request = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + + Response response = client.newCall(request).execute(); + + Moshi moshi = new Moshi.Builder().build(); + GoogleAuthTokenJson token = moshi.adapter(GoogleAuthTokenJson.class).fromJson(response.body().string()); + + if (token.getError() == null) { + return token; + } else { + return null; + } + } + + @Override + public String getTokenId() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + refreshToken(refreshToken); + } + return tokenId; + } + + /** + * Refreshes tokenId if it has expired + * + * @return AuthInfo object + * @throws LoginFailedException When login fails + */ + @Override + public AuthInfo getAuthInfo() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + refreshToken(refreshToken); + } + authbuilder.setProvider("google"); + authbuilder.setToken(AuthInfo.JWT.newBuilder().setContents(tokenId).setUnknown2(59).build()); + return authbuilder.build(); + } + + @Override + public boolean isTokenIdExpired() { + if (System.currentTimeMillis() > expiresTimestamp) { + return true; + } else { + return false; + } + } + + /** + * This callback will be called when we get the + * verification url and device code. + * This will allow applications to + * programmatically redirect user to redirect user. + */ + public interface OnGoogleLoginOAuthCompleteListener { + /** + * Good Hook to provide custom redirects to verification url page. + * + * @param googleAuthJson GoogleAuth object + */ + void onInitialOAuthComplete(GoogleAuthJson googleAuthJson); + + /** + * Good Idea to persist the refresh token recieved here + * + * @param googleAuthTokenJson GoogleAuthToken object + */ + void onTokenIdReceived(GoogleAuthTokenJson googleAuthTokenJson); + } +} diff --git a/src/main/java/com/pokegoapi/auth/GoogleLogin.java b/src/main/java/com/pokegoapi/auth/GoogleLogin.java deleted file mode 100644 index ad80f8c5..00000000 --- a/src/main/java/com/pokegoapi/auth/GoogleLogin.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.pokegoapi.auth; - -import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; -import com.pokegoapi.exceptions.LoginFailedException; -import com.pokegoapi.util.Log; -import com.squareup.moshi.Moshi; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -import java.io.IOException; -import java.net.URISyntaxException; - -public class GoogleLogin extends Login { - public static final String SECRET = "NCjF1TLi2CcY6t5mt0ZveuL7"; - public static final String CLIENT_ID = "848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com"; - public static final String OAUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/device/code"; - public static final String OAUTH_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token"; - private static final String TAG = GoogleLogin.class.getSimpleName(); - - private final OkHttpClient client; - - public GoogleLogin(OkHttpClient client) { - this.client = client; - } - - /** - * Returns an AuthInfo object given a token, this should not be an access token but rather an id_token - * - * @param token the id_token stored from a previous oauth attempt. - * @return AuthInfo a AuthInfo proto structure to be encapsulated in server requests - */ - public AuthInfo login(String token) { - AuthInfo.Builder builder = AuthInfo.newBuilder(); - builder.setProvider("google"); - builder.setToken(AuthInfo.JWT.newBuilder().setContents(token).setUnknown2(59).build()); - return builder.build(); - } - - /** - * Starts a login flow for google using a username and password, this uses googles device oauth endpoint, - * a URL and code is displayed, not really ideal right now. - * - * @param username Google username - * @param password Google password - * @return AuthInfo a AuthInfo proto structure to be encapsulated in server requests - */ - public AuthInfo login(String username, String password) throws LoginFailedException { - try { - HttpUrl url = HttpUrl.parse(OAUTH_ENDPOINT).newBuilder() - .addQueryParameter("client_id", CLIENT_ID) - .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") - .build(); - - //Create empty body - RequestBody reqBody = RequestBody.create(null, new byte[0]); - - Request request = new Request.Builder() - .url(url) - .method("POST", reqBody) - .build(); - - Response response = client.newCall(request).execute(); - - Moshi moshi = new Moshi.Builder().build(); - - GoogleAuthJson googleAuth = moshi.adapter(GoogleAuthJson.class).fromJson(response.body().string()); - Log.d(TAG, "Get user to go to:" - + googleAuth.getVerificationUrl() - + " and enter code:" + googleAuth.getUserCode()); - - GoogleAuthTokenJson token; - while ((token = poll(googleAuth)) == null) { - Thread.sleep(googleAuth.getInterval() * 1000); - } - - - Log.d(TAG, "Got token: " + token.getIdToken()); - - AuthInfo.Builder authbuilder = AuthInfo.newBuilder(); - authbuilder.setProvider("google"); - authbuilder.setToken(AuthInfo.JWT.newBuilder().setContents(token.getIdToken()).setUnknown2(59).build()); - - return authbuilder.build(); - } catch (Exception e) { - throw new LoginFailedException(); - } - - } - - - private GoogleAuthTokenJson poll(GoogleAuthJson json) throws URISyntaxException, IOException { - HttpUrl url = HttpUrl.parse(OAUTH_TOKEN_ENDPOINT).newBuilder() - .addQueryParameter("client_id", CLIENT_ID) - .addQueryParameter("client_secret", SECRET) - .addQueryParameter("code", json.getDeviceCode()) - .addQueryParameter("grant_type", "http://oauth.net/grant_type/device/1.0") - .addQueryParameter("scope", "openid email https://www.googleapis.com/auth/userinfo.email") - .build(); - - //Empty request body - RequestBody reqBody = RequestBody.create(null, new byte[0]); - Request request = new Request.Builder() - .url(url) - .method("POST", reqBody) - .build(); - - Response response = client.newCall(request).execute(); - - Moshi moshi = new Moshi.Builder().build(); - GoogleAuthTokenJson token = moshi.adapter(GoogleAuthTokenJson.class).fromJson(response.body().string()); - - if (token.getError() == null) { - return token; - } else { - return null; - } - - } - -} diff --git a/src/main/java/com/pokegoapi/auth/PtcAuthJson.java b/src/main/java/com/pokegoapi/auth/PtcAuthJson.java index 6a719dfa..5c9bedcd 100644 --- a/src/main/java/com/pokegoapi/auth/PtcAuthJson.java +++ b/src/main/java/com/pokegoapi/auth/PtcAuthJson.java @@ -15,24 +15,15 @@ package com.pokegoapi.auth; +import lombok.Getter; +import lombok.Setter; + public class PtcAuthJson { + @Getter + @Setter private String lt; + @Getter + @Setter private String execution; - - public String getLt() { - return lt; - } - - public void setLt(String lt) { - this.lt = lt; - } - - public String getExecution() { - return execution; - } - - public void setExecution(String execution) { - this.execution = execution; - } } diff --git a/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java b/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java new file mode 100644 index 00000000..216b148a --- /dev/null +++ b/src/main/java/com/pokegoapi/auth/PtcCredentialProvider.java @@ -0,0 +1,257 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.auth; + +import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.squareup.moshi.Moshi; +import okhttp3.Cookie; +import okhttp3.CookieJar; +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + +public class PtcCredentialProvider extends CredentialProvider { + public static final String CLIENT_SECRET = "w8ScCUXJQc6kXKw8FiOhd8Fixzht18Dq3PEVkUCP5ZPxtgyWsbTvWHFLm2wNY0JR"; + public static final String REDIRECT_URI = "https://www.nianticlabs.com/pokemongo/error"; + public static final String CLIENT_ID = "mobile-app_pokemon-go"; + public static final String API_URL = "https://pgorelease.nianticlabs.com/plfe/rpc"; + public static final String LOGIN_URL = "https://sso.pokemon.com/sso/login?service=https%3A%2F%2Fsso.pokemon.com%2Fsso%2Foauth2.0%2FcallbackAuthorize"; + public static final String LOGIN_OAUTH = "https://sso.pokemon.com/sso/oauth2.0/accessToken"; + public static final String USER_AGENT = "niantic"; + private static final String TAG = PtcCredentialProvider.class.getSimpleName(); + //We try and refresh token 5 minutes before it actually expires + private static final long REFRESH_TOKEN_BUFFER_TIME = 5 * 60 * 1000; + + private final OkHttpClient client; + private final String username; + private final String password; + private String tokenId; + private long expiresTimestamp; + private AuthInfo.Builder authbuilder; + + /** + * Instantiates a new Ptc login. + * + * @param client the client + * @param username Username + * @param password password + */ + public PtcCredentialProvider(OkHttpClient client, String username, String password) + throws LoginFailedException, RemoteServerException { + this.username = username; + this.password = password; + /* + This is a temporary, in-memory cookie jar. + We don't require any persistence outside of the scope of the login, + so it being discarded is completely fine + */ + CookieJar tempJar = new CookieJar() { + private final HashMap> cookieStore = new HashMap>(); + + @Override + public void saveFromResponse(HttpUrl url, List cookies) { + cookieStore.put(url.host(), cookies); + } + + @Override + public List loadForRequest(HttpUrl url) { + List cookies = cookieStore.get(url.host()); + return cookies != null ? cookies : new ArrayList(); + } + }; + + this.client = client.newBuilder() + .cookieJar(tempJar) + .addInterceptor(new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + //Makes sure the User-Agent is always set + Request req = chain.request(); + req = req.newBuilder().header("User-Agent", USER_AGENT).build(); + return chain.proceed(req); + } + }) + .build(); + + authbuilder = AuthInfo.newBuilder(); + login(username, password); + } + + /** + * Starts a login flow for pokemon.com (PTC) using a username and password, + * this uses pokemon.com's oauth endpoint and returns a usable AuthInfo without user interaction + * + * @param username PTC username + * @param password PTC password + */ + private void login(String username, String password) throws LoginFailedException, RemoteServerException { + //TODO: stop creating an okhttp client per request + Request get = new Request.Builder() + .url(LOGIN_URL) + .get() + .build(); + + Response getResponse = null; + try { + getResponse = client.newCall(get).execute(); + } catch (IOException e) { + throw new RemoteServerException("Failed to receive contents from server", e); + } + + Moshi moshi = new Moshi.Builder().build(); + + PtcAuthJson ptcAuth = null; + try { + String response = getResponse.body().string(); + ptcAuth = moshi.adapter(PtcAuthJson.class).fromJson(response); + } catch (IOException e) { + throw new RemoteServerException("Looks like the servers are down", e); + } + + HttpUrl url = HttpUrl.parse(LOGIN_URL).newBuilder() + .addQueryParameter("lt", ptcAuth.getLt()) + .addQueryParameter("execution", ptcAuth.getExecution()) + .addQueryParameter("_eventId", "submit") + .addQueryParameter("username", username) + .addQueryParameter("password", password) + .build(); + + RequestBody reqBody = RequestBody.create(null, new byte[0]); + + Request postRequest = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + + // Need a new client for this to not follow redirects + Response response = null; + try { + response = client.newBuilder() + .followRedirects(false) + .followSslRedirects(false) + .build() + .newCall(postRequest) + .execute(); + } catch (IOException e) { + throw new RemoteServerException("Network failure", e); + } + + String body = null; + try { + body = response.body().string(); + } catch (IOException e) { + throw new RemoteServerException("Response body fetching failed", e); + } + + if (body.length() > 0) { + PtcError ptcError = null; + try { + ptcError = moshi.adapter(PtcError.class).fromJson(body); + } catch (IOException e) { + throw new RemoteServerException("Unmarshalling failure", e); + } + if (ptcError.getError() != null && ptcError.getError().length() > 0) { + throw new LoginFailedException(ptcError.getError()); + } + } + + String ticket = null; + for (String location : response.headers("location")) { + ticket = location.split("ticket=")[1]; + } + + url = HttpUrl.parse(LOGIN_OAUTH).newBuilder() + .addQueryParameter("client_id", CLIENT_ID) + .addQueryParameter("redirect_uri", REDIRECT_URI) + .addQueryParameter("client_secret", CLIENT_SECRET) + .addQueryParameter("grant_type", "refreshToken") + .addQueryParameter("code", ticket) + .build(); + + postRequest = new Request.Builder() + .url(url) + .method("POST", reqBody) + .build(); + + try { + response = client.newCall(postRequest).execute(); + } catch (IOException e) { + throw new RemoteServerException("Network Failure ", e); + } + + try { + body = response.body().string(); + } catch (IOException e) { + throw new RemoteServerException("Network failure", e); + } + + String[] params; + try { + params = body.split("&"); + this.tokenId = params[0].split("=")[1]; + this.expiresTimestamp = System.currentTimeMillis() + + (Integer.valueOf(params[1].split("=")[1]) * 1000 - REFRESH_TOKEN_BUFFER_TIME); + } catch (Exception e) { + throw new LoginFailedException("Failed to fetch token"); + } + } + + @Override + public String getTokenId() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + login(username, password); + } + return tokenId; + } + + /** + * Valid auth info object * + * + * @return AuthInfo a AuthInfo proto structure to be encapsulated in server requests + * @throws LoginFailedException when refreshing fails + */ + @Override + public AuthInfo getAuthInfo() throws LoginFailedException, RemoteServerException { + if (isTokenIdExpired()) { + login(username, password); + } + + authbuilder.setProvider("ptc"); + authbuilder.setToken(AuthInfo.JWT.newBuilder().setContents(tokenId).setUnknown2(59).build()); + + return authbuilder.build(); + } + + @Override + public boolean isTokenIdExpired() { + if (System.currentTimeMillis() > expiresTimestamp) { + return true; + } else { + return false; + } + } +} diff --git a/src/main/java/com/pokegoapi/auth/PtcError.java b/src/main/java/com/pokegoapi/auth/PtcError.java index 00ec9dfc..546dbbc3 100644 --- a/src/main/java/com/pokegoapi/auth/PtcError.java +++ b/src/main/java/com/pokegoapi/auth/PtcError.java @@ -15,15 +15,12 @@ package com.pokegoapi.auth; +import lombok.Getter; +import lombok.Setter; + public class PtcError { + @Getter + @Setter private String error; - - public String getError() { - return error; - } - - public void setError(String error) { - this.error = error; - } } diff --git a/src/main/java/com/pokegoapi/auth/PtcLogin.java b/src/main/java/com/pokegoapi/auth/PtcLogin.java deleted file mode 100644 index fe124245..00000000 --- a/src/main/java/com/pokegoapi/auth/PtcLogin.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.pokegoapi.auth; - -import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; -import com.pokegoapi.exceptions.LoginFailedException; -import com.squareup.moshi.Moshi; -import lombok.Getter; -import okhttp3.Cookie; -import okhttp3.CookieJar; -import okhttp3.HttpUrl; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - - -public class PtcLogin extends Login { - public static final String CLIENT_SECRET = "w8ScCUXJQc6kXKw8FiOhd8Fixzht18Dq3PEVkUCP5ZPxtgyWsbTvWHFLm2wNY0JR"; - public static final String REDIRECT_URI = "https://www.nianticlabs.com/pokemongo/error"; - public static final String CLIENT_ID = "mobile-app_pokemon-go"; - - public static final String API_URL = "https://pgorelease.nianticlabs.com/plfe/rpc"; - public static final String LOGIN_URL = "https://sso.pokemon.com/sso/login?service=https%3A%2F%2Fsso.pokemon.com%2Fsso%2Foauth2.0%2FcallbackAuthorize"; - public static final String LOGIN_OAUTH = "https://sso.pokemon.com/sso/oauth2.0/accessToken"; - - public static final String USER_AGENT = "niantic"; - - private final OkHttpClient client; - @Getter - String token; - - /** - * Instantiates a new Ptc login. - * - * @param client the client - */ - public PtcLogin(OkHttpClient client) { - /* - This is a temporary, in-memory cookie jar. - We don't require any persistence outside of the scope of the login, - so it being discarded is completely fine - */ - CookieJar tempJar = new CookieJar() { - private final HashMap> cookieStore = new HashMap>(); - - @Override - public void saveFromResponse(HttpUrl url, List cookies) { - cookieStore.put(url.host(), cookies); - } - - @Override - public List loadForRequest(HttpUrl url) { - List cookies = cookieStore.get(url.host()); - return cookies != null ? cookies : new ArrayList(); - } - }; - - this.client = client.newBuilder() - .cookieJar(tempJar) - .addInterceptor(new Interceptor() { - @Override - public Response intercept(Chain chain) throws IOException { - //Makes sure the User-Agent is always set - Request req = chain.request(); - req = req.newBuilder().header("User-Agent", USER_AGENT).build(); - return chain.proceed(req); - } - }) - .build(); - } - - /** - * Returns an AuthInfo object given a token, this should not be an access token but rather an id_token - * - * @param token the id_token stored from a previous oauth attempt. - * @return AuthInfo a AuthInfo proto structure to be encapsulated in server requests - */ - public AuthInfo login(String token) { - AuthInfo.Builder builder = AuthInfo.newBuilder(); - builder.setProvider("ptc"); - builder.setToken(AuthInfo.JWT.newBuilder().setContents(token).setUnknown2(59).build()); - return builder.build(); - } - - /** - * Starts a login flow for pokemon.com (PTC) using a username and password, - * this uses pokemon.com's oauth endpoint and returns a usable AuthInfo without user interaction - * - * @param username PTC username - * @param password PTC password - * @return AuthInfo a AuthInfo proto structure to be encapsulated in server requests - */ - public AuthInfo login(String username, String password) throws LoginFailedException { - //TODO: stop creating an okhttp client per request - - try { - Request get = new Request.Builder() - .url(LOGIN_URL) - .get() - .build(); - - Response getResponse = client.newCall(get).execute(); - - Moshi moshi = new Moshi.Builder().build(); - - PtcAuthJson ptcAuth = moshi.adapter(PtcAuthJson.class).fromJson(getResponse.body().string()); - - HttpUrl url = HttpUrl.parse(LOGIN_URL).newBuilder() - .addQueryParameter("lt", ptcAuth.getLt()) - .addQueryParameter("execution", ptcAuth.getExecution()) - .addQueryParameter("_eventId", "submit") - .addQueryParameter("username", username) - .addQueryParameter("password", password) - .build(); - - RequestBody reqBody = RequestBody.create(null, new byte[0]); - - Request postRequest = new Request.Builder() - .url(url) - .method("POST", reqBody) - .build(); - - // Need a new client for this to not follow redirects - Response response = client.newBuilder() - .followRedirects(false) - .followSslRedirects(false) - .build() - .newCall(postRequest) - .execute(); - - String body = response.body().string(); - - if (body.length() > 0) { - PtcError ptcError = moshi.adapter(PtcError.class).fromJson(body); - if (ptcError.getError() != null && ptcError.getError().length() > 0) { - throw new LoginFailedException(); - } - } - - String ticket = null; - for (String location : response.headers("location")) { - ticket = location.split("ticket=")[1]; - } - - url = HttpUrl.parse(LOGIN_OAUTH).newBuilder() - .addQueryParameter("client_id", CLIENT_ID) - .addQueryParameter("redirect_uri", REDIRECT_URI) - .addQueryParameter("client_secret", CLIENT_SECRET) - .addQueryParameter("grant_type", "refresh_token") - .addQueryParameter("code", ticket) - .build(); - - postRequest = new Request.Builder() - .url(url) - .method("POST", reqBody) - .build(); - - response = client.newCall(postRequest).execute(); - - body = response.body().string(); - - String token; - try { - token = body.split("token=")[1]; - token = token.split("&")[0]; - } catch (Exception e) { - throw new LoginFailedException(); - } - - AuthInfo.Builder authbuilder = AuthInfo.newBuilder(); - authbuilder.setProvider("ptc"); - authbuilder.setToken(AuthInfo.JWT.newBuilder().setContents(token).setUnknown2(59).build()); - - return authbuilder.build(); - } catch (Exception e) { - throw new LoginFailedException(); - } - - } - -} diff --git a/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java b/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java index 3ea40914..1c7646dc 100644 --- a/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java +++ b/src/main/java/com/pokegoapi/examples/CatchPokemonAtAreaExample.java @@ -32,15 +32,16 @@ import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; + import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.map.pokemon.CatchResult; import com.pokegoapi.api.map.pokemon.CatchablePokemon; import com.pokegoapi.api.map.pokemon.EncounterResult; -import com.pokegoapi.auth.GoogleLogin; -import com.pokegoapi.auth.PtcLogin; +import com.pokegoapi.auth.PtcCredentialProvider; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.util.Log; + import okhttp3.OkHttpClient; import java.util.List; @@ -54,10 +55,12 @@ public static void main(String[] args) { OkHttpClient http = new OkHttpClient(); RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth = null; try { - auth = new PtcLogin(http).login(ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD); - // or google - //auth = new GoogleLogin(http).login("", ""); // currently uses oauth flow so no user or pass needed - PokemonGo go = new PokemonGo(auth, http); + //or google + //new PokemonGo(GoogleCredentialProvider(http,listner)); + //Subsiquently + //new PokemonGo(GoogleCredentialProvider(http,refreshtoken)); + PokemonGo go = new PokemonGo(new PtcCredentialProvider(http, ExampleLoginDetails.LOGIN, + ExampleLoginDetails.PASSWORD), http); // set location go.setLocation(-32.058087, 115.744325, 0); diff --git a/src/main/java/com/pokegoapi/examples/FightGymExample.java b/src/main/java/com/pokegoapi/examples/FightGymExample.java new file mode 100644 index 00000000..96aa5338 --- /dev/null +++ b/src/main/java/com/pokegoapi/examples/FightGymExample.java @@ -0,0 +1,103 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.examples; + + +import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.gym.Battle; +import com.pokegoapi.api.gym.Gym; +import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.auth.CredentialProvider; +import com.pokegoapi.auth.PtcCredentialProvider; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.Log; +import okhttp3.OkHttpClient; + +import java.util.List; + +public class FightGymExample { + + /** + * Catches a pokemon at an area. + */ + public static void main(String[] args) { + OkHttpClient http = new OkHttpClient(); + CredentialProvider auth = null; + try { + auth = new PtcCredentialProvider(http, ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD); + // or google + //auth = new GoogleCredentialProvider(http, token); // currently uses oauth flow so no user or pass needed + PokemonGo go = new PokemonGo(auth, http); + // set location + go.setLocation(-32.011011, 115.932831, 0); + + List pokemons = go.getInventories().getPokebank().getPokemons(); + Pokemon[] attackers = new Pokemon[6]; + + for (int i = 0; i < 6; i++) { + attackers[i] = pokemons.get(i); + } + + + for (Gym gym : go.getMap().getGyms()) { + if (gym.isAttackable()) { + Battle battle = gym.battle(attackers); + // start the battle + Result result = battle.start(); + + if (result == Result.SUCCESS) { + // started battle successfully + + // loop while battle is not finished + while (!battle.isConcluded()) { + System.out.println("attack:" + battle.attack(5)); + Thread.sleep(500); + } + + System.out.println("Battle result:" + battle.getOutcome()); + + } else { + System.out.println("FAILED:" + result); + } + } + + } + + } catch (LoginFailedException | RemoteServerException | InterruptedException e) { + // failed to login, invalid credentials, auth issue or server issue. + Log.e("Main", "Failed to login or server issue: ", e); + + } + } +} diff --git a/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java b/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java index bce2958a..c49d20c2 100644 --- a/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java +++ b/src/main/java/com/pokegoapi/examples/TransferOnePidgeyExample.java @@ -18,12 +18,14 @@ import POGOProtos.Enums.PokemonIdOuterClass; import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; import POGOProtos.Networking.Responses.ReleasePokemonResponseOuterClass; + import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.pokemon.Pokemon; -import com.pokegoapi.auth.PtcLogin; +import com.pokegoapi.auth.PtcCredentialProvider; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.util.Log; + import okhttp3.OkHttpClient; import java.util.List; @@ -38,10 +40,12 @@ public static void main(String[] args) { OkHttpClient http = new OkHttpClient(); RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth = null; try { - auth = new PtcLogin(http).login(ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD); - // or google - //auth = new GoogleLogin(http).login("", ""); // currently uses oauth flow so no user or pass needed - PokemonGo go = new PokemonGo(auth, http); + //or google + //new PokemonGo(GoogleCredentialProvider(http,listner)); + //Subsiquently + //new PokemonGo(GoogleCredentialProvider(http,refreshtoken)); + PokemonGo go = new PokemonGo(new PtcCredentialProvider(http, ExampleLoginDetails.LOGIN, + ExampleLoginDetails.PASSWORD), http); List pidgeys = go.getInventories().getPokebank().getPokemonByPokemonId(PokemonIdOuterClass.PokemonId.PIDGEY); diff --git a/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java b/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java index 29e45d70..85be079e 100644 --- a/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java +++ b/src/main/java/com/pokegoapi/exceptions/LoginFailedException.java @@ -27,4 +27,8 @@ public LoginFailedException(String reason) { public LoginFailedException(Exception exception) { super(exception); } + + public LoginFailedException(String reason, Exception exception) { + super(reason, exception); + } } diff --git a/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java b/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java index 23d5d2a3..5e3ca966 100644 --- a/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java +++ b/src/main/java/com/pokegoapi/exceptions/RemoteServerException.java @@ -27,4 +27,8 @@ public RemoteServerException(String reason) { public RemoteServerException(Exception exception) { super(exception); } + + public RemoteServerException(String reason, Exception exception) { + super(reason, exception); + } } diff --git a/src/main/java/com/pokegoapi/main/RequestHandler.java b/src/main/java/com/pokegoapi/main/RequestHandler.java index 7520bf3a..53bbd98b 100644 --- a/src/main/java/com/pokegoapi/main/RequestHandler.java +++ b/src/main/java/com/pokegoapi/main/RequestHandler.java @@ -17,7 +17,6 @@ import POGOProtos.Networking.Envelopes.AuthTicketOuterClass; import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; -import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo; import POGOProtos.Networking.Envelopes.ResponseEnvelopeOuterClass; import com.google.protobuf.ByteString; import com.pokegoapi.api.PokemonGo; @@ -39,7 +38,6 @@ public class RequestHandler { private final PokemonGo api; private RequestEnvelopeOuterClass.RequestEnvelope.Builder builder; private boolean hasRequests; - private RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth; private List serverRequests; private String apiEndpoint; private OkHttpClient client; @@ -50,14 +48,12 @@ public class RequestHandler { * Instantiates a new Request handler. * * @param api the api - * @param auth the auth * @param client the client */ - public RequestHandler(PokemonGo api, RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth, OkHttpClient client) { + public RequestHandler(PokemonGo api, OkHttpClient client) throws LoginFailedException, RemoteServerException { this.api = api; this.client = client; apiEndpoint = ApiSettings.API_ENDPOINT; - this.auth = auth; serverRequests = new ArrayList<>(); /* TODO: somehow fix it so people using the deprecated functions will still work, while not calling this deprecated stuff ourselves */ @@ -130,7 +126,8 @@ public void sendServerRequests(ServerRequest... serverRequests) throws RemoteSer } if (responseEnvelop.getStatusCode() == 102) { - throw new LoginFailedException(); + throw new LoginFailedException(String.format("Error %s in API Url %s", + responseEnvelop.getApiUrl(), responseEnvelop.getError())); } else if (responseEnvelop.getStatusCode() == 53) { // 53 means that the api_endpoint was not correctly set, should be at this point, though, so redo the request sendServerRequests(serverRequests); @@ -177,7 +174,7 @@ public void sendServerRequests() throws RemoteServerException, LoginFailedExcept try { request.writeTo(stream); } catch (IOException e) { - Log.wtf(TAG, "Failed to write request to bytearray ouput stream. This should never happen", e); + Log.wtf(TAG, "Failed to write request to bytearray output stream. This should never happen", e); } RequestBody body = RequestBody.create(null, stream.toByteArray()); @@ -193,7 +190,7 @@ public void sendServerRequests() throws RemoteServerException, LoginFailedExcept } if (response.code() != 200) { - throw new RemoteServerException("Got a unexcepted http code : " + response.code()); + throw new RemoteServerException("Got a unexpected http code : " + response.code()); } ResponseEnvelopeOuterClass.ResponseEnvelope responseEnvelop = null; @@ -236,14 +233,15 @@ public void sendServerRequests() throws RemoteServerException, LoginFailedExcept } @Deprecated - private void resetBuilder() { + private void resetBuilder() throws LoginFailedException, RemoteServerException { builder = RequestEnvelopeOuterClass.RequestEnvelope.newBuilder(); resetBuilder(builder); hasRequests = false; serverRequests.clear(); } - private void resetBuilder(RequestEnvelopeOuterClass.RequestEnvelope.Builder builder) { + private void resetBuilder(RequestEnvelopeOuterClass.RequestEnvelope.Builder builder) + throws LoginFailedException, RemoteServerException { builder.setStatusCode(2); builder.setRequestId(8145806132888207460L); if (lastAuth != null @@ -252,7 +250,7 @@ private void resetBuilder(RequestEnvelopeOuterClass.RequestEnvelope.Builder buil builder.setAuthTicket(lastAuth); } else { Log.d(TAG, "Authenticated with static token"); - builder.setAuthInfo(auth); + builder.setAuthInfo(api.getAuthInfo()); } builder.setUnknown12(989); builder.setLatitude(api.getLatitude()); @@ -273,11 +271,6 @@ public RequestEnvelopeOuterClass.RequestEnvelope build() { return builder.build(); } - public void setAuthInfo(AuthInfo auth) { - this.auth = auth; - this.lastAuth = null; - } - public void setLatitude(double latitude) { builder.setLatitude(latitude); } diff --git a/src/main/java/com/pokegoapi/util/Log.java b/src/main/java/com/pokegoapi/util/Log.java index 1b84ea77..da64d88e 100644 --- a/src/main/java/com/pokegoapi/util/Log.java +++ b/src/main/java/com/pokegoapi/util/Log.java @@ -95,7 +95,7 @@ public static void wtf(String tag, String msg, Throwable tr) { getInstance().wtf(tag, msg, tr); } - enum Level { + public enum Level { VERBOSE(2), DEBUG(3), diff --git a/src/resources/protobuf b/src/resources/protobuf index eeccbb12..8e0fac2d 160000 --- a/src/resources/protobuf +++ b/src/resources/protobuf @@ -1 +1 @@ -Subproject commit eeccbb121b126aa51fc4eebae8d2f23d013e1cb8 +Subproject commit 8e0fac2d685fbc635886e9091039b245bb86511c