Skip to content

Commit

Permalink
Release v1.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
vinnymac committed Jan 4, 2017
2 parents 03c318d + 4cc35e1 commit eadb6ee
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 45 deletions.
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

**PokéNurse** is a desktop application for Windows and Mac that allows you to manage your pokémon from Pokémon Go without the need for a mobile device. You can now favorite, transfer, and evolve from the comfort of your own home!

## Downloads for v1.8.0
## Downloads for v1.9.0
You may view all the releases [here](https://github.com/vinnymac/PokeNurse/releases)
* [macOS](https://github.com/vinnymac/PokeNurse/releases/download/v1.8.0/PokeNurse.dmg)
* [Windows](https://github.com/vinnymac/PokeNurse/releases/download/v1.8.0/PokeNurse.exe)
* [Linux 32 bit](https://github.com/vinnymac/PokeNurse/releases/download/v1.8.0/PokeNurse-ia32.deb)
* [Linux 64 bit](https://github.com/vinnymac/PokeNurse/releases/download/v1.8.0/PokeNurse-x64.deb)
* [macOS](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse.dmg)
* [Windows](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse.exe)
* [Linux 32 bit](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse-ia32.deb)
* [Linux 64 bit](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse-x64.deb)

## Examples
![Login Window](app/loginExample.png)
Expand All @@ -23,14 +23,28 @@ You may view all the releases [here](https://github.com/vinnymac/PokeNurse/relea
This project uses [Electron](http://electron.atom.io/) and [Node.js](https://nodejs.org/en/). Criticism is welcome and encouraged.

## Features
* List Pokemon
* List and Sort Pokemon
* Pokedex Number
* Name
* CP
* IV
* Transfer Pokemon
* Evolve Pokemon
* Favorite/Unfavorite Pokemon
* PowerUp Pokemon
* Details - Evolutions, DPS, Energy, Moves, and more
* Renaming & Templated Renaming

## Templated Renaming
When renaming, it will automatically convert a name like `Bulba-[HP]` into `Bulba-140`.
`[IV]` represents the IV percent of that pokemon: 40
`[VI]` represents 100 minus the IV: 60
`[ATT]`, `[DEF]`, `[STA]` represent attack, defense, and stamina, they will appear like: ⑨
`[FAST]` is the damage of the quick move: 8
`[CHARGE]` is the damage of the cinematic move: 40
`[ENERGY]` is the amount of cinematic moves you can use before your energy runs out: ②
`[HP]` is the max stamina: 140
Note: Only 12 characters can be used to rename a pokemon.

## Contributing
All future pull request should be made to the **develop** branch.
Expand Down
34 changes: 21 additions & 13 deletions app/actions/trainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,19 @@ function generateEmptySpecies(candies, pokemonSettings) {
})
}

// TODO Can we find these constants in POGOBuf or item templates?
const MILLISECONDS_FACTOR = 1000
const MOVE2_CHARGE_DELAY_MS = 500
const STAB_MULTIPLIER = 1.25 // 25% damage boost

function dpsForMove(move, primary) {
function dpsForMove(hasStab, move, primary) {
const moveDelay = primary ? 0 : MOVE2_CHARGE_DELAY_MS
const dps = move.power / (move.duration_ms + moveDelay) * MILLISECONDS_FACTOR
let dps = move.power / (move.duration_ms + moveDelay) * MILLISECONDS_FACTOR

// TODO optional STAB
// const STAB_MULTIPLIER = 1.25
// if (hasStab) {
// dps = dps * STAB_MULTIPLIER
// }
if (hasStab) {
dps *= STAB_MULTIPLIER
}

return dps
}
Expand All @@ -77,12 +78,14 @@ function egpsForMove(move, primary) {
}

// List of all POGOProtos.Enums.PokemonMove
function getMove(moveSettings, move, primary) {
// types - array of up to two pokemon types ['fire', 'water']
// moveSettings - object holding move meta
// move - id for move
// primary - first or second move
function getMove(types, moveSettings, move, primary) {
const moveSetting = Object.assign({}, moveSettings[move])

moveSetting.dps = dpsForMove(moveSetting, primary)
moveSetting.energy_gain = moveSetting.energy_delta
moveSetting.egps = egpsForMove(moveSetting, primary)
moveSetting.dodge_window_ms = moveSetting.damage_window_end_ms - moveSetting.damage_window_start_ms

moveSetting.energy_cost = moveSetting.energy_delta * -1
Expand All @@ -91,6 +94,11 @@ function getMove(moveSettings, move, primary) {

moveSetting.type = utils.getType(moveSetting.pokemon_type)

const hasStab = types.includes(moveSetting.type)
moveSetting.dps = dpsForMove(hasStab, moveSetting, primary)

moveSetting.egps = egpsForMove(moveSetting, primary)

return moveSetting
}

Expand Down Expand Up @@ -151,13 +159,13 @@ function parseInventory(inventory) {
.map(utils.getName)
.join('/')

const quickMoves = pokemonSetting.quick_moves.map(m => getMove(moveSettings, m, true))
const quickMoves = pokemonSetting.quick_moves.map(m => getMove(type, moveSettings, m, true))

const cinematicMoves = pokemonSetting.cinematic_moves.map(m => getMove(moveSettings, m, false))
const cinematicMoves = pokemonSetting.cinematic_moves.map(m => getMove(type, moveSettings, m, false))

const move1 = getMove(moveSettings, p.move_1, true)
const move1 = getMove(type, moveSettings, p.move_1, true)

const move2 = getMove(moveSettings, p.move_2, false)
const move2 = getMove(type, moveSettings, p.move_2, false)

// TODO Use CamelCase instead of under_score for all keys except responses
const pokemonWithStats = {
Expand Down
4 changes: 2 additions & 2 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "PokeNurse",
"productName": "PokeNurse",
"version": "1.8.0",
"version": "1.9.0",
"description": "A tool for Pokémon Go to aid in transferring and evolving Pokémon",
"main": "./main.js",
"author": {
Expand All @@ -14,6 +14,6 @@
"async-file": "^2.0.2",
"electron-localshortcut": "^1.0.0",
"node-pogo-protos": "2.4.0",
"pogobuf": "1.8.0"
"pogobuf": "1.9.0"
}
}
2 changes: 1 addition & 1 deletion app/reducers/trainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export default handleActions({

POWER_UP_POKEMON_SUCCESS(state, action) {
const pokemon = action.payload
const message = `Upgraded ${pokemon.nickname} succesfully!`
const message = `Upgraded ${pokemon.nickname} successfully!`
const title = `Power Up ${pokemon.nickname}`
ipcRenderer.send('information-dialog', message, title)

Expand Down
2 changes: 2 additions & 0 deletions app/screens/Detail/components/CinematicMove.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const CinematicMove = React.createClass({
const chargedMoveTip = (<span>
{`Duration: ${move.duration_ms}ms`}
<br />
{`DPS: ${move.dps.toFixed(2)}`}
<br />
{`Dodge Window: ${move.dodge_window_ms}ms`}
<br />
{`Crit Chance: ${critChance.toFixed(2)}%`}
Expand Down
24 changes: 14 additions & 10 deletions app/screens/Detail/components/ModalBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,6 @@ const ModalBody = React.createClass({
<div className="pokemon-info-item-title">Height</div>
</div>
</div>
<div className="pokemon_info">
<div className="pokemon-info-item split-2-way">
<div className="pokemon-info-item-text combat-stat">{`${attack}`}</div>
<div className="pokemon-info-item-title">Attack</div>
</div>
<div className="pokemon-info-item split-2-way">
<div className="pokemon-info-item-text combat-stat">{`${defense}`}</div>
<div className="pokemon-info-item-title">Defense</div>
</div>
</div>
<div className="pokemon_info">
<div className="pokemon-info-item split-2-way">
<div className="pokemon-info-item-text cp-upgrade">{cpPerUpgrade}</div>
Expand All @@ -132,6 +122,20 @@ const ModalBody = React.createClass({
<div className="pokemon-info-item-title">{`${name} Candies`}</div>
</div>
</div>
<div className="pokemon_info">
<div className="pokemon-info-item split-3-way">
<div className="pokemon-info-item-text combat-stat">{`${attack}`}</div>
<div className="pokemon-info-item-title">Attack</div>
</div>
<div className="pokemon-info-item split-3-way">
<div className="pokemon-info-item-text combat-stat">{`${defense}`}</div>
<div className="pokemon-info-item-title">Defense</div>
</div>
<div className="pokemon-info-item split-3-way">
<div className="pokemon-info-item-text combat-stat">{`${pokemon.iv}%`}</div>
<div className="pokemon-info-item-title">IV</div>
</div>
</div>
<div className="pokemon_move_info">
<div className="pokemon-move-item-title">Quick Moves</div>
{quickMoves}
Expand Down
41 changes: 39 additions & 2 deletions app/screens/Detail/components/Nickname.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import {
ipcRenderer,
} from 'electron'
import React, {
PropTypes
} from 'react'
Expand All @@ -6,6 +9,12 @@ import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { renamePokemon } from '../../../actions'

function getNumberInCircle(num) {
if (num === 0) return String.fromCharCode(9450)
if (num < 21) return String.fromCharCode(9311 + num)
return `${num}`
}

const Nickname = React.createClass({
propTypes: {
pokemon: PropTypes.object.isRequired,
Expand Down Expand Up @@ -42,7 +51,6 @@ const Nickname = React.createClass({
className="input-lg"
onKeyPress={this.handleKeyPress}
defaultValue={newNickname}
maxLength="12"
placeholder="Enter a new nickname"
ref={(c) => { this.input = c }}
/>
Expand Down Expand Up @@ -70,8 +78,37 @@ const Nickname = React.createClass({
},

handleKeyPress(e) {
const {
pokemon,
} = this.props

if (e.key === 'Enter') {
this.props.renamePokemon(this.props.pokemon, e.target.value, (updatedPokemon) => {
let newName = e.target.value

const totalEnergy = parseInt(Math.floor(100 / pokemon.move_2.energy_cost), 10)
const energy = getNumberInCircle(totalEnergy)
const vi = (100 - pokemon.iv).toFixed(0)
const attack = getNumberInCircle(pokemon.attack)
const defense = getNumberInCircle(pokemon.defense)
const stamina = getNumberInCircle(pokemon.stamina)

newName = newName
.replace('[IV]', pokemon.iv.toFixed(0))
.replace('[VI]', vi)
.replace('[ATT]', attack)
.replace('[DEF]', defense)
.replace('[STA]', stamina)
.replace('[FAST]', pokemon.move_1.power.toFixed(0))
.replace('[CHARGE]', pokemon.move_2.power.toFixed(0))
.replace('[ENERGY]', energy)
.replace('[HP]', pokemon.stamina_max)

if (newName.length > 12) {
ipcRenderer.send('error-message', 'The name must contain 12 characters or less.')
return
}

this.props.renamePokemon(pokemon, newName, (updatedPokemon) => {
this.handleRenameComplete(updatedPokemon)
})
}
Expand Down
2 changes: 1 addition & 1 deletion app/screens/Detail/components/QuickMove.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const QuickMove = React.createClass({
<br />
{`Damage Window: ${move.damage_window_end_ms}ms`}
<br />
No STAB DPS: ${move.dps.toFixed(2)}
{`DPS: ${move.dps.toFixed(2)}`}
<br />
{`Energy Gain: ${move.energy_gain}`}
<br />
Expand Down
20 changes: 17 additions & 3 deletions app/screens/Table/components/Pokemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import Tooltip from '../../Tooltip'
const favoriteGlyph = 'fa fa-star favorite-yellow'
const emptyFavoriteGlyph = 'fa fa-star-o'

function hasMaxCP(pokemon) {
return pokemon.cp.toFixed(0) === pokemon.max_cp.toFixed(0)
}

const Pokemon = React.createClass({

displayName: 'PokemonTable',
Expand Down Expand Up @@ -140,7 +144,7 @@ const Pokemon = React.createClass({
return species.pokemon.map((pokemon) => {
const favorite = pokemon.favorite ? favoriteGlyph : emptyFavoriteGlyph
const pokeiv = `${pokemon.iv}% (${pokemon.attack}/${pokemon.defense}/${pokemon.stamina})`
const powerUpTip = this.getPowerUpTip(pokemon)
const powerUpTip = this.getPowerUpTip(pokemon, species)
const cpTip = `Max CP: ${pokemon.max_cp}`
const ivTip = (<span>
{`Attack: ${pokemon.attack}`}
Expand Down Expand Up @@ -223,7 +227,7 @@ const Pokemon = React.createClass({
},

getPowerUpTip(pokemon) {
if (pokemon.cp === pokemon.max_cp) {
if (hasMaxCP(pokemon)) {
return `Max CP ${pokemon.max_cp}`
}

Expand All @@ -240,7 +244,17 @@ const Pokemon = React.createClass({
</span>)
},

handleClickPowerup(pokemon) {
handleClickPowerup(pokemon, species) {
if (hasMaxCP(pokemon)) {
ipcRenderer.send('error-message', 'Sorry, you have reached the Max CP!')
return
}

if (species.candy < 1) {
ipcRenderer.send('error-message', `Sorry, you have ${species.candy} candy left!`)
return
}

if (ipcRenderer.sendSync('confirmation-dialog', 'power up').success) {
// TODO Calculate and update the pokemon immediately with estimates
this.props.powerUpPokemon(pokemon)
Expand Down
5 changes: 0 additions & 5 deletions app/screens/Table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ import React, {
import {
ipcRenderer
} from 'electron'
import {
InputGroup,
FormControl,
Button,
} from 'react-bootstrap'
import $ from 'jquery'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "PokeNurse",
"version": "1.8.0",
"version": "1.9.0",
"description": "A tool for Pokémon Go to aid in transferring and evolving Pokémon",
"main": "main.js",
"scripts": {
Expand Down Expand Up @@ -139,7 +139,7 @@
"electron-localshortcut": "^1.0.0",
"font-awesome": "^4.7.0",
"node-pogo-protos": "2.4.0",
"pogobuf": "1.8.0",
"pogobuf": "1.9.0",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-redux": "5.0.1",
Expand Down

0 comments on commit eadb6ee

Please sign in to comment.