Procházet zdrojové kódy

Initial construction of feat branch.

Sam Jaffe před 8 roky
rodič
revize
57f2fb1142

+ 5 - 0
resources/Potato.json

@@ -107,6 +107,11 @@
     {"name": "Perform (sing)", "ranks": 3, "pointsSpent": 3}
   ],
   
+  "feats": [
+    "Improved Initiative",
+    "Augment Healing"
+  ],
+  
   "inventory": {
     "items": [
       {

+ 5 - 5
resources/classes/Bard.json

@@ -6,11 +6,11 @@
   "will":"GOOD",
   "features":[
     [
-      {"name":"Bardic Music"},
-      {"name":"Bardic Knowledge"},
-      {"name":"Countersong"},
-      {"name":"Fascinate"},
-      {"name":"Inspire Courage +1"}
+      {"@type":"Simple", "name":"Bardic Music"},
+      {"@type":"Simple", "name":"Bardic Knowledge"},
+      {"@type":"Simple", "name":"Countersong"},
+      {"@type":"Simple", "name":"Fascinate"},
+      {"@type":"Simple", "name":"Inspire Courage +1"}
     ],
     []
   ],

+ 1 - 0
resources/classes/Cleric.json

@@ -7,6 +7,7 @@
   "features":[
     [
       {
+        "@type": "Simple",
         "name":"Turn or Rebuke Undead"
       }
     ]

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 35 - 0
resources/feats/default.json


+ 1 - 0
src/main/lombok/org/leumasjaffe/charsheet/config/Constants.java

@@ -8,6 +8,7 @@ import lombok.experimental.UtilityClass;
 public final class Constants {
 	public String PREVIOUS_LOADOUT = "$$PREVIOUS";
 	public String NO_FLAT_FOOTED = "Keeps Dexterity When Flat-footed";
+	public String INITIATIVE = "Character::Initiative";
 	
 	public String K_DISTANCE = "Distance Measurement Unit";
 	public enum DistanceMeasurement {

+ 15 - 6
src/main/lombok/org/leumasjaffe/charsheet/model/DDCharacter.java

@@ -1,30 +1,37 @@
 package org.leumasjaffe.charsheet.model;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 
+import org.leumasjaffe.charsheet.model.features.DDFeat;
+import org.leumasjaffe.charsheet.model.features.DDFeature;
 import org.leumasjaffe.charsheet.model.inventory.DDInventory;
 import org.leumasjaffe.charsheet.model.observable.IntValue;
 import org.leumasjaffe.charsheet.model.observable.ObjectValue;
 import org.leumasjaffe.charsheet.model.skill.DDSkills;
+import org.leumasjaffe.observer.Observable;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
 import lombok.AccessLevel;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.NonNull;
 import lombok.experimental.FieldDefaults;
 
 @NoArgsConstructor
-@Data
+@Data @EqualsAndHashCode(callSuper=false)
 @FieldDefaults(level=AccessLevel.PRIVATE)
 @JsonIgnoreProperties(ignoreUnknown=true)
-public class DDCharacter {
+public class DDCharacter extends Observable {
 	@NonNull String name = "";
 	
 	@NonNull String player = "";
@@ -46,13 +53,10 @@ public class DDCharacter {
 	@NonNull String skin = "";
 	
 	@NonNull IntValue experience = new IntValue();
-	
 	@NonNull HitPoints health = new HitPoints();
-	
 	@NonNull Ability abilities = new Ability();
-	
 	@NonNull DDSkills skills = new DDSkills(Collections.emptyList());
-	
+	@NonNull List<DDFeat> feats = new ArrayList<>();
 	@NonNull DDInventory inventory = new DDInventory();
 
 	public String getClassAndLevelString() {
@@ -92,4 +96,9 @@ public class DDCharacter {
 	public int getLevel() {
 		return classes.stream().map(DDCharacterClass::getLevel).mapToInt(IntValue::value).sum();
 	}
+	
+	public List<DDFeature> getFeatureBonuses(String appliesScope) {
+		return feats.stream().flatMap(f -> f.getProperties().stream())
+				.filter(f -> f.appliesTo(appliesScope)).collect(Collectors.toList());
+	}
 }

+ 1 - 0
src/main/lombok/org/leumasjaffe/charsheet/model/DDClass.java

@@ -9,6 +9,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
+import org.leumasjaffe.charsheet.model.features.DDFeature;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
 import org.leumasjaffe.charsheet.model.magic.DDSpellList;
 import org.leumasjaffe.charsheet.model.magic.DDSpellList.SpellList;

+ 0 - 14
src/main/lombok/org/leumasjaffe/charsheet/model/DDFeature.java

@@ -1,14 +0,0 @@
-package org.leumasjaffe.charsheet.model;
-
-import lombok.AccessLevel;
-import lombok.Data;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.experimental.FieldDefaults;
-
-@Data
-@RequiredArgsConstructor
-@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
-public class DDFeature {
-	@NonNull String name;
-}

+ 22 - 0
src/main/lombok/org/leumasjaffe/charsheet/model/features/DDFeat.java

@@ -0,0 +1,22 @@
+package org.leumasjaffe.charsheet.model.features;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+
+import lombok.AccessLevel;
+import lombok.Data;
+import lombok.NonNull;
+import lombok.experimental.FieldDefaults;
+
+@Data
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class DDFeat {
+	@NonNull String name, page, benefit;
+	@NonNull List<DDPrerequisite> prerequisites;
+	@NonNull List<DDFeature> properties;
+	
+	@JsonCreator public static DDFeat fromString(String name) {
+		return DDFeatFactory.loadFeat(name);
+	}
+}

+ 49 - 0
src/main/lombok/org/leumasjaffe/charsheet/model/features/DDFeatFactory.java

@@ -0,0 +1,49 @@
+package org.leumasjaffe.charsheet.model.features;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+
+import lombok.AccessLevel;
+import lombok.SneakyThrows;
+import lombok.Synchronized;
+import lombok.experimental.FieldDefaults;
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public final class DDFeatFactory {
+	Set<String> resourcesLoaded = new HashSet<>();
+	Map<String, DDFeat> featStore = new HashMap<>();
+	
+	ObjectMapper mapper = new ObjectMapper();
+
+	
+	static {
+		mapper.registerModule(new Jdk8Module());
+		loadIfAbsent("resources/feats/default.json");
+	}
+	
+	public DDFeat loadFeat(final String name) {
+		return featStore.get(name);
+	}
+	
+	@Synchronized
+	@SneakyThrows
+	private void loadIfAbsent(final String rname) {
+		final List<DDFeat> temp = mapper.readValue(
+				new File(rname),
+				new TypeReference<ArrayList<DDFeat>>() {
+				});
+		resourcesLoaded.add(rname);
+		temp.forEach(s -> featStore.put(s.getName(), s));
+	}
+}

+ 65 - 0
src/main/lombok/org/leumasjaffe/charsheet/model/features/DDFeature.java

@@ -0,0 +1,65 @@
+package org.leumasjaffe.charsheet.model.features;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
+
+import lombok.AllArgsConstructor;
+
+@JsonTypeInfo(use=Id.NAME)
+@JsonSubTypes({
+	@Type(name="Simple", value=DDFeature.Simple.class),
+	@Type(name="Flat", value=DDFeature.Flat.class),
+	@Type(name="SpellLevel", value=DDFeature.PerSpellLevel.class)
+})
+public interface DDFeature {
+	public enum Group {
+		NONE
+	}
+	boolean appliesTo(String key);
+	<T> T value();
+	
+	@AllArgsConstructor
+	public class Simple implements DDFeature {
+		String name;
+		@Override public boolean appliesTo(String key) { return false; }
+		@Override public <T> T value() { return null; }
+	}
+
+	@AllArgsConstructor
+	public static class Flat implements DDFeature {
+		String applies;
+		Group group;
+		int value;
+		
+		@Override
+		public boolean appliesTo(String key) {
+			return applies.equals(key);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public Object value() {
+			return this.value;
+		}
+	}
+	
+	@AllArgsConstructor
+	public static class PerSpellLevel implements DDFeature {
+		String applies;
+		Group group;
+		int value;
+		
+		@Override
+		public boolean appliesTo(String key) {
+			return applies.equals(key);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public Object value() {
+			return this.value; // TODO consume spell level information
+		}
+	}
+}

+ 9 - 0
src/main/lombok/org/leumasjaffe/charsheet/model/features/DDPrerequisite.java

@@ -0,0 +1,9 @@
+package org.leumasjaffe.charsheet.model.features;
+
+import lombok.AllArgsConstructor;
+
+@AllArgsConstructor
+public class DDPrerequisite {
+	String applies;
+	int value;
+}

+ 0 - 5
src/main/lombok/org/leumasjaffe/charsheet/model/magic/DDSpellFactory.java

@@ -32,11 +32,6 @@ public final class DDSpellFactory {
 		loadIfAbsent("resources/spells/default.json");
 	}
 	
-	public DDSpell loadSpellWithResource(final String rname, final String name) {
-		loadIfAbsent(rname);
-		return loadSpell(name);
-	}
-	
 	public DDSpell loadSpell(final String name) {
 		return spellStore.get(name);
 	}

+ 1 - 6
src/main/lombok/org/leumasjaffe/charsheet/model/magic/DDSpellList.java

@@ -30,13 +30,8 @@ public class DDSpellList {
 		@JsonCreator
 		public SpellList(List<String> data) {
 			this.spellList = new ArrayList<>(data.size());
-			int idx = -1;
 			for ( final String name : data ) {
-				if ((idx = name.indexOf(':')) != -1) {
-					spellList.add(DDSpellFactory.loadSpellWithResource(name.substring(0, idx), name.substring(idx))); 
-				} else {
-					spellList.add(DDSpellFactory.loadSpell(name));
-				}
+				spellList.add(DDSpellFactory.loadSpell(name));
 			}
 		}
 	} 

+ 17 - 2
src/main/lombok/org/leumasjaffe/charsheet/view/summary/InitiativeLine.java

@@ -8,6 +8,7 @@ import java.awt.GridBagConstraints;
 import java.awt.Color;
 import javax.swing.border.LineBorder;
 
+import org.leumasjaffe.charsheet.config.Constants;
 import org.leumasjaffe.charsheet.model.Ability;
 import org.leumasjaffe.charsheet.model.DDCharacter;
 import org.leumasjaffe.charsheet.observer.helper.AbilModStringify;
@@ -33,6 +34,7 @@ public class InitiativeLine extends JPanel {
 	private static final long serialVersionUID = 1L;
 	IndirectObservableListener<JTextField, DDCharacter> ttlObserver;
 	ObservableListener<JTextField, Ability.Scores> dexObserver;
+	ObservableListener<JTextField, DDCharacter> tempObserver;
 
 	public InitiativeLine() {
 		setOpaque(false);
@@ -127,16 +129,28 @@ public class InitiativeLine extends JPanel {
 		ttlObserver = new IndirectObservableListener<>(total, 
 				(c, v) -> {
 					final int adex = v.getAbilities().getDex().modifier();
-					c.setText(StringHelper.toString( adex ));
+					final int miscValue = getInitiativeBonuses(v);
+					c.setText(StringHelper.toString( adex + miscValue ));
 				});
 		dexObserver = new ObservableListener<>(dex, 
 				new AbilModStringify());
+		tempObserver = new ObservableListener<>(misc, (c, v) -> {
+			final int miscValue = getInitiativeBonuses(v);
+			c.setText(StringHelper.toString(miscValue));
+		});
+	}
+
+	private int getInitiativeBonuses(DDCharacter v) {
+		// FIXME
+		return v.getFeatureBonuses(Constants.INITIATIVE).stream()
+				.mapToInt(f -> (Integer) f.value()).sum();
 	}
 
 	public void setModel(DDCharacter model) {
 		final Ability.Scores dex = model.getAbilities().getDex();
-		ttlObserver.setObserved(model, dex);
+		ttlObserver.setObserved(model, model, dex);
 		dexObserver.setObserved(dex);
+		tempObserver.setObserved(model);
 	}
 
 	@Override
@@ -144,5 +158,6 @@ public class InitiativeLine extends JPanel {
 		super.removeNotify();
 		ObserverDispatch.unsubscribeAll(ttlObserver);
 		ObserverDispatch.unsubscribeAll(dexObserver);
+		ObserverDispatch.unsubscribeAll(tempObserver);
 	}
 }