diff --git a/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java b/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java index b8ad31c6..8b9cd3d4 100644 --- a/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java +++ b/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java @@ -27,6 +27,7 @@ import com.pokemonshowdown.data.CommunityLoungeData; import com.pokemonshowdown.data.MyApplication; import com.pokemonshowdown.data.Onboarding; +import com.pokemonshowdown.replays.ReplayFragment; import org.json.JSONException; import org.json.JSONObject; @@ -189,7 +190,7 @@ public void run() { return true; case R.id.menu_settings: new AlertDialog.Builder(this) - .setMessage(R.string.teaser_alert) + .setMessage(R.string.still_in_development) .create() .show(); return true; @@ -230,6 +231,10 @@ private void selectItem(int position) { mPosition = 1; fragment = CommunityLoungeFragment.newInstance(); break; + case 2: + mPosition = 2; + fragment = ReplayFragment.newInstance(); + break; case 3: mPosition = 3; fragment = CreditsFragment.newInstance(); @@ -237,6 +242,7 @@ private void selectItem(int position) { default: mPosition = 2; fragment = new PlaceHolderFragment(); + break; } FragmentManager fm = getSupportFragmentManager(); @@ -351,6 +357,22 @@ public void run() { mDialog.show(); } }); + return; + case MyApplication.EXTRA_UNKNOWN_ERROR: + runOnUiThread(new Runnable() { + @Override + public void run() { + if (mDialog != null && mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = new AlertDialog.Builder(BattleFieldActivity.this) + .setMessage("An unknown error was caught. " + + "You can copy current roomId to clipboard; if anything funny happens," + + " finish the battle in your device's browser.") + .create(); + mDialog.show(); + } + }); } } diff --git a/app/src/main/java/com/pokemonshowdown/app/BattleFieldFragment.java b/app/src/main/java/com/pokemonshowdown/app/BattleFieldFragment.java index 9df21f84..52b31fbc 100644 --- a/app/src/main/java/com/pokemonshowdown/app/BattleFieldFragment.java +++ b/app/src/main/java/com/pokemonshowdown/app/BattleFieldFragment.java @@ -93,6 +93,7 @@ public void onDetach() { super.onDetach(); getActivity().getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); getActivity().getActionBar().removeAllTabs(); + BattleFieldData.get(getActivity()).leaveAllRooms(); } @Override @@ -103,7 +104,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - final String roomId = getCurrentRoomId(); + final String roomId = "http://play.pokemonshowdown.com/" + getCurrentRoomId(); new AlertDialog.Builder(getActivity()) .setTitle(R.string.bar_room_id) .setMessage(roomId) @@ -290,6 +291,14 @@ public void processNewRoomRequest(String roomId) { fragment.cancelSearchingButton(); } } + + if (mRoomList.size() > 2) { + new AlertDialog.Builder(getActivity()) + .setMessage("This app does not handle concurrent battles well =.= " + + "Not just yet =.= Don't close any window, finish all battles and reset the app") + .create() + .show(); + } } public void generateAvailableWatchBattleDialog() { diff --git a/app/src/main/java/com/pokemonshowdown/app/BattleFragment.java b/app/src/main/java/com/pokemonshowdown/app/BattleFragment.java index 765f5909..a4fee145 100644 --- a/app/src/main/java/com/pokemonshowdown/app/BattleFragment.java +++ b/app/src/main/java/com/pokemonshowdown/app/BattleFragment.java @@ -267,6 +267,7 @@ public void onResume() { @Override public void onPause() { super.onPause(); + Log.d(BTAG, "onPause"); BattleFieldData.RoomData roomData = BattleFieldData.get(getActivity()).getAnimationInstance(mRoomId); if (roomData != null) { roomData.setMessageListener(true); @@ -1248,12 +1249,14 @@ public void displayPokemon(String tag) { getView().findViewById(getSpriteId(tag)).setAlpha(1f); if (!isBatonPass()) { ((LinearLayout) getView().findViewById(getTempStatusId(tag))).removeAllViews(); - } else { - getView().findViewById(getSpriteId(tag)).setAlpha(0.2f); } ImageView sub = (ImageView) relativeLayout.findViewWithTag("Substitute"); - if (sub != null && !isBatonPass()) { - relativeLayout.removeView(sub); + if (sub != null) { + if (!isBatonPass()) { + relativeLayout.removeView(sub); + } else { + getView().findViewById(getSpriteId(tag)).setAlpha(0.2f); + } } setBatonPass(false); } catch (NullPointerException e) { @@ -2044,7 +2047,7 @@ public void onAnimationStart(Animator animation) { layoutParams.addRule(RelativeLayout.ALIGN_LEFT, getSpriteId(tag)); layoutParams.setMargins((int) (imageView.getWidth() * 0.25f), (int) (imageView.getHeight() * 0.5f), 0, 0); relativeLayout.addView(flyingMessage, layoutParams); - } catch (NullPointerException e) { + } catch (Exception e) { } } @@ -2054,7 +2057,7 @@ public void onAnimationEnd(Animator animation) { try { RelativeLayout relativeLayout = (RelativeLayout) getView().findViewById(getPkmLayoutId(tag)); relativeLayout.removeView(flyingMessage); - } catch (NullPointerException e) { + } catch (Exception e) { } } diff --git a/app/src/main/java/com/pokemonshowdown/app/DmgCalcActivity.java b/app/src/main/java/com/pokemonshowdown/app/DmgCalcActivity.java index 66e70ddb..5b5fdd70 100644 --- a/app/src/main/java/com/pokemonshowdown/app/DmgCalcActivity.java +++ b/app/src/main/java/com/pokemonshowdown/app/DmgCalcActivity.java @@ -12,7 +12,9 @@ import android.widget.TextView; import com.pokemonshowdown.data.FieldFragment; +import com.pokemonshowdown.data.ItemDex; import com.pokemonshowdown.data.MoveDex; +import com.pokemonshowdown.data.Pokedex; import com.pokemonshowdown.data.Pokemon; import com.pokemonshowdown.data.SearchableActivity; @@ -28,7 +30,7 @@ import java.util.List; import java.util.Map; -public class DmgCalcActivity extends FragmentActivity { +public class DmgCalcActivity extends FragmentActivity implements FieldFragment.FieldConditionsListener { public final static String DTAG = DmgCalcActivity.class.getName(); public final static int REQUEST_CODE_FIND_ATTACKER = 0; public final static int REQUEST_CODE_FIND_DEFENDER = 1; @@ -37,7 +39,7 @@ public class DmgCalcActivity extends FragmentActivity { public final static int REQUEST_CODE_GET_MOVE_3 = 4; public final static int REQUEST_CODE_GET_MOVE_4 = 5; - private final DecimalFormat DAMAGE_FORMAT = new DecimalFormat("#0.0%"); + private final static DecimalFormat DAMAGE_FORMAT = new DecimalFormat("#0.0%"); private Pokemon mAttacker; private Pokemon mDefender; @@ -59,6 +61,8 @@ public class DmgCalcActivity extends FragmentActivity { private int mSpikesCount = 0; private Weather mActiveWeather = Weather.NO_WEATHER; + private FieldFragment mFieldFragment; + public enum FieldConditions { SINGLES, DOUBLES, STEALTH_ROCK, ZERO_SPIKES, ONE_SPIKES, TWO_SPIKES, THREE_SPIKES, REFLECT, LIGHT_SCREEN, FORESIGHT, HELPING_HAND, NO_WEATHER, SUN, RAIN, SAND, HAIL, GRAVITY; } @@ -78,13 +82,13 @@ public void onCreate(Bundle savedInstanceState) { getActionBar().setTitle(R.string.bar_dmg_calc); getActionBar().setDisplayHomeAsUpEnabled(true); - FieldFragment fieldFragment = new DmgCalcFieldXYFragment(); - fieldFragment.setFieldConditionsListener(new DefaultFieldConditionsListener()); + mFieldFragment = new DmgCalcFieldXYFragment(); + mFieldFragment.setFieldConditionsListener(this); Bundle fieldBundle = new Bundle(); - fieldFragment.setArguments(fieldBundle); + mFieldFragment.setArguments(fieldBundle); FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() - .replace(R.id.dmgcalc_field_container, fieldFragment) + .replace(R.id.dmgcalc_field_container, mFieldFragment) .commit(); ImageView switchButton = (ImageView) findViewById(R.id.dmgcalc_switch); @@ -287,6 +291,8 @@ private void loadPokemon(Pokemon pokemon, int searchCode) { bundle.putBoolean(PokemonFragment.SEARCH, true); bundle.putInt(PokemonFragment.SEARCH_CODE, searchCode); bundle.putBoolean(PokemonFragment.STAGES, true); + bundle.putBoolean(PokemonFragment.HEALTH, true); + bundle.putBoolean(PokemonFragment.ITEMS, true); fragment.setArguments(bundle); FragmentManager fragmentManager = getSupportFragmentManager(); fragment.show(fragmentManager, PokemonFragment.PTAG); @@ -341,13 +347,19 @@ private void calculateDamage(int moveIndex) { int maxHitsTilKo = minDamage == 0 ? 0 : (int) Math.ceil((double) defenderHP / (minDamage + damagePerRound)); int minHitsTilKo = maxDamage == 0 ? 0 : (int) Math.ceil((double) defenderHP / (maxDamage + damagePerRound)); - String damageText; + String damageText = null; if (minDamage == maxDamage && minDamage == 0) { damageText = String.format("--"); - } else if (minDamageText.equals(maxDamageText)) { + } else if (minDamageText.equals(maxDamageText) && minHitsTilKo > 0) { damageText = getResources().getString(R.string.dmg_is_same, minDamageText, minHitsTilKo); - } else if (maxHitsTilKo == minHitsTilKo) { + } else if (minDamageText.equals(maxDamageText)) { + getResources().getString(R.string.dmg_is_same_outhealed, minDamageText); + } else if (maxHitsTilKo == minHitsTilKo && minHitsTilKo > 0) { damageText = getResources().getString(R.string.dmg_not_same_same_ko, minDamageText, maxDamageText, minHitsTilKo); + } else if (minHitsTilKo > 0 && maxHitsTilKo <= 0) { + damageText = getResources().getString(R.string.dmg_not_same_not_same__maybe_outhealed, minDamageText, maxDamageText, minHitsTilKo); + } else if (minHitsTilKo <= 0 && maxHitsTilKo <= 0) { + damageText = getResources().getString(R.string.dmg_not_same_not_same_outhealed, minDamageText, maxDamageText); } else { damageText = getResources().getString(R.string.dmg_not_same_not_same_ko, minDamageText, maxDamageText, minHitsTilKo, maxHitsTilKo); } @@ -366,12 +378,13 @@ private void calculateDamage(int moveIndex) { ((TextView) findViewById(R.id.move4_result)).setText(damageText); break; } + } private int calculateDefendersInitialHP() { - int baseHP = getDefender().calculateHP(); - int calculatedHP = baseHP; - List typing = Arrays.asList(getDefender().getType()); + int baseHP = "Shedinja".equals(getDefender().getName()) ? 1 : getDefender().calculateHP(); + int calculatedHP = getDefender().getHP(); + List typing = Arrays.asList(getRealTyping(getDefender())); if (mStealthRocksActive && !getDefender().getAbility().equals("Magic Guard")) { calculatedHP -= baseHP * (0.125 * calculateWeaknessModifier("stealthrock", "Rock")); @@ -384,18 +397,22 @@ private int calculateDefendersInitialHP() { return calculatedHP; } + private double getHPFraction(Pokemon pokemon) { + return pokemon.getHP() / (double) pokemon.calculateHP(); + } + private int calculateDefendersDamagePerRound() { int baseHP = getDefender().calculateHP(); int damagePerRound = 0; String defenderAbility = getDefender().getAbility(); - List defenderTypes = Arrays.asList(getDefender().getType()); + List defenderTypes = Arrays.asList(getRealTyping(getDefender())); // Weather damage if ((defenderAbility.equals("Solar Power") || defenderAbility.equals("Dry Skin")) && mActiveWeather == Weather.SUN) { damagePerRound += (baseHP * 0.125); } - if (!defenderAbility.equals("Overcoat") && !defenderAbility.equals("Magic Guard")) { + if (!defenderAbility.equals("Overcoat") && !defenderAbility.equals("Magic Guard") && !getDefender().getItem().equals("safetygoggles")) { if (mActiveWeather == Weather.SAND && !defenderAbility.equals("Sand Veil") && !defenderAbility.equals("Sand Rush") && !defenderAbility.equals("Sand Force") && !defenderTypes.contains("Rock") && !defenderTypes.contains("Steel") && !defenderTypes.contains("Ground")) { damagePerRound += (baseHP / 16); } else if (mActiveWeather == Weather.HAIL && !defenderAbility.equals("Ice Body") && !defenderAbility.equals("Snow Cloak") && !defenderTypes.contains("Ice")) { @@ -416,6 +433,15 @@ private int calculateDefendersDamagePerRound() { damagePerRound -= (baseHP / 16); } + //Items + if (getDefender().getItem().equals("leftovers")) { + damagePerRound -= (baseHP / 16); + } + + if (getDefender().getItem().equals("stickybarb") && !getDefender().getAbility().equals("Magic Guard")) { + damagePerRound += baseHP * (0.125); + } + return damagePerRound; } @@ -442,24 +468,6 @@ private int calculateDamageRoutine(int moveIndex, double luck, boolean crit) { basePower = moveJson.getString("basePower"); category = moveJson.getString("category"); targets = moveJson.getString("target"); - - if ("weatherball".equals(move)) { - switch (mActiveWeather) { - case HAIL: - type = "Ice"; - break; - case SAND: - type = "Rock"; - break; - case RAIN: - type = "Water"; - break; - case SUN: - type = "Fire"; - break; - } - } - hasSecondary = moveJson.optBoolean("secondary", true); } catch (JSONException | NullPointerException e) { @@ -481,10 +489,13 @@ private int calculateDamageRoutine(int moveIndex, double luck, boolean crit) { boolean usesAttack = "Physical".equals(category); boolean usesDefense = "Physical".equals(category) || "psyshock".equals(move) || "psystrike".equals(move) || "secretsword".equals(move); - double attack = "foulplay".equals(move) ? Math.round(getDefender().calculateAtk() * getAtkMultiplier()) : usesAttack ? Math.round(getAttacker().calculateAtk() * getAtkMultiplier()) : getAttacker().calculateSpAtk() * getSpecialAttackMultiplier(); - double defense = usesDefense ? getDefender().calculateDef() * getDefenseMultiplier() : getDefender().calculateSpDef() * getSpecialDefenseMultiplier(); + double attack = "foulplay".equals(move) ? Math.round(getDefender().calculateAtk() * getAttackMultiplier(getAttacker())) : usesAttack ? Math.round(getAttacker().calculateAtk() * getAttackMultiplier(getAttacker())) : getAttacker().calculateSpAtk() * getSpecialAttackMultiplier(getAttacker()); + double defense = usesDefense ? getDefender().calculateDef() * getDefenseMultiplier(getDefender()) : getDefender().calculateSpDef() * getSpecialDefenseMultiplier(getDefender()); double base = calculateBasePower(move, type, Double.parseDouble(basePower)); + String originalType = type; + type = modifyAttackType(move, type); + boolean isStab = Arrays.asList(getAttackerTypingAfterAbilities(type)).contains(type); List modifiers = new ArrayList<>(); @@ -494,69 +505,182 @@ private int calculateDamageRoutine(int moveIndex, double luck, boolean crit) { modifiers.add(calculateCritMultiplier(move, crit)); modifiers.add(mHelpingHandActive ? 1.5 : 1.0); modifiers.add(getSpreadMultiplicator(targets)); - modifyDamageWithAbility(modifiers, move, type, category, usesDefense, hasSecondary); - + modifyDamageWithAbility(modifiers, move, type, originalType, category, usesDefense, hasSecondary); + modifyDamageWithItem(modifiers, move, type, originalType, category); base = base == 0.0 ? 0 : Math.floor(((2 * getAttacker().getLevel() / 5 + 2) * attack * base / defense) / 50 + 2); return applyDamageModifiers(base, modifiers); } } } + private String modifyAttackType(String move, String type) { + String attackerAbility = getAttacker().getAbility(); + if ("naturalgift".equals(move)) { + JSONObject itemObject = ItemDex.get(this).getItemJsonObject(getAttacker().getItem()); + JSONObject naturalGiftObject = itemObject == null ? null : itemObject.optJSONObject("naturalGift"); + if (naturalGiftObject != null) { + type = naturalGiftObject.optString("type", type); + } + } else if ("weatherball".equals(move)) { + switch (mActiveWeather) { + case HAIL: + type = "Ice"; + break; + case SAND: + type = "Rock"; + break; + case RAIN: + type = "Water"; + break; + case SUN: + type = "Fire"; + break; + } + } else if (attackerAbility.equals("Aerilate") && type.equals("Normal")) { + type = "Flying"; + } else if (attackerAbility.equals("Refrigerate") && type.equals("Normal")) { + type = "Ice"; + } else if (attackerAbility.equals("Pixilate") && type.equals("Normal")) { + type = "Fairy"; + } else if (attackerAbility.equals("Normalize")) { + type = "Normal"; + } else if ("technoblast".equals(move)) { + JSONObject itemObject = ItemDex.get(this).getItemJsonObject(getAttacker().getItem()); + type = itemObject == null ? null : itemObject.optString("onDrive", type); + } else if ("judgement".equals(move)) { + JSONObject itemObject = ItemDex.get(this).getItemJsonObject(getAttacker().getItem()); + type = itemObject == null ? "Normal" : itemObject.optString("onPlate", "Normal"); + } + return type; + } + private int applyDamageModifiers(double base, List modifiers) { for (double modifier : modifiers) { - base = base % 1 > 0.5 ? Math.ceil(base * modifier) : Math.floor(base *modifier); + base = base % 1 > 0.5 ? Math.ceil(base * modifier) : Math.floor(base * modifier); } return (int) base; } - private double getAtkMultiplier() { + private double getAttackMultiplier(Pokemon pokemon) { double baseMultiplier = 1.0; - if (getAttacker().getAbility().equals("Huge Power") || getAttacker().getAbility().equals("Pure Power")) { + if (pokemon.getAbility().equals("Huge Power") || pokemon.getAbility().equals("Pure Power")) { baseMultiplier *= 2.0; } - if (getAttacker().getAbility().equals("Hustle")) { + if (pokemon.getAbility().equals("Hustle")) { baseMultiplier *= 1.5; } - if (getAttacker().getAbility().equals("Flower Gift") && mActiveWeather == Weather.SUN) { + if (pokemon.getAbility().equals("Flower Gift") && mActiveWeather == Weather.SUN) { + baseMultiplier *= 1.5; + } + + if ("Defeatist".equals(pokemon.getAbility())) { + baseMultiplier *= 0.5; + } + + if ("choiceband".equals(pokemon.getItem())) { + baseMultiplier *= 1.5; + } + + if ("Pikachu".equals(pokemon.getName()) && "lightball".equals(pokemon.getItem())) { + baseMultiplier *= 2.0; + } + + if (("Cubone".equals(pokemon.getName()) || "Marowak".equals(pokemon.getName())) && "thickclub".equals(pokemon.getItem())) { baseMultiplier *= 1.5; } return baseMultiplier; } - private double getSpecialDefenseMultiplier() { + private double getSpecialAttackMultiplier(Pokemon pokemon) { double baseMultiplier = 1.0; - if (getAttacker().getAbility().equals("Flower Gift") && mActiveWeather == Weather.SUN) { + if (mActiveWeather == Weather.SUN && pokemon.getAbility().equals("Solar Power")) { baseMultiplier *= 1.5; } - if (Arrays.asList(getDefender().getType()).contains("Rock")) { + if ("Defeatist".equals(pokemon.getAbility())) { + baseMultiplier *= 0.5; + } + + if ("choicespecs".equals(pokemon.getItem())) { + baseMultiplier *= 1.5; + } + + if ("Clamperl".equals(pokemon.getName()) && "deepseatooth".equals(pokemon.getItem())) { + baseMultiplier *= 2.0; + } + + if ("Pikachu".equals(pokemon.getName()) && "lightball".equals(pokemon.getItem())) { + baseMultiplier *= 2.0; + } + + if (("Latios".equals(pokemon.getName()) || "Latias".equals(pokemon.getName())) && "souldew".equals(pokemon.getItem())) { baseMultiplier *= 1.5; } return baseMultiplier; } - private double getDefenseMultiplier() { + private double getDefenseMultiplier(Pokemon pokemon) { double baseMultiplier = 1.0; + if ("eviolite".equals(pokemon.getItem()) && Pokedex.get(this).getPokemonJSONObject(pokemon.getName()).has("evos")) { + baseMultiplier *= 1.5; + } + return baseMultiplier; } - private double getSpecialAttackMultiplier() { + private double getSpecialDefenseMultiplier(Pokemon pokemon) { double baseMultiplier = 1.0; - if (mActiveWeather == Weather.SUN && getAttacker().getAbility().equals("Solar Power")) { + if (pokemon.getAbility().equals("Flower Gift") && mActiveWeather == Weather.SUN) { + baseMultiplier *= 1.5; + } + + if (Arrays.asList(pokemon.getType()).contains("Rock")) { + baseMultiplier *= 1.5; + } + + if ("assaultvest".equals(pokemon.getItem())) { + baseMultiplier *= 1.5; + } + + if ("Clamperl".equals(pokemon.getName()) && "deepseascale".equals(pokemon.getItem())) { + baseMultiplier *= 2.0; + } + + if (("Latios".equals(pokemon.getName()) || "Latias".equals(pokemon.getName())) && "souldew".equals(pokemon.getItem())) { + baseMultiplier *= 1.5; + } + + if ("eviolite".equals(pokemon.getItem()) && Pokedex.get(this).getPokemonJSONObject(pokemon.getName()).has("evos")) { baseMultiplier *= 1.5; } return baseMultiplier; } - private void modifyDamageWithAbility(List modifiers, String move, String type, String category, boolean usesDefense, boolean hasSecondary) { + private void modifyDamageWithItem(List modifiers, String move, String type, String originalType, String category) { + String attackerItem = getAttacker().getItem(); + + if ("lifeorb".equals(attackerItem)) { + modifiers.add(1.3); + } + + if ("muscleband".equals(attackerItem) && "Physical".equals(category)) { + modifiers.add(1.1); + } + + if ("wiseglasses".equals(attackerItem) && "Special".equals(category)) { + modifiers.add(1.1); + } + } + + private void modifyDamageWithAbility(List modifiers, String move, String type, String originalType, String category, boolean usesDefense, boolean hasSecondary) { List attackerTyping = Arrays.asList(getAttackerTypingAfterAbilities(type)); String attackerAbility = getAttacker().getAbility(); String defenderAbility = getDefender().getAbility(); @@ -574,6 +698,10 @@ private void modifyDamageWithAbility(List modifiers, String move, String modifiers.add(1.5); } + if (((attackerAbility.equals("Swarm") && type.equals("Bug")) || (attackerAbility.equals("Blaze") && type.equals("Fire")) || (attackerAbility.equals("Torrent") && type.equals("Water")) || (attackerAbility.equals("Overgrow") && type.equals("Grass"))) && getHPFraction(getAttacker()) <= 1 / 3.0) { + modifiers.add(1.5); + } + if (attackerAbility.equals("Iron Fist") && Arrays.asList(new String[]{"bulletpunch", "cometpunch", "dizzypunch", "drainpunch", "dynamicpunch", "firepunch", "focuspunch", "hammerarm", "icepunch", "machpunch", "megapunch", "meteormash", "poweruppunch", "shadowpunch", "skyuppercut", "thunderpunch"}).contains(move)) { modifiers.add(1.2); @@ -630,18 +758,18 @@ private void modifyDamageWithAbility(List modifiers, String move, String } if (attackerAbility.equals("Analytic")) { - modifiers.add(1.3); + modifiers.add(1.3); //TODO: Reimplement } - if (attackerAbility.equals("Aerilate") && type.equals("Normal")) { + if (attackerAbility.equals("Aerilate") && originalType.equals("Normal")) { modifiers.add(1.3); } - if (attackerAbility.equals("Refrigerate") && type.equals("Normal")) { + if (attackerAbility.equals("Refrigerate") && originalType.equals("Normal")) { modifiers.add(1.3); } - if (attackerAbility.equals("Pixilate") && type.equals("Normal")) { + if (attackerAbility.equals("Pixilate") && originalType.equals("Normal")) { modifiers.add(1.3); } @@ -649,7 +777,6 @@ private void modifyDamageWithAbility(List modifiers, String move, String modifiers.add(0.5); } - if (mActiveWeather == Weather.SAND && attackerAbility.equals("Sand Force") && Arrays.asList(new String[]{"Rock", "Ground", "Steel"}).contains(type)) { modifiers.add(1.3); } @@ -699,38 +826,33 @@ private double getSpreadMultiplicator(String targets) { return ("allAdjacentFoes".equals(targets) || "allAdjacent".equals(targets) || "all".equals(targets)) && !mIsSingles ? 0.75 : 1; } - private double calculateWeaknessModifier(String move, String type) { - double modifier = 1.0; - - String[] defenderTyping = getDefender().getType(); - String attackerAbility = getAttacker().getAbility(); - String defenderAbility = getDefender().getAbility(); - - if ("Forecast".equals(defenderAbility)) { + private String[] getRealTyping(Pokemon pokemon) { + String[] typing = pokemon.getType(); + if ("Forecast".equals(pokemon.getAbility())) { switch (mActiveWeather) { case RAIN: - defenderTyping = new String[]{"Water"}; + typing = new String[]{"Water"}; break; case SUN: - defenderTyping = new String[]{"Fire"}; + typing = new String[]{"Fire"}; break; case HAIL: - defenderTyping = new String[]{"Ice"}; + typing = new String[]{"Ice"}; break; } + } else if ("Multitype".equals(pokemon.getAbility()) && pokemon.getName().contains("Arceus")) { + JSONObject itemObject = ItemDex.get(this).getItemJsonObject(getAttacker().getItem()); + typing = itemObject == null ? new String[]{"Normal"} : new String[]{itemObject.optString("onPlate", "Normal")}; } + return typing; + } - if (!"weatherball".equals(move)) { - if (defenderAbility.equals("Aerilate") && type.equals("Normal")) { - type = "Flying"; - } else if (defenderAbility.equals("Refrigerate") && type.equals("Normal")) { - type = "Ice"; - } else if (defenderAbility.equals("Pixilate") && type.equals("Normal")) { - type = "Fairy"; - } else if (defenderAbility.equals("Normalize")) { - type = "Normal"; - } - } + private double calculateWeaknessModifier(String move, String type) { + double modifier = 1.0; + + String[] defenderTyping = getRealTyping(getDefender()); + String attackerAbility = getAttacker().getAbility(); + String defenderAbility = getDefender().getAbility(); for (String defType : defenderTyping) { if (mEffectivenessImmune.get(defType) != null && mEffectivenessImmune.get(defType).contains(type)) { @@ -738,6 +860,8 @@ private double calculateWeaknessModifier(String move, String type) { modifier = 1.0; } else if (defType.equals("Flying") && mGravityActive) { modifier = 1.0; + } else if ("ringtarget".equals(getDefender().getItem())) { + modifier = 1.0; } else { modifier = 0.0; } @@ -764,7 +888,7 @@ private double calculateWeaknessModifier(String move, String type) { type = backupType; } - if ("freezedry".equals(move) && Arrays.asList(getDefender().getType()).contains("Water")) { + if ("freezedry".equals(move) && Arrays.asList(defenderTyping).contains("Water")) { modifier *= 4; // as it should be resisted once } @@ -790,8 +914,14 @@ private double calculateWeaknessModifier(String move, String type) { modifier *= 0.5; } + if ("airballoon".equals(getDefender().getItem()) && "Ground".equals(type)) { + modifier *= 0; + } + if (attackerAbility.equals("Tinted Lens") && modifier < 1.0) { modifier *= 2.0; + } else if ("expertbelt".equals(getAttacker().getItem()) && modifier > 1.0) { + modifier *= 1.2; } return modifier; @@ -808,35 +938,64 @@ private double calculateBasePower(String move, String type, double bp) { bp = 150; break; case "punishment": - bp = Math.min(200, 20 * countDefendersStatStages() + 60); + bp = Math.min(200, 20 * countStatStages(getDefender(), true) + 60); + break; + case "storedpower": + bp = 20 + (20 * countStatStages(getAttacker(), true)); + break; + case "knockoff": + bp = getDefender().getItem().isEmpty() || getDefender().getItem() == null ? 65 : 97.5; break; case "fling": - bp = 130; - break; // TODO: Reimplement if items are supported + JSONObject obj = ItemDex.get(this).getItemJsonObject(getAttacker().getItem()); + JSONObject flingObject = obj == null ? null : obj.optJSONObject("fling"); + if (flingObject != null) { + bp = flingObject.optInt("basePower", 0); + } else { + bp = 0; + } + break; case "lowkick": case "grassknot": - double weight = getDefender().getWeight(); + double weight = calcuateWeight(getDefender()); bp = weight < 10.0 ? 20 : weight < 25.0 ? 40 : weight < 50.0 ? 60 : weight < 100.0 ? 80 : weight < 200.0 ? 100 : 120; break; + case "acrobatics": + bp = getAttacker().getItem() == null || getAttacker().getItem().isEmpty() || "flyinggem".equals(getAttacker().getItem()) ? 55 : 110; + break; case "reversal": case "flail": - bp = 200; // TODO: Reimplement if health modifiable + int mod = (int) (48 * getHPFraction(getAttacker())); + bp = mod <= 1 ? 200 : mod <= 4 ? 150 : mod <= 9 ? 100 : mod <= 16 ? 80 : mod <= 32 ? 40 : 20; break; case "heatcrash": case "heavyslam": - ratio = getDefender().getWeight() / getAttacker().getWeight(); + ratio = calcuateWeight(getDefender()) / calcuateWeight(getAttacker()); bp = ratio <= 0.2 ? 120 : ratio <= 0.25 ? 100 : ratio <= 1 / 3 ? 80 : ratio <= 0.5 ? 60 : 40; break; case "crushgrip": case "wringout": - bp = 121; // TODO: Reimplement once health modifiable + bp = 1 + (120 * getHPFraction(getDefender())); + break; + case "brine": + bp = getHPFraction(getDefender()) <= 0.5 ? 130 : 65; + break; + case "eruption": + case "waterspout": + bp = Math.max(1, 150 * getHPFraction(getAttacker())); break; case "frustration": case "return": bp = 102; break; case "naturalgift": - bp = 100;// TODO: Reimplement if items are supported + obj = ItemDex.get(this).getItemJsonObject(getAttacker().getItem()); + JSONObject naturalGiftObject = obj == null ? null : obj.optJSONObject("naturalGift"); + if (naturalGiftObject != null) { + bp = naturalGiftObject.optInt("basePower", 0); + } else { + bp = 0; + } break; case "gyroball": bp = 25.0 * getDefender().calculateSpd() / getAttacker().calculateSpd(); @@ -850,7 +1009,6 @@ private double calculateBasePower(String move, String type, double bp) { bp = 100; } break; - // TODO: Probably many other moves... } if (getAttacker().getAbility().equals("Technician") && bp <= 60) { @@ -867,20 +1025,85 @@ private double calculateBasePower(String move, String type, double bp) { bp *= 0.5; } + // Items + if (getAttacker().getName().equals("Dialga") && getAttacker().getItem().equals("adamantorb") && (type.equals("Dragon") || type.equals("Steel"))) { + bp *= 1.2; + } else if (getAttacker().getName().equals("Palkia") && getAttacker().getItem().equals("lustrousorb") && (type.equals("Dragon") || type.equals("Water"))) { + bp *= 1.2; + } else if ((getAttacker().getName().equals("Giratina") || getAttacker().getName().equals("Giratina-Origin")) && getAttacker().getItem().equals("griseousorb") && (type.equals("Dragon") || type.equals("Ghost"))) { + bp *= 1.2; + } + + if (Arrays.asList(new String[]{"dracoplate", "dragonfang"}).contains(getAttacker().getItem()) && "Dragon".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"earthplate", "softsand"}).contains(getAttacker().getItem()) && "Ground".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"fistplate", "blackbelt"}).contains(getAttacker().getItem()) && "Fighting".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"flameplate", "charcoal"}).contains(getAttacker().getItem()) && "Fire".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"icicleplate", "nevermeltice"}).contains(getAttacker().getItem()) && "Ice".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"insectplate", "silverpowder"}).contains(getAttacker().getItem()) && "Bug".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"ironplate", "metalcoat"}).contains(getAttacker().getItem()) && "Steel".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"meadowplate", "miracleseed", "roseincense"}).contains(getAttacker().getItem()) && "Grass".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"mindplate", "twistedspoon", "oddincense"}).contains(getAttacker().getItem()) && "Psychic".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"pixieplate"}).contains(getAttacker().getItem()) && "Fairy".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"dreadplate", "blackglasses"}).contains(getAttacker().getItem()) && "Dark".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"skyplate", "sharpbeak"}).contains(getAttacker().getItem()) && "Flying".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"splashplate", "mysticwater", "seaincense", "waveincense"}).contains(getAttacker().getItem()) && "Water".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"spookyplate", "spelltag"}).contains(getAttacker().getItem()) && "Ghost".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"stoneplate", "hardstone", "rockincense"}).contains(getAttacker().getItem()) && "Rock".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"toxicplate", "poisonbarb"}).contains(getAttacker().getItem()) && "Poison".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"zapplate", "magnet"}).contains(getAttacker().getItem()) && "Electric".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"silkscarf"}).contains(getAttacker().getItem()) && "Normal".equals(type)) { + bp *= 1.2; + } else if (Arrays.asList(new String[]{"polkadotbow"}).contains(getAttacker().getItem()) && "Normal".equals(type)) { + bp *= 1.125; + } else if (Arrays.asList(new String[]{"pinkbow"}).contains(getAttacker().getItem()) && "Normal".equals(type)) { + bp *= 1.1; + } + return bp; } - private int countDefendersStatStages() { + private int countStatStages(Pokemon pokemon, boolean positiveOnly) { int count = 0; - for(int change : getDefender().getStages()) { - if(change > 6) { - count += change-6; + for (int change : pokemon.getStages()) { + if (change > 6 || !positiveOnly) { + count += change - 6; } } - return count; } + private double calcuateWeight(Pokemon pokemon) { + double normalWeight = pokemon.getWeight(); + + if ("floatstone".equals(pokemon.getItem())) { + normalWeight *= 0.5; + } + + if ("Light Metal".equals(pokemon.getAbility())) { + normalWeight *= 0.5; + } else if ("Heavy Metal".equals(pokemon.getAbility())) { + normalWeight *= 2.0; + } + + return normalWeight; + } private void createIndexOfTypeModifiers() { // Normal Type @@ -1013,24 +1236,49 @@ private void setConditionStatus(FieldConditions conditions, boolean value) { } private String[] getAttackerTypingAfterAbilities(String moveType) { - return getAttacker().getAbility().equals("Protean") ? new String[]{moveType} : getAttacker().getType(); + return getAttacker().getAbility().equals("Protean") ? new String[]{moveType} : getRealTyping(getAttacker()); } public void updateDamage() { calculateAllMoves(); } - private class DefaultFieldConditionsListener implements FieldConditionsListener { - @Override - public void onFieldConditionChanged(FieldConditions conditions, boolean value) { - setConditionStatus(conditions, value); + @Override + public void onFieldConditionChanged(FieldConditions conditions, boolean value) { + setConditionStatus(conditions, value); + } + + + @Override + protected void onPause() { + super.onPause(); + if (mFieldFragment != null) { + mFieldFragment.removeListener(); } + } + @Override + protected void onResume() { + super.onResume(); + if (mFieldFragment != null) { + mFieldFragment.setFieldConditionsListener(this); + } } - public interface FieldConditionsListener { - public void onFieldConditionChanged(FieldConditions conditions, boolean value); + @Override + protected void onStop() { + super.onStop(); + if (mFieldFragment != null) { + mFieldFragment.removeListener(); + } } -} + @Override + protected void onRestart() { + super.onRestart(); + if (mFieldFragment != null) { + mFieldFragment.setFieldConditionsListener(this); + } + } +} diff --git a/app/src/main/java/com/pokemonshowdown/app/PokemonFragment.java b/app/src/main/java/com/pokemonshowdown/app/PokemonFragment.java index 4bb5d570..3752e2f4 100644 --- a/app/src/main/java/com/pokemonshowdown/app/PokemonFragment.java +++ b/app/src/main/java/com/pokemonshowdown/app/PokemonFragment.java @@ -1,5 +1,6 @@ package com.pokemonshowdown.app; +import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; @@ -14,11 +15,15 @@ import android.view.Window; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.SeekBar; import android.widget.TextView; +import com.pokemonshowdown.data.ItemDex; import com.pokemonshowdown.data.Pokemon; import com.pokemonshowdown.data.SearchableActivity; +import org.json.JSONObject; + import java.util.Arrays; import java.util.Set; @@ -30,6 +35,10 @@ public class PokemonFragment extends DialogFragment { public final static String SEARCH = "Search"; public final static String SEARCH_CODE = "Search Code"; public final static String STAGES = "Stages"; + public final static String ITEMS = "Items"; + public final static String HEALTH = "Health"; + + private TextView mPokemonItem; @Override public void onDismiss(DialogInterface dialog) { @@ -83,7 +92,7 @@ public void onClick(View v) { addSearchWidget(view); } - TextView pokemonStats = (TextView) view.findViewById(R.id.stats); + final TextView pokemonStats = (TextView) view.findViewById(R.id.stats); resetStatsString(); pokemonStats.setBackgroundResource(R.drawable.editable_frame); pokemonStats.setOnClickListener(new View.OnClickListener() { @@ -205,6 +214,57 @@ public void onClick(DialogInterface dialog, int which) { } }); + int initialHPFraction = (int) (100 * getPokemon().getHP() / (double) getPokemon().calculateHP()); + final TextView initialHPText = (TextView) view.findViewById(R.id.initial_hp_text); + initialHPText.setText(Integer.toString(initialHPFraction)); + + final SeekBar initialHP = (SeekBar) view.findViewById(R.id.initial_hp); + initialHP.setProgress(initialHPFraction); + initialHP.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mPokemon.setHP((int) Math.ceil(getPokemon().calculateHP() * (progress / 100.0))); + initialHPText.setText(Integer.toString(progress)); + pokemonStats.setText(getStatsString()); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + + mPokemonItem = (TextView) view.findViewById(R.id.pokemon_fragment_item); + String item = getPokemon().getItem(); + if (getPokemon().getItem() != null && !getPokemon().getItem().isEmpty()) { + JSONObject itemObject = ItemDex.get(getActivity()).getItemJsonObject(item); + if (itemObject != null) { + int itemDrawable = ItemDex.getItemIcon(getActivity(), item); + mPokemonItem.setCompoundDrawablesWithIntrinsicBounds(itemDrawable != 0 ? getResources().getDrawable(itemDrawable) : null, null, null, null); + item = itemObject.optString("name", item); + } + mPokemonItem.setText(item); + } else { + mPokemonItem.setText(getResources().getString(R.string.pokemon_nohelditem)); + } + + mPokemonItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity().getApplicationContext(), SearchableActivity.class); + intent.putExtra(SearchableActivity.SEARCH_TYPE, SearchableActivity.REQUEST_CODE_SEARCH_ITEM); + startActivityForResult(intent, SearchableActivity.REQUEST_CODE_SEARCH_ITEM); + } + }); + + mPokemonItem.setVisibility(getArguments().getBoolean(ITEMS) ? View.VISIBLE : View.GONE); + initialHP.setVisibility(getArguments().getBoolean(HEALTH) ? View.VISIBLE : View.GONE); + initialHPText.setVisibility(getArguments().getBoolean(HEALTH) ? View.VISIBLE : View.GONE); } private void addSearchWidget(View view) { @@ -231,7 +291,12 @@ public void setAbilityString(String ability) { } public String getStatsString() { - return ("HP " + Integer.toString(getPokemon().getHP()) + " / Atk " + Integer.toString(getPokemon().getAtk()) + " / Def " + Integer.toString(getPokemon().getDef()) + " / SpA " + Integer.toString(getPokemon().getSpAtk()) + " / SpD " + Integer.toString(getPokemon().getSpDef()) + " / Spe " + Integer.toString(getPokemon().getSpd())); + if (getArguments().getBoolean(STAGES) && getPokemon().calculateHP() != getPokemon().getHP()) { + return ("HP " + Integer.toString(getPokemon().getHP()) + " (" + getPokemon().calculateHP() + ")" + " / Atk " + Integer.toString(getPokemon().getBaseAtk()) + " / Def " + Integer.toString(getPokemon().getBaseDef()) + " / SpA " + Integer.toString(getPokemon().getBaseSpAtk()) + " / SpD " + Integer.toString(getPokemon().getBaseSpDef()) + " / Spe " + Integer.toString(getPokemon().getBaseSpd())); + } else { + return ("HP " + Integer.toString(getPokemon().getHP()) + " / Atk " + Integer.toString(getPokemon().getAtk()) + " / Def " + Integer.toString(getPokemon().getDef()) + " / SpA " + Integer.toString(getPokemon().getSpAtk()) + " / SpD " + Integer.toString(getPokemon().getSpDef()) + " / Spe " + Integer.toString(getPokemon().getSpd())); + + } } public void resetStatsString() { @@ -257,5 +322,21 @@ private void closeFragment() { getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); } - + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == Activity.RESULT_OK && requestCode == SearchableActivity.REQUEST_CODE_SEARCH_ITEM) { + String item = data.getExtras().getString("Search"); + getPokemon().setItem(item); + + if (mPokemonItem != null) { + JSONObject itemObject = ItemDex.get(getActivity()).getItemJsonObject(item); + if (itemObject != null) { + int itemDrawable = ItemDex.getItemIcon(getActivity(), item); + mPokemonItem.setCompoundDrawablesWithIntrinsicBounds(itemDrawable != 0 ? getResources().getDrawable(itemDrawable) : null, null, null, null); + item = itemObject.optString("name", item); + } + mPokemonItem.setText(item); + } + } + } } diff --git a/app/src/main/java/com/pokemonshowdown/app/TeamBuildingFragment.java b/app/src/main/java/com/pokemonshowdown/app/TeamBuildingFragment.java index 8731fdef..47be687c 100644 --- a/app/src/main/java/com/pokemonshowdown/app/TeamBuildingFragment.java +++ b/app/src/main/java/com/pokemonshowdown/app/TeamBuildingFragment.java @@ -149,6 +149,11 @@ public boolean onContextItemSelected(MenuItem item) { mPokemonListAdapter.notifyDataSetChanged(); // Notify parent activity that the mPokemonTeam changed (so to reprint in the drawer) ((TeamBuildingActivity) getActivity()).updateList(); + if (mPokemonTeam.isFull()) { + mFooterButton.setVisibility(View.GONE); + } else { + mFooterButton.setVisibility(View.VISIBLE); + } return true; case 2: @@ -335,6 +340,8 @@ public void onClick(View view) { move1PpTextView.setText(""); ImageView move1TypeImageView = (ImageView) convertView.findViewById(R.id.teambuilder_move1_type); move1TypeImageView.setImageDrawable(null); + TextView move1NameTextView = (TextView) convertView.findViewById(R.id.teambuilder_move1_name); + move1NameTextView.setText(""); } if (!pokemon.getMove2().equals("")) { @@ -360,6 +367,8 @@ public void onClick(View view) { move2PpTextView.setText(""); ImageView move2TypeImageView = (ImageView) convertView.findViewById(R.id.teambuilder_move2_type); move2TypeImageView.setImageDrawable(null); + TextView move2NameTextView = (TextView) convertView.findViewById(R.id.teambuilder_move2_name); + move2NameTextView.setText(""); } @@ -386,6 +395,8 @@ public void onClick(View view) { move3PpTextView.setText(""); ImageView move3TypeImageView = (ImageView) convertView.findViewById(R.id.teambuilder_move3_type); move3TypeImageView.setImageDrawable(null); + TextView move3NameTextView = (TextView) convertView.findViewById(R.id.teambuilder_move3_name); + move3NameTextView.setText(""); } if (!pokemon.getMove4().equals("")) { @@ -411,6 +422,8 @@ public void onClick(View view) { move4PpTextView.setText(""); ImageView move4TypeImageView = (ImageView) convertView.findViewById(R.id.teambuilder_move4_type); move4TypeImageView.setImageDrawable(null); + TextView move4NameTextView = (TextView) convertView.findViewById(R.id.teambuilder_move4_name); + move4NameTextView.setText(""); } diff --git a/app/src/main/java/com/pokemonshowdown/data/BattleFieldData.java b/app/src/main/java/com/pokemonshowdown/data/BattleFieldData.java index 705a8ca0..9aa1434f 100644 --- a/app/src/main/java/com/pokemonshowdown/data/BattleFieldData.java +++ b/app/src/main/java/com/pokemonshowdown/data/BattleFieldData.java @@ -215,11 +215,29 @@ public void leaveRoom(String roomId) { } public void leaveAllRooms() { - for (String roomId : mRoomList) { + ArrayList holder = new ArrayList<>(); + ArrayList roomList = getRoomList(); + for (String roomId : roomList) { + if (!roomId.equals("global")) { + holder.add(roomId); + } + } + for (String roomId : holder) { leaveRoom(roomId); } } + public Format getFormatUsingId(String formatNameId) { + for (FormatType formatType : mFormatTypes) { + for (Format format : formatType.getFormatList()) { + if(MyApplication.toId(format.getName()).equals(formatNameId)) { + return format; + } + } + } + return null; + } + public static class BattleLog { private String mRoomId; private CharSequence mChatBox; diff --git a/app/src/main/java/com/pokemonshowdown/data/FieldFragment.java b/app/src/main/java/com/pokemonshowdown/data/FieldFragment.java index 69fc1384..6008c3bf 100644 --- a/app/src/main/java/com/pokemonshowdown/data/FieldFragment.java +++ b/app/src/main/java/com/pokemonshowdown/data/FieldFragment.java @@ -10,15 +10,23 @@ */ public class FieldFragment extends Fragment { - private DmgCalcActivity.FieldConditionsListener mListener; + private FieldConditionsListener mListener; - public void setFieldConditionsListener(@Nullable DmgCalcActivity.FieldConditionsListener listener) { + public void setFieldConditionsListener(@Nullable FieldConditionsListener listener) { mListener = listener; } + public void removeListener() { + mListener = null; + } + protected void sendUpdateToListeners(DmgCalcActivity.FieldConditions fieldCondition, boolean value) { if(mListener != null) { mListener.onFieldConditionChanged(fieldCondition, value); } } + + public interface FieldConditionsListener { + public void onFieldConditionChanged(DmgCalcActivity.FieldConditions conditions, boolean value); + } } diff --git a/app/src/main/java/com/pokemonshowdown/data/ItemDex.java b/app/src/main/java/com/pokemonshowdown/data/ItemDex.java index f93d8660..50888fa5 100644 --- a/app/src/main/java/com/pokemonshowdown/data/ItemDex.java +++ b/app/src/main/java/com/pokemonshowdown/data/ItemDex.java @@ -59,7 +59,7 @@ public JSONObject getItemJsonObject(String name) { try { String item = mItemDexEntries.get(MyApplication.toId(name)); return new JSONObject(item); - } catch (JSONException e) { + } catch (NullPointerException | JSONException e) { return null; } } diff --git a/app/src/main/java/com/pokemonshowdown/data/MyApplication.java b/app/src/main/java/com/pokemonshowdown/data/MyApplication.java index 1217f66a..70fdf2b8 100644 --- a/app/src/main/java/com/pokemonshowdown/data/MyApplication.java +++ b/app/src/main/java/com/pokemonshowdown/data/MyApplication.java @@ -35,6 +35,7 @@ public class MyApplication extends Application { public final static String EXTRA_SERVER_MESSAGE = "New Server Message"; public final static String EXTRA_REQUIRE_SIGN_IN = "Require Sign In"; public final static String EXTRA_ERROR_MESSAGE = "Error Message"; + public final static String EXTRA_UNKNOWN_ERROR = "Unknown Error"; public final static String EXTRA_UPDATE_SEARCH = "Search Update"; public final static String EXTRA_CHANNEL = "Channel"; public final static String EXTRA_ROOMID = "RoomId"; @@ -70,25 +71,19 @@ public void onCreate() { mBattleFieldData = BattleFieldData.get(appContext); mCommunityLoungeData = CommunityLoungeData.get(appContext); mRoomCategoryList = new HashMap<>(); - } - @Override - public void onTerminate() { - mOnboarding.signingOut(); - mBattleFieldData.leaveAllRooms(); - mCommunityLoungeData.leaveAllRooms(); - closeActiveConnection(); - super.onTerminate(); + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread thread, Throwable ex) { + handleException(thread, ex); + } + }); } public static MyApplication getMyApplication() { return sMyApplication; } - public void setWebSocketClient(WebSocketClient webSocketClient) { - mWebSocketClient = webSocketClient; - } - public WebSocketClient getWebSocketClient() { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); @@ -401,4 +396,10 @@ public static String toId(String name) { } return name.toLowerCase().replaceAll("[^a-z0-9]", ""); } + + private void handleException(Thread thread, Throwable ex) { + ex.printStackTrace(); + Intent intent = new Intent(ACTION_FROM_MY_APPLICATION).putExtra(EXTRA_DETAILS, EXTRA_UNKNOWN_ERROR); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } } diff --git a/app/src/main/java/com/pokemonshowdown/data/Pokemon.java b/app/src/main/java/com/pokemonshowdown/data/Pokemon.java index e29c3bc1..8b09692d 100644 --- a/app/src/main/java/com/pokemonshowdown/data/Pokemon.java +++ b/app/src/main/java/com/pokemonshowdown/data/Pokemon.java @@ -96,41 +96,39 @@ public static Pokemon importPokemon(String importString, Context appContext, boo pokemonItem = nameItem[1]; pokemonMainData = nameItem[0]; } - String tmpString = pokemonMainData; - String[] tmpSplit = tmpString.trim().split(" "); - switch (tmpSplit.length) { - case 1: - pokemonName = tmpSplit[0].trim(); - break; - case 2: - // name (gender) - // nickname (name) - if (tmpString.contains("(") && tmpString.contains(")")) { - String gender = tmpString.substring(tmpString.indexOf("(") + 1, tmpString.indexOf(")")); - if (gender.equals("M") || gender.equals("F") || gender.equals("N")) { - pokemonGender = gender; - pokemonName = tmpSplit[0].trim(); - } else { - //is pokemon name - pokemonNickname = tmpSplit[0].trim(); - pokemonName = gender; - } - } else { - Log.w(PTAG, "Invalid pokemon name"); - return null; - } - break; + if (pokemonMainData.contains("(") && pokemonMainData.contains(")")) { + int countOpen = pokemonMainData.length() - pokemonMainData.replace("(", "").length(); + int countClosed = pokemonMainData.length() - pokemonMainData.replace(")", "").length(); - case 3: - // nickname (name) (gender) - pokemonNickname = tmpSplit[0].trim(); - pokemonName = tmpSplit[1].replace("(", "").replace(")", "").trim(); - pokemonGender = tmpSplit[2].replace("(", "").replace(")", "").trim(); - break; + if (countOpen == 1 && countClosed == 1) { + // either name or gender + String genderOrName = pokemonMainData.substring(pokemonMainData.lastIndexOf("(") + 1, pokemonMainData.lastIndexOf(")")); - default: - return null; + if (genderOrName.equals("M") || genderOrName.equals("F") || genderOrName.equals("N")) { + pokemonGender = genderOrName; + pokemonName = pokemonMainData.substring(0, pokemonMainData.lastIndexOf("(")); + } else { + pokemonName = genderOrName; + pokemonNickname = pokemonMainData.substring(0, pokemonMainData.lastIndexOf("(")); + } + } else { + // both name + gender + String genderOrName = pokemonMainData.substring(pokemonMainData.lastIndexOf("(") + 1, pokemonMainData.lastIndexOf(")")); + + if (genderOrName.equals("M") || genderOrName.equals("F") || genderOrName.equals("N")) { + pokemonGender = genderOrName; + pokemonMainData = pokemonMainData.substring(0, pokemonMainData.lastIndexOf("(")); + pokemonName = pokemonMainData.substring(pokemonMainData.lastIndexOf("(") + 1, pokemonMainData.lastIndexOf(")")); + pokemonNickname = pokemonMainData.substring(0, pokemonMainData.lastIndexOf("(")); + } else { + // is nickname with ()()() and (name) + pokemonName = genderOrName; + pokemonNickname = pokemonMainData.substring(0, pokemonMainData.lastIndexOf("(")); + } + } + } else { + pokemonName = pokemonMainData; } // replace for different formes @@ -511,7 +509,9 @@ public String exportPokemon(Context appContext) { } else { sb.append(getName()); } - sb.append(" (").append(getGender().toUpperCase()).append(")"); + if (!getGender().toUpperCase().equals("N")) { + sb.append(" (").append(getGender().toUpperCase()).append(")"); + } if (getItem().length() > 0) { JSONObject itemJSon = ItemDex.get(appContext).getItemJsonObject(getItem()); if (itemJSon != null) { @@ -609,7 +609,7 @@ public String exportPokemon(Context appContext) { // IVS difZero = false; for (int i : getIVs()) { - if (i != 0) { + if (i != 31) { difZero = true; break; } @@ -618,13 +618,13 @@ public String exportPokemon(Context appContext) { boolean first = true; sb.append("IVs: "); - if (getHPIV() != 0) { + if (getHPIV() != 31) { if (first) { sb.append(getHPIV()).append(" HP "); first = false; } } - if (getAtkIV() != 0) { + if (getAtkIV() != 31) { if (first) { sb.append(getAtkIV()).append(" Atk "); first = false; @@ -632,7 +632,7 @@ public String exportPokemon(Context appContext) { sb.append("/ ").append(getAtkIV()).append(" Atk "); } } - if (getDefIV() != 0) { + if (getDefIV() != 31) { if (first) { sb.append(getDefIV()).append(" Def "); first = false; @@ -641,7 +641,7 @@ public String exportPokemon(Context appContext) { sb.append("/ ").append(getDefIV()).append(" Def "); } } - if (getSpAtkIV() != 0) { + if (getSpAtkIV() != 31) { if (first) { sb.append(getSpAtkIV()).append(" SpA "); first = false; @@ -650,7 +650,7 @@ public String exportPokemon(Context appContext) { sb.append("/ ").append(getSpAtkIV()).append(" SpA "); } } - if (getSpDefIV() != 0) { + if (getSpDefIV() != 31) { if (first) { sb.append(getSpDefIV()).append(" SpD "); first = false; @@ -659,7 +659,7 @@ public String exportPokemon(Context appContext) { sb.append("/ ").append(getSpDefIV()).append(" SpD "); } } - if (getSpdIV() != 0) { + if (getSpdIV() != 31) { if (first) { sb.append(getSpdIV()).append(" Spe "); first = false; @@ -1174,6 +1174,7 @@ public float[] getNatureMultiplier() { public void setNatureMultiplier(String nature) { mNatureMultiplier = new float[6]; Arrays.fill(mNatureMultiplier, 1.0f); + if (nature.equals("Adamant")) { mNatureMultiplier[1] = 1.1f; mNatureMultiplier[3] = 0.9f; @@ -1191,11 +1192,11 @@ public void setNatureMultiplier(String nature) { mNatureMultiplier[1] = 0.9f; } if (nature.equals("Careful")) { - mNatureMultiplier[5] = 1.1f; + mNatureMultiplier[4] = 1.1f; mNatureMultiplier[3] = 0.9f; } if (nature.equals("Gentle")) { - mNatureMultiplier[5] = 1.1f; + mNatureMultiplier[4] = 1.1f; mNatureMultiplier[2] = 0.9f; } if (nature.equals("Hasty")) { @@ -1232,7 +1233,7 @@ public void setNatureMultiplier(String nature) { } if (nature.equals("Naughty")) { mNatureMultiplier[1] = 1.1f; - mNatureMultiplier[5] = 0.9f; + mNatureMultiplier[4] = 0.9f; } if (nature.equals("Quiet")) { mNatureMultiplier[3] = 1.1f; @@ -1240,7 +1241,7 @@ public void setNatureMultiplier(String nature) { } if (nature.equals("Rash")) { mNatureMultiplier[3] = 1.1f; - mNatureMultiplier[5] = 0.9f; + mNatureMultiplier[4] = 0.9f; } if (nature.equals("Relaxed")) { mNatureMultiplier[2] = 1.1f; diff --git a/app/src/main/java/com/pokemonshowdown/data/PokemonTeam.java b/app/src/main/java/com/pokemonshowdown/data/PokemonTeam.java index 18107c39..4ea0e18f 100644 --- a/app/src/main/java/com/pokemonshowdown/data/PokemonTeam.java +++ b/app/src/main/java/com/pokemonshowdown/data/PokemonTeam.java @@ -6,8 +6,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -62,15 +60,29 @@ public static void loadPokemonTeams(Context appContext) { StringBuffer pokemonTeamBuffer = new StringBuffer(""); String currentNickname = null; + String currentTierId = ""; + for (String s : fileContentStringArray) { if (s.startsWith("===") && s.endsWith("===")) { if (pokemonTeamBuffer.length() > 0) { PokemonTeam pt = PokemonTeam.importPokemonTeam(pokemonTeamBuffer.toString(), appContext, true); pt.setNickname(currentNickname); + if (!currentTierId.isEmpty()) { + BattleFieldData.Format currentFormat = BattleFieldData.get(appContext).getFormatUsingId(currentTierId); + if (currentFormat != null) { + pt.setTier(currentFormat.getName()); + } + } mPokemonTeamList.add(pt); } pokemonTeamBuffer.setLength(0); - currentNickname = s.replace("=", "").trim(); + if (s.contains("[") && s.contains("]")) { + currentTierId = s.substring(s.indexOf("[") + 1, s.indexOf("]")); + currentNickname = s.substring(s.indexOf("]") + 1).replace("=", "").trim(); + } else { + currentTierId = ""; + currentNickname = s.replace("=", "").trim(); + } } else { pokemonTeamBuffer.append(s).append("\n"); } @@ -79,6 +91,12 @@ public static void loadPokemonTeams(Context appContext) { if (pokemonTeamBuffer.length() > 0 && currentNickname != null) { PokemonTeam pt = PokemonTeam.importPokemonTeam(pokemonTeamBuffer.toString(), appContext, true); pt.setNickname(currentNickname); + if (!currentTierId.isEmpty()) { + BattleFieldData.Format currentFormat = BattleFieldData.get(appContext).getFormatUsingId(currentTierId); + if (currentFormat != null) { + pt.setTier(currentFormat.getName()); + } + } mPokemonTeamList.add(pt); } @@ -94,7 +112,11 @@ public static void savePokemonTeams(Context c) { StringBuilder sb = new StringBuilder(); for (PokemonTeam pokemonTeam : mPokemonTeamList) { - sb.append("=== ").append(pokemonTeam.getNickname()).append(" ===\n"); + sb.append("=== "); + if (!pokemonTeam.getTier().isEmpty()) { + sb.append("[").append(MyApplication.toId(pokemonTeam.getTier())).append("] "); + } + sb.append(pokemonTeam.getNickname()).append(" ===\n"); sb.append(pokemonTeam.exportPokemonTeam(c)); } diff --git a/app/src/main/java/com/pokemonshowdown/data/SearchableActivity.java b/app/src/main/java/com/pokemonshowdown/data/SearchableActivity.java index 190449f9..3c93a74f 100644 --- a/app/src/main/java/com/pokemonshowdown/data/SearchableActivity.java +++ b/app/src/main/java/com/pokemonshowdown/data/SearchableActivity.java @@ -92,7 +92,7 @@ protected void onListItemClick(ListView l, View v, int position, long id) { protected void onNewIntent(Intent intent) { setIntent(intent); if (Intent.ACTION_SEARCH.equals(intent.getAction())) { - String query = intent.getStringExtra(SearchManager.QUERY); + String query = MyApplication.toId(intent.getStringExtra(SearchManager.QUERY)); switch (mSearchType) { case REQUEST_CODE_SEARCH_POKEMON: searchPokemon(query); diff --git a/app/src/main/java/com/pokemonshowdown/replays/Replay.java b/app/src/main/java/com/pokemonshowdown/replays/Replay.java new file mode 100644 index 00000000..b34bc0ec --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/Replay.java @@ -0,0 +1,185 @@ +package com.pokemonshowdown.replays; + +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.util.Log; + +import java.util.ArrayList; + +/** + * Replay instance + * Returns events and such + */ +public class Replay { + Fragment BattleFragment; + + //Each step is an seprate event in-game + //unformated steps for BattleMessage.java + private ArrayList mFormatedSteps = new ArrayList(); + //Speed in milliseconds at which each event of the replay will last + //if Battle fragment does not handle messages fast enough, possibility of an exception being thrown + private long mSpeed; + + private com.pokemonshowdown.app.BattleFragment mReplayBattleFragment; + private int mCurrentStep; + + public ArrayList getSteps(){return mFormatedSteps;} + + public static ArrayList getSteps(String replayData){ + String [] unformatedSteps; + ArrayList formatedSteps = new ArrayList(); + unformatedSteps = replayData.split(System.getProperty("line.separator")); + for(String str : unformatedSteps){ + formatedSteps.add(str); + } + return formatedSteps; + } + + + public Replay(String replayData, com.pokemonshowdown.app.BattleFragment replayBattleFragment){ + mReplayBattleFragment = replayBattleFragment; + mFormatedSteps.add(""); + String[] mReplayData = replayData.split("::"); + for(String str : mReplayData){ + mFormatedSteps.add(reformat(str).replaceFirst("\\W", "")); + } + } + + //Converts the script.log to everything the battle message can understand + //Not fully stable + public static String reformat(String mLine){ + String args[] = mLine.split("\\|"); + //Houses temporary splits when string is reformated + String temp[]; + + String command; + if(args.length < 2){ + return ""; + } + command = args[1]; + Log.i("Command", command); + switch(command){ + case "player": + break; + case "poke": + break; + case "switch": + mLine = mLine.replace(",", ", L100,"); + mLine = mLine.replace("(", ""); + mLine = mLine.replace(")", ""); + mLine = mLine.replace("\\", ""); + //mLine = mLine.replace(" 100/100", "100/100"); + mLine = fixp1p2(mLine); + args = mLine.split("\\|"); + temp = args[4].split(" "); + temp[0] = ""; + args[4] = temp[1]; + mLine = rebuildString(args); + break; + case "-damage": + mLine = mLine.replace("(" , ""); + mLine = mLine.replace(")" , ""); + mLine = mLine.replace("\\" , ""); + mLine = fixp1p2(mLine); + args = mLine.split("\\|"); + temp = args[3].split(" "); + temp[0] = ""; + args[3] = temp[1]; + mLine = rebuildString(args); + break; + case "-heal": + mLine = mLine.replace("(" , ""); + mLine = mLine.replace(")" , ""); + mLine = mLine.replace("\\" , ""); + mLine = fixp1p2(mLine); + args = mLine.split("\\|"); + temp = args[3].split(" "); + temp[0] = ""; + args[3] = temp[1]; + mLine = rebuildString(args); + break; + default: + mLine = mLine.replace("(" , ""); + mLine = mLine.replace(")" , ""); + mLine = mLine.replace("\\" , ""); + mLine = fixp1p2(mLine); + break; + } + return mLine; + } + + static String fixp1p2(String in){ + in = in.replaceAll("p1", "p1a"); + in = in.replaceAll("p2", "p2a"); + return in; + } + + private void runClock(){ + new Handler().postDelayed(new Runnable() { + + @Override + public void run() { + getStep(); + } + }, mSpeed); + Log.i("Replay Next Step #", Integer.toString(mCurrentStep)); + } + + private void getStep(){ + if(mFormatedSteps.get(mCurrentStep).equalsIgnoreCase("callback|decision")){ + mSpeed = 1500; + mCurrentStep++; + mReplayBattleFragment.processServerMessage(mFormatedSteps.get(mCurrentStep)); + Log.i("Replay Next Step", mFormatedSteps.get(mCurrentStep)); + runClock(); + return; + } + mReplayBattleFragment.processServerMessage(mFormatedSteps.get(mCurrentStep)); + mCurrentStep++; + Log.i("Replay Next Step", mFormatedSteps.get(mCurrentStep)); + runClock(); + return; + } + + /* BattleFragment. + + new CountDownTimer(3000, 1000) { + + public void onTick(long millisUntilFinished) { + //Random thing needed + } + + public void onFinish() { + Log.i("test", "reached"); + } + }.start();*/ + + //Pause the replay + public void Pause(){ + + } + //Skip the turn + public void Skip(){ + + } + //Play the replay + public void Play() { + /*if (p1Pokemon.isEmpty() || p2Pokemon.isEmpty() || turns.isEmpty()) { + Log.e("Replay Error", "Not all replay values have been specified. Are you sure you calle" + + "d the methods in the right order?"); + return; + }*/ + runClock(); + return; + } + public static String rebuildString(String[] s){ + String v = ""; + for (String string : s) { + v += string; + v += "|"; + } + return v; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java b/app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java new file mode 100644 index 00000000..bbbded45 --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java @@ -0,0 +1,93 @@ +package com.pokemonshowdown.replays; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import com.pokemonshowdown.app.BattleFragment; +import com.pokemonshowdown.app.R; +import com.pokemonshowdown.data.BattleFieldData; + +public class ReplayFragment extends android.support.v4.app.Fragment implements View.OnClickListener{ + + public ProgressDialog mWaitingDialog; + + public static ReplayFragment newInstance() { + ReplayFragment fragment = new ReplayFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + public ReplayFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View v = inflater.inflate(R.layout.fragment_replay, container, false); + v.setFocusableInTouchMode(true); + Button submit = (Button) v.findViewById(R.id.submit); + submit.setOnClickListener(this); + return v; + } + + @Override + public void onDetach() { + super.onDetach(); + } + + public void showReplay(View view) { + //User input not supported +/* + EditText mEditText = (EditText) view.findViewById(R.id.replayInput); +*/ + + RetrieveReplayTask getReplayTask = new RetrieveReplayTask(){ + public void OnResponseRecived(Object obj) { + String battleLog = (String) obj; + //If replay was not retrieved correctly + if(battleLog == null){ + Toast toast = Toast.makeText(getActivity().getApplicationContext(), "Error fetching replay", Toast.LENGTH_LONG); + toast.show(); + return; + } + setUpReplayBattle(battleLog); + } + }; + + getReplayTask.execute("http://pokemonshowdown.com/replay/exeggutorboldalakazam"); + } + + @Override + public void onClick(View view) { + showReplay(view); + } + + private void setUpReplayBattle(String replayString){ + + //Create BattleFragment (Basically the same thing as watching replays) + BattleFragment replayBattleFragment; + replayBattleFragment = BattleFragment.newInstance("replay"); + Replay currentReplay = new Replay(replayString, replayBattleFragment); + BattleFieldData fieldData = BattleFieldData.get(getActivity().getApplicationContext()); + fieldData.joinRoom("replay",false); + FragmentManager fm = getFragmentManager(); + FragmentTransaction ft = fm.beginTransaction(); + ft.replace(R.id.fragmentContainer, replayBattleFragment).commit(); + currentReplay.Play(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java b/app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java new file mode 100644 index 00000000..c0c1e284 --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java @@ -0,0 +1,5 @@ +package com.pokemonshowdown.replays; + +public interface ResponseHandler { + public void OnResponseRecived(Object result); +} diff --git a/app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java b/app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java new file mode 100644 index 00000000..8fbf64f2 --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java @@ -0,0 +1,60 @@ +package com.pokemonshowdown.replays; + +import android.os.AsyncTask; +import android.util.Log; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Battle log of all events are stored in + * TODO : Allow cached copies of replays + */ +public abstract class RetrieveReplayTask extends AsyncTask implements ResponseHandler { + private String mHtml = ""; + + @Override + protected String doInBackground(String... url) { + Log.i("Getting Replay", url[0]); + try { + HttpClient client = new DefaultHttpClient(); + HttpGet request = new HttpGet(url[0]); + HttpResponse response = client.execute(request); + + InputStream in = response.getEntity().getContent(); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + StringBuilder str = new StringBuilder(); + String line = null; + while((line = reader.readLine()) != null) + { + str.append("::" + line); + } + in.close(); + mHtml = str.toString(); + mHtml = mHtml.substring(mHtml.indexOf("")); + Log.i("Html Sauce",mHtml); + } catch (IOException e) { + e.printStackTrace(); + } + + return mHtml; + } + + @Override + protected void onPostExecute(String element) { + OnResponseRecived(element); + return; + } + + @Override + public abstract void OnResponseRecived(Object result); + +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_battle.xml b/app/src/main/res/layout/fragment_battle.xml index 67ea2a31..8fa7961d 100644 --- a/app/src/main/res/layout/fragment_battle.xml +++ b/app/src/main/res/layout/fragment_battle.xml @@ -1,7 +1,8 @@ + android:layout_height="match_parent" + android:keepScreenOn="true"> - - + + android:layout_height="wrap_content"> - + + android:contentDescription="@string/pokemon_fragment_description" /> - + android:layout_toRightOf="@id/pokemon_icon" /> + @@ -57,7 +55,7 @@ android:layout_height="wrap_content" android:scaleType="fitXY" android:adjustViewBounds="true" - android:contentDescription="@string/pokemon_list"/> + android:contentDescription="@string/pokemon_list" /> + android:paddingRight="4dp" /> + android:layout_gravity="center" /> + + + + + + + + + + android:contentDescription="@string/type_1" /> + android:contentDescription="@string/type_2" /> + android:layout_marginLeft="8dp" /> + android:contentDescription="@string/gender" /> + android:background="@drawable/editable_frame" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_replay.xml b/app/src/main/res/layout/fragment_replay.xml new file mode 100644 index 00000000..beec1027 --- /dev/null +++ b/app/src/main/res/layout/fragment_replay.xml @@ -0,0 +1,31 @@ + + + + + + + + +