From b1b92743e8485caa3fd2b5ef771efff869d9840c Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Tue, 1 Sep 2020 00:54:22 -0700 Subject: [PATCH] Adds armor class and section divider to monster cards. --- .../monstercards/models/Monster.java | 197 ++++++++++++++++++ .../ui/monster/MonsterFragment.java | 18 +- .../ui/monster/MonsterViewModel.java | 8 + .../main/res/drawable/ic_section_divider.xml | 9 + app/src/main/res/layout/fragment_monster.xml | 28 +++ app/src/main/res/values/strings.xml | 1 + 6 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/ic_section_divider.xml diff --git a/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java b/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java index 12b5430..bb31122 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java +++ b/app/src/main/java/com/majinnaibu/monstercards/models/Monster.java @@ -4,6 +4,7 @@ import com.majinnaibu.monstercards.helpers.StringHelper; import java.util.ArrayList; import java.util.List; +import java.util.Locale; public class Monster { @@ -87,4 +88,200 @@ public class Monster { return sb.toString(); } + public int getAbilityScore(String abilityScoreName) { + if ("strength".equals(abilityScoreName) || "str".equals(abilityScoreName)) { + return getStrengthScore(); + } else if ("dexterity".equals(abilityScoreName) || "dex".equals(abilityScoreName)) { + return getDexterityScore(); + } else if ("constitution".equals(abilityScoreName) || "con".equals(abilityScoreName)) { + return getConstitutionScore(); + } else if ("intelligence".equals(abilityScoreName) || "int".equals(abilityScoreName)) { + return getIntelligenceScore(); + } else if ("wisdom".equals(abilityScoreName) || "wis".equals(abilityScoreName)) { + return getWisdomScore(); + } else if ("charisma".equals(abilityScoreName) || "cha".equals(abilityScoreName)) { + return getCharismaScore(); + } else { + return 10; + } + } + + public static int getAbilityModifierForScore(int score) { + return (int)Math.floor((score-10)/2.0); + } + + public int getAbilityModifier(String abilityScoreName) { + int score = getAbilityScore(abilityScoreName); + return getAbilityModifierForScore(score); + } + + private int mStrengthScore; + public int getStrengthScore() { + return mStrengthScore; + } + public void setStrengthScore(int value) { + mStrengthScore = value; + } + public int getStrengthModifier() { + return getAbilityModifierForScore(getStrengthScore()); + } + + private int mDexterityScore; + public int getDexterityScore() { + return mDexterityScore; + } + public void setDexterityScore(int value) { + mDexterityScore = value; + } + public int getDexterityModifier() { + return getAbilityModifierForScore(getDexterityScore()); + } + + private int mConstitutionScore; + public int getConstitutionScore() { + return mConstitutionScore; + } + public void setConstitutionScore(int value) { + mConstitutionScore = value; + } + public int getConstitutionModifier() { + return getAbilityModifierForScore(getConstitutionScore()); + } + + private int mIntelligenceScore; + public int getIntelligenceScore() { + return mIntelligenceScore; + } + public void setIntelligenceScore(int value) { + mIntelligenceScore = value; + } + public int getIntelligenceModifier() { + return getAbilityModifierForScore(getIntelligenceScore()); + } + + private int mWisdomScore; + public int getWisdomScore() { + return mWisdomScore; + } + public void setWisdomScore(int value) { + mWisdomScore = value; + } + public int getWisdomModifier() { + return getAbilityModifierForScore(getWisdomScore()); + } + + private int mCharismaScore; + public int getCharismaScore() { + return mCharismaScore; + } + public void setCharismaScore(int value) { + mCharismaScore = value; + } + public int getCharismaModifier() { + return getAbilityModifierForScore(getCharismaScore()); + } + + private String mArmorName; + public String getArmorName() { + return mArmorName; + } + public void setArmorName(String value) { + mArmorName = value; + } + + private int mShieldBonus; + public int getShieldBonus() { + return mShieldBonus; + } + public void setShieldBonus(int value) { + mShieldBonus = value; + } + + private int mNaturalArmorBonus; + public int getNaturalArmorBonus() { + return mNaturalArmorBonus; + } + public void setNaturalArmorBonus(int value) { + mNaturalArmorBonus = value; + } + + private String mOtherArmorDescription; + public String getOtherArmorDescription() { + return mOtherArmorDescription; + } + public void setOtherArmorDescription(String value) { + mOtherArmorDescription = value; + } + + public String getArmorClass() { + boolean hasShield = getShieldBonus() != 0; + String armorName = getArmorName(); + if (StringHelper.isNullOrEmpty(armorName) || "none".equals(armorName)) { + // 10 + dexMod + 2 for shieldBonus "15" or "17 (shield)" + return String.format(Locale.US, "%d%s", BASE_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? " (shield)" : ""); + } else if("natural armor".equals(armorName)) { + // 10 + dexMod + naturalArmorBonus + 2 for shieldBonus "16 (natural armor)" or "18 (natural armor, shield)" + return String.format(Locale.US, "%d (natural armor%s)", BASE_ARMOR_CLASS + getDexterityModifier() + getNaturalArmorBonus() + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("mage armor".equals(armorName)) { + // 10 + dexMod + 2 for shield + 3 for mage armor "15 (18 with mage armor)" or 17 (shield, 20 with mage armor) + return String.format(Locale.US, "%d (%s%d with mage armor)", BASE_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? "shield, " : "", MAGE_ARMOR_ARMOR_CLASS + getDexterityModifier() + getShieldBonus()); + } else if ("padded".equals(armorName)) { + // 11 + dexMod + 2 for shield "18 (padded armor, shield)" + return String.format(Locale.US, "%d (padded%s)", PADDED_ARMOR_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("leather".equals(armorName)) { + // 11 + dexMod + 2 for shield "18 (leather, shield)" + return String.format(Locale.US, "%d (leather%s)", LEATHER_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("studded".equals(armorName)) { + // 12 + dexMod +2 for shield "17 (studded leather)" + return String.format(Locale.US, "%d (studded leather%s)", STUDDED_LEATHER_ARMOR_CLASS + getDexterityModifier() + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("hide".equals(armorName)) { + // 12 + Min(2, dexMod) + 2 for shield "12 (hide armor)" + return String.format(Locale.US, "%d (hide%s)", HIDE_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("chain shirt".equals(armorName)) { + // 13 + Min(2, dexMod) + 2 for shield "12 (chain shirt)" + return String.format(Locale.US, "%d (chain shirt%s)", CHAIN_SHIRT_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("scale mail".equals(armorName)) { + // 14 + Min(2, dexMod) + 2 for shield "14 (scale mail)" + return String.format(Locale.US, "%d (scale mail%s)", SCALE_MAIL_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("breastplate".equals(armorName)) { + // 14 + Min(2, dexMod) + 2 for shield "16 (breastplate)" + return String.format(Locale.US, "%d (breastplate%s)", BREASTPLATE_ARMOR_CLASS +Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("half plate".equals(armorName)) { + // 15 + Min(2, dexMod) + 2 for shield "17 (half plate)" + return String.format(Locale.US, "%d (half plate%s)", HALF_PLATE_ARMOR_CLASS + Math.min(2, getDexterityModifier()) + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("ring mail".equals(armorName)) { + // 14 + 2 for shield "14 (ring mail) + return String.format(Locale.US, "%d (ring mail%s)", RING_MAIL_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("chain mail".equals(armorName)) { + // 16 + 2 for shield "16 (chain mail)" + return String.format(Locale.US, "%d (chain mail%s)", CHAIN_MAIL_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield" : ""); + } else if ("splint".equals(armorName)) { + // 17 + 2 for shield "17 (splint)" + return String.format(Locale.US, "%d (splint%s)", SPLINT_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield": ""); + } else if ("plate".equals(armorName)) { + // 18 + 2 for shield "18 (plate)" + return String.format(Locale.US, "%d (plate%s)", PLATE_ARMOR_CLASS + getShieldBonus(), hasShield ? ", shield": ""); + } else if ("other".equals(armorName)) { + // pure string value shield check does nothing just copies the string from otherArmorDesc + return getOtherArmorDescription(); + } else { + return ""; + } + } + + private static final int BASE_ARMOR_CLASS = 10; + private static final int MAGE_ARMOR_ARMOR_CLASS = BASE_ARMOR_CLASS + 3; + private static final int PADDED_ARMOR_ARMOR_CLASS = BASE_ARMOR_CLASS + 1; + private static final int LEATHER_ARMOR_CLASS = BASE_ARMOR_CLASS + 1; + private static final int STUDDED_LEATHER_ARMOR_CLASS = BASE_ARMOR_CLASS + 2; + private static final int HIDE_ARMOR_CLASS = BASE_ARMOR_CLASS + 2; + private static final int CHAIN_SHIRT_ARMOR_CLASS = BASE_ARMOR_CLASS + 3; + private static final int SCALE_MAIL_ARMOR_CLASS = BASE_ARMOR_CLASS + 4; + private static final int BREASTPLATE_ARMOR_CLASS = BASE_ARMOR_CLASS + 4; + private static final int HALF_PLATE_ARMOR_CLASS = BASE_ARMOR_CLASS + 5; + private static final int RING_MAIL_ARMOR_CLASS = BASE_ARMOR_CLASS + 4; + private static final int CHAIN_MAIL_ARMOR_CLASS = BASE_ARMOR_CLASS + 6; + private static final int SPLINT_ARMOR_CLASS = BASE_ARMOR_CLASS + 7; + private static final int PLATE_ARMOR_CLASS = BASE_ARMOR_CLASS + 8; + } diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java b/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java index d5a9240..217c614 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java +++ b/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterFragment.java @@ -1,6 +1,7 @@ package com.majinnaibu.monstercards.ui.monster; import android.os.Bundle; +import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -32,6 +33,11 @@ public class MonsterFragment extends Fragment { monster.setType("fey"); monster.setTag(""); monster.setAlignment("neutral good"); + // Armor & Armor Class + monster.setArmorName("none"); + monster.setShieldBonus(0); + monster.setNaturalArmorBonus(7); + monster.setOtherArmorDescription("14"); // END remove block monsterViewModel = new ViewModelProvider(this).get(MonsterViewModel.class); View root = inflater.inflate(R.layout.fragment_monster, container, false); @@ -48,8 +54,16 @@ public class MonsterFragment extends Fragment { final TextView monsterMeta = root.findViewById(R.id.meta); monsterViewModel.getMeta().observe(getViewLifecycleOwner(), new Observer() { @Override - public void onChanged(@Nullable String s) { - monsterMeta.setText(s); + public void onChanged(@Nullable String metaText) { + monsterMeta.setText(metaText); + } + }); + + final TextView monsterArmorClass = root.findViewById(R.id.armor_class); + monsterViewModel.getArmorClass().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(@Nullable String armorText) { + monsterArmorClass.setText(Html.fromHtml("Armor Class " + armorText)); } }); diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterViewModel.java b/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterViewModel.java index 8ab2b50..26f03d3 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterViewModel.java +++ b/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterViewModel.java @@ -14,6 +14,9 @@ public class MonsterViewModel extends ViewModel { mName.setValue(""); mMeta = new MutableLiveData<>(); mMeta.setValue(""); + mArmorClass = new MutableLiveData<>(); + mArmorClass.setValue(""); + } private MutableLiveData mName; @@ -24,11 +27,16 @@ public class MonsterViewModel extends ViewModel { public LiveData getMeta() { return mMeta; } + private MutableLiveData mArmorClass; + public LiveData getArmorClass() { + return mArmorClass; + } private Monster mMonster; public void setMonster(Monster monster) { mMonster = monster; mName.setValue(mMonster.getName()); mMeta.setValue(mMonster.getMeta()); + mArmorClass.setValue(mMonster.getArmorClass()); } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_section_divider.xml b/app/src/main/res/drawable/ic_section_divider.xml new file mode 100644 index 0000000..22a9637 --- /dev/null +++ b/app/src/main/res/drawable/ic_section_divider.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_monster.xml b/app/src/main/res/layout/fragment_monster.xml index 534520c..5f140dd 100644 --- a/app/src/main/res/layout/fragment_monster.xml +++ b/app/src/main/res/layout/fragment_monster.xml @@ -41,5 +41,33 @@ app:layout_constraintTop_toBottomOf="@+id/name" tools:text="Tiny fey, neutral good" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 232856a..d1a421d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,4 +6,5 @@ Library Search Query + section divider \ No newline at end of file