Adds armor class and section divider to monster cards.

This commit is contained in:
2020-09-01 00:54:22 -07:00
parent 4382b85b96
commit b1b92743e8
6 changed files with 259 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ import com.majinnaibu.monstercards.helpers.StringHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
public class Monster { public class Monster {
@@ -87,4 +88,200 @@ public class Monster {
return sb.toString(); 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;
} }

View File

@@ -1,6 +1,7 @@
package com.majinnaibu.monstercards.ui.monster; package com.majinnaibu.monstercards.ui.monster;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -32,6 +33,11 @@ public class MonsterFragment extends Fragment {
monster.setType("fey"); monster.setType("fey");
monster.setTag(""); monster.setTag("");
monster.setAlignment("neutral good"); monster.setAlignment("neutral good");
// Armor & Armor Class
monster.setArmorName("none");
monster.setShieldBonus(0);
monster.setNaturalArmorBonus(7);
monster.setOtherArmorDescription("14");
// END remove block // END remove block
monsterViewModel = new ViewModelProvider(this).get(MonsterViewModel.class); monsterViewModel = new ViewModelProvider(this).get(MonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_monster, container, false); 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); final TextView monsterMeta = root.findViewById(R.id.meta);
monsterViewModel.getMeta().observe(getViewLifecycleOwner(), new Observer<String>() { monsterViewModel.getMeta().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override @Override
public void onChanged(@Nullable String s) { public void onChanged(@Nullable String metaText) {
monsterMeta.setText(s); monsterMeta.setText(metaText);
}
});
final TextView monsterArmorClass = root.findViewById(R.id.armor_class);
monsterViewModel.getArmorClass().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String armorText) {
monsterArmorClass.setText(Html.fromHtml("<b>Armor Class</b> " + armorText));
} }
}); });

View File

@@ -14,6 +14,9 @@ public class MonsterViewModel extends ViewModel {
mName.setValue(""); mName.setValue("");
mMeta = new MutableLiveData<>(); mMeta = new MutableLiveData<>();
mMeta.setValue(""); mMeta.setValue("");
mArmorClass = new MutableLiveData<>();
mArmorClass.setValue("");
} }
private MutableLiveData<String> mName; private MutableLiveData<String> mName;
@@ -24,11 +27,16 @@ public class MonsterViewModel extends ViewModel {
public LiveData<String> getMeta() { public LiveData<String> getMeta() {
return mMeta; return mMeta;
} }
private MutableLiveData<String> mArmorClass;
public LiveData<String> getArmorClass() {
return mArmorClass;
}
private Monster mMonster; private Monster mMonster;
public void setMonster(Monster monster) { public void setMonster(Monster monster) {
mMonster = monster; mMonster = monster;
mName.setValue(mMonster.getName()); mName.setValue(mMonster.getName());
mMeta.setValue(mMonster.getMeta()); mMeta.setValue(mMonster.getMeta());
mArmorClass.setValue(mMonster.getArmorClass());
} }
} }

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="800.5dp"
android:height="20.5dp"
android:viewportWidth="800.5"
android:viewportHeight="20.5">
<path
android:pathData="M0.5,0l-0.5,20.5l800.5,-20.5l-800,0z"
android:fillColor="#9b2818"/>
</vector>

View File

@@ -41,5 +41,33 @@
app:layout_constraintTop_toBottomOf="@+id/name" app:layout_constraintTop_toBottomOf="@+id/name"
tools:text="Tiny fey, neutral good" /> tools:text="Tiny fey, neutral good" />
<ImageView
android:id="@+id/divider1"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/section_divider"
android:scaleType="fitXY"
android:src="@drawable/ic_section_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/meta" />
<TextView
android:id="@+id/armor_class"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider1"
tools:text="Armor Class 15" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>

View File

@@ -6,4 +6,5 @@
<string name="title_library">Library</string> <string name="title_library">Library</string>
<string name="action_search">Search</string> <string name="action_search">Search</string>
<string name="label_search_query">Query</string> <string name="label_search_query">Query</string>
<string name="section_divider">section divider</string>
</resources> </resources>