mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 04:57:27 +00:00
Ability Conditions overhaul WIP
This commit is contained in:
1 parent
8f76e007e4
commit
d9b63038dd
3 files changed
+315
-18
No files matched your search
@@ -1,15 +1,6 @@
|
||||
package kamkeel.npcs.controllers;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityPhase;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityVariant;
|
||||
import kamkeel.npcs.controllers.data.ability.ChainedAbility;
|
||||
import kamkeel.npcs.controllers.data.ability.IAbilityAction;
|
||||
import kamkeel.npcs.controllers.data.ability.IAbilityExtender;
|
||||
import kamkeel.npcs.controllers.data.ability.IAbilityFieldProvider;
|
||||
import kamkeel.npcs.controllers.data.ability.IEffectAction;
|
||||
import kamkeel.npcs.controllers.data.ability.IChainedAbilityFieldProvider;
|
||||
import kamkeel.npcs.controllers.data.ability.UserType;
|
||||
import kamkeel.npcs.controllers.data.ability.*;
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityCharge;
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityCutter;
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityDash;
|
||||
@@ -43,14 +34,7 @@ import noppes.npcs.controllers.data.PlayerData;
|
||||
import noppes.npcs.util.NBTJsonUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -70,6 +54,7 @@ public class AbilityController implements IAbilityHandler {
|
||||
private final List<IAbilityFieldProvider> fieldProviders = new ArrayList<>();
|
||||
private final List<IChainedAbilityFieldProvider> chainedFieldProviders = new ArrayList<>();
|
||||
private final List<IAbilityExtender> extenders = new ArrayList<>();
|
||||
private final Map<String, Supplier<IAbilityCondition>> conditionTypes = new HashMap<>();
|
||||
private final List<Predicate<EntityPlayer>> flightCheckers = new ArrayList<>();
|
||||
|
||||
// ── Legacy Migration ─────────────────────────────────────────────────────
|
||||
@@ -90,6 +75,7 @@ public class AbilityController implements IAbilityHandler {
|
||||
|
||||
public AbilityController() {
|
||||
registerBuiltinTypes();
|
||||
registerBuiltinConditionTypes();
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -160,6 +146,10 @@ public class AbilityController implements IAbilityHandler {
|
||||
registerType("cnpc:slicer", AbilitySlicer::new);
|
||||
}
|
||||
|
||||
private void registerBuiltinConditionTypes() {
|
||||
registerCondition(IAbilityCondition.ConditionHPAbove::new);
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BUILT-IN ABILITIES
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -890,6 +880,23 @@ public class AbilityController implements IAbilityHandler {
|
||||
return extenders;
|
||||
}
|
||||
|
||||
public void registerCondition(Supplier<IAbilityCondition> conditionFactory) {
|
||||
IAbilityCondition temp = conditionFactory.get();
|
||||
String typeId = temp.getTypeId();
|
||||
if (conditionTypes.containsKey(typeId)) {
|
||||
LogWriter.info("AbilityController: Overwriting Condition type: " + typeId);
|
||||
}
|
||||
conditionTypes.put(typeId, conditionFactory);
|
||||
}
|
||||
|
||||
public Supplier<IAbilityCondition> getConditionType(String key) {
|
||||
return conditionTypes.get(key);
|
||||
}
|
||||
|
||||
public String[] getConditionTypes() {
|
||||
return conditionTypes.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
public void registerFlightChecker(Predicate<EntityPlayer> checker) {
|
||||
flightCheckers.add(checker);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package kamkeel.npcs.controllers.data.ability;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
public abstract class ConditionField<T> {
|
||||
protected final String key;
|
||||
protected final String label;
|
||||
protected final Class<T> type; // Float.class, Integer.class, etc
|
||||
protected T value;
|
||||
|
||||
public ConditionField(String key, String label, Class<T> type, T defaultValue) {
|
||||
this.key = key;
|
||||
this.label = label;
|
||||
this.type = type;
|
||||
this.value = defaultValue;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public abstract void writeNBT(NBTTagCompound nbt);
|
||||
|
||||
public abstract void readNBT(NBTTagCompound nbt);
|
||||
|
||||
public static ConditionField<Integer> intField(String key, String label, int defaultValue) {
|
||||
return intField(key, label, defaultValue, 0, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static ConditionField<Integer> intField(String key, String label, int defaultValue, int min, int max) {
|
||||
return new NumberField<>(key, label, Integer.class, defaultValue, min, max);
|
||||
}
|
||||
|
||||
public static ConditionField<Double> doubleField(String key, String label, double defaultValue) {
|
||||
return doubleField(key, label, defaultValue, 0, Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static ConditionField<Double> doubleField(String key, String label, double defaultValue, double min, double max) {
|
||||
return new NumberField<>(key, label, Double.class, defaultValue, min, max);
|
||||
}
|
||||
|
||||
public static ConditionField<Float> floatField(String key, String label, float defaultValue) {
|
||||
return floatField(key, label, defaultValue, 0, Float.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static ConditionField<Float> floatField(String key, String label, float defaultValue, float min, float max) {
|
||||
return new NumberField<>(key, label, Float.class, defaultValue, min, max);
|
||||
}
|
||||
|
||||
public static ConditionField<String> stringField(String key, String label) {
|
||||
return new StringField(key, label, "");
|
||||
}
|
||||
|
||||
public static ConditionField<String> stringField(String key, String label, String defaultValue) {
|
||||
return new StringField(key, label, defaultValue);
|
||||
}
|
||||
|
||||
public static ConditionField<Boolean> booleanField(String key, String label, boolean defaultValue) {
|
||||
return new BoolField(key, label, defaultValue);
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> ConditionField<E> enumField(String key, String label, E defaultValue, Class<E> enumClass) {
|
||||
return new EnumField<>(key, label, defaultValue, enumClass);
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> ConditionField<E> enumField(String key, String label, E defaultValue) {
|
||||
return new EnumField<>(key, label, defaultValue, defaultValue.getDeclaringClass());
|
||||
}
|
||||
|
||||
private static class NumberField<T extends Number & Comparable<T>> extends ConditionField<T> {
|
||||
private T min;
|
||||
private T max;
|
||||
|
||||
public NumberField(String key, String label, Class<T> type, T defaultValue, T min, T max) {
|
||||
super(key, label, type, defaultValue);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T value) {
|
||||
if (value.compareTo(min) < 0) {
|
||||
this.value = min;
|
||||
} else if (value.compareTo(max) > 0) {
|
||||
this.value = max;
|
||||
} else {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public NumberField<T> min(T value) {
|
||||
this.min = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NumberField<T> max(T value) {
|
||||
this.max = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(NBTTagCompound nbt) {
|
||||
if (value instanceof Integer) nbt.setInteger(key, (Integer) value);
|
||||
else if (value instanceof Float) nbt.setFloat(key, (Float) value);
|
||||
else if (value instanceof Double) nbt.setDouble(key, (Double) value);
|
||||
else if (value instanceof Long) nbt.setLong(key, (Long) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readNBT(NBTTagCompound nbt) {
|
||||
if (!nbt.hasKey(key)) return;
|
||||
T v;
|
||||
if (type == Integer.class) v = (T) (Integer) nbt.getInteger(key);
|
||||
else if (type == Float.class) v = (T) (Float) nbt.getFloat(key);
|
||||
else if (type == Double.class) v = (T) (Double) nbt.getDouble(key);
|
||||
else if (type == Long.class) v = (T) (Long) nbt.getLong(key);
|
||||
else return;
|
||||
setValue(v);
|
||||
}
|
||||
}
|
||||
|
||||
private static class StringField extends ConditionField<String> {
|
||||
public StringField(String key, String label, String defaultValue) {
|
||||
super(key, label, String.class, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(NBTTagCompound nbt) {
|
||||
nbt.setString(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(NBTTagCompound nbt) {
|
||||
setValue(nbt.getString(key));
|
||||
}
|
||||
}
|
||||
|
||||
private static class BoolField extends ConditionField<Boolean> {
|
||||
public BoolField(String key, String label, boolean defaultValue) {
|
||||
super(key, label, Boolean.class, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(NBTTagCompound nbt) {
|
||||
nbt.setBoolean(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(NBTTagCompound nbt) {
|
||||
setValue(nbt.getBoolean(key));
|
||||
}
|
||||
}
|
||||
|
||||
private static class EnumField<E extends Enum<E>> extends ConditionField<E> {
|
||||
private final E[] options;
|
||||
|
||||
public EnumField(String key, String label, E defaultValue, Class<E> enumClass) {
|
||||
super(key, label, enumClass, defaultValue);
|
||||
this.options = enumClass.getEnumConstants();
|
||||
}
|
||||
|
||||
public E[] getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(NBTTagCompound nbt) {
|
||||
nbt.setString(key, value.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(NBTTagCompound nbt) {
|
||||
if (!nbt.hasKey(key)) return;
|
||||
try {
|
||||
setValue(Enum.valueOf(type, nbt.getString(key)));
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package kamkeel.npcs.controllers.data.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.AbilityController;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.LogWriter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface IAbilityCondition {
|
||||
/**
|
||||
* Check if this condition is met.
|
||||
*
|
||||
* @param caster The entity that would use the ability (NPC or Player)
|
||||
* @param target The current target (may be null for self-targeting abilities or players)
|
||||
* @return true if the condition is satisfied
|
||||
*/
|
||||
boolean check(EntityLivingBase caster, EntityLivingBase target);
|
||||
|
||||
UserType getUserType();
|
||||
|
||||
String getTypeId();
|
||||
|
||||
List<ConditionField<?>> getFields();
|
||||
|
||||
default NBTTagCompound writeNBT() {
|
||||
NBTTagCompound nbt = new NBTTagCompound();
|
||||
nbt.setInteger("userType", getUserType().ordinal());
|
||||
nbt.setString("type", getTypeId());
|
||||
for (ConditionField<?> field : getFields()) {
|
||||
field.writeNBT(nbt);
|
||||
}
|
||||
return nbt;
|
||||
}
|
||||
|
||||
default void readNBT(NBTTagCompound nbt) {
|
||||
for (ConditionField<?> field : getFields()) {
|
||||
field.readNBT(nbt);
|
||||
}
|
||||
}
|
||||
|
||||
static IAbilityCondition fromNBT(NBTTagCompound nbt) {
|
||||
String typeId = nbt.getString("type");
|
||||
Supplier<IAbilityCondition> factory = AbilityController.Instance.getConditionType(typeId);
|
||||
if (factory == null) {
|
||||
LogWriter.info("AbilityController: Unknown condition type: " + typeId);
|
||||
return null;
|
||||
}
|
||||
IAbilityCondition condition = factory.get();
|
||||
condition.readNBT(nbt);
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
class ConditionHPAbove implements IAbilityCondition {
|
||||
ConditionField<Float> threshold = ConditionField.floatField("threshold", "threshold", 0.5f);
|
||||
|
||||
public ConditionHPAbove() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(EntityLivingBase caster, EntityLivingBase target) {
|
||||
return caster.getHealth() / caster.getMaxHealth() > threshold.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserType getUserType() {
|
||||
return UserType.BOTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeId() {
|
||||
return "hp_above";
|
||||
}
|
||||
|
||||
public float getThreshold() {
|
||||
return threshold.getValue();
|
||||
}
|
||||
|
||||
public void setThreshold(float threshold) {
|
||||
this.threshold.setValue(threshold);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConditionField<?>> getFields() {
|
||||
return Arrays.asList(
|
||||
threshold
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user