mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 03:47:27 +00:00
Large Ability changes, cleanup, langs, fixes.
This commit is contained in:
1 parent
c7d04cb9d3
commit
fdb2ff98d8
37 files changed
+517
-214
No files matched your search
+1
-1
Submodule src/api updated: 3ac76848d3...5cd0888511.
@@ -12,9 +12,10 @@ import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.DataAbilities;
|
||||
import noppes.npcs.NpcDamageSource;
|
||||
import noppes.npcs.api.INbt;
|
||||
import noppes.npcs.api.ability.IAbility;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
import noppes.npcs.scripted.NpcAPI;
|
||||
@@ -31,7 +32,7 @@ public abstract class Ability implements IAbility {
|
||||
|
||||
protected String id;
|
||||
protected String name;
|
||||
protected String typeId; // e.g., "cnpc:slam", "mymod:custom_ability"
|
||||
protected String typeId; // e.g., "ability.cnpc.slam" (also used as lang key)
|
||||
|
||||
// Selection
|
||||
protected int weight = 10;
|
||||
@@ -136,7 +137,7 @@ public abstract class Ability implements IAbility {
|
||||
|
||||
// Apply damage
|
||||
if (finalDamage > 0) {
|
||||
hitEntity.attackEntityFrom(DamageSource.causeMobDamage(npc), finalDamage);
|
||||
hitEntity.attackEntityFrom(new NpcDamageSource("mob", npc), finalDamage);
|
||||
}
|
||||
|
||||
// Apply knockback if any
|
||||
|
||||
@@ -22,6 +22,7 @@ public class AbilityController implements IAbilityHandler {
|
||||
public static AbilityController Instance;
|
||||
|
||||
private final Map<String, Supplier<Ability>> factories = new LinkedHashMap<>();
|
||||
private final Map<String, Supplier<Ability>> factoriesByTypeId = new LinkedHashMap<>();
|
||||
private final Map<String, Ability> savedAbilities = new LinkedHashMap<>();
|
||||
|
||||
public AbilityController() {
|
||||
@@ -177,12 +178,13 @@ public class AbilityController implements IAbilityHandler {
|
||||
|
||||
@Override
|
||||
public String[] getTypes() {
|
||||
return factories.keySet().toArray(new String[0]);
|
||||
// Return the ability typeIds (lang keys), not the factory keys
|
||||
return factoriesByTypeId.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasType(String typeId) {
|
||||
return factories.containsKey(typeId);
|
||||
return factories.containsKey(typeId) || factoriesByTypeId.containsKey(typeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -208,14 +210,19 @@ public class AbilityController implements IAbilityHandler {
|
||||
* Register a new ability type.
|
||||
* Call during FMLInitializationEvent.
|
||||
*
|
||||
* @param typeId The unique type ID (e.g., "cnpc:slam", "mymod:custom_ability")
|
||||
* @param factoryKey The factory key (e.g., "cnpc:slam", "mymod:custom_ability")
|
||||
* @param factory Factory lambda that creates a new instance
|
||||
*/
|
||||
public void registerType(String typeId, Supplier<Ability> factory) {
|
||||
if (factories.containsKey(typeId)) {
|
||||
LogWriter.info("AbilityController: Overwriting existing ability type: " + typeId);
|
||||
public void registerType(String factoryKey, Supplier<Ability> factory) {
|
||||
if (factories.containsKey(factoryKey)) {
|
||||
LogWriter.info("AbilityController: Overwriting existing ability type: " + factoryKey);
|
||||
}
|
||||
factories.put(typeId, factory);
|
||||
factories.put(factoryKey, factory);
|
||||
|
||||
// Also register by the ability's actual typeId (lang key)
|
||||
Ability temp = factory.get();
|
||||
String abilityTypeId = temp.getTypeId();
|
||||
factoriesByTypeId.put(abilityTypeId, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,6 +236,10 @@ public class AbilityController implements IAbilityHandler {
|
||||
|
||||
String typeId = nbt.getString("typeId");
|
||||
Supplier<Ability> factory = factories.get(typeId);
|
||||
if (factory == null) {
|
||||
// Try looking up by ability typeId (lang key)
|
||||
factory = factoriesByTypeId.get(typeId);
|
||||
}
|
||||
if (factory == null) {
|
||||
LogWriter.info("AbilityController: Unknown ability type: " + typeId);
|
||||
return null;
|
||||
@@ -241,15 +252,19 @@ public class AbilityController implements IAbilityHandler {
|
||||
|
||||
/**
|
||||
* Create a new empty ability of the given type.
|
||||
* @param factoryKey The factory key (e.g., "cnpc:slam") or the ability typeId (e.g., "ability.cnpc.slam")
|
||||
*/
|
||||
public Ability create(String typeId) {
|
||||
Supplier<Ability> factory = factories.get(typeId);
|
||||
public Ability create(String factoryKey) {
|
||||
// Try direct lookup first (factory key)
|
||||
Supplier<Ability> factory = factories.get(factoryKey);
|
||||
if (factory == null) {
|
||||
// Try looking up by ability typeId
|
||||
factory = factoriesByTypeId.get(factoryKey);
|
||||
}
|
||||
if (factory == null) {
|
||||
return null;
|
||||
}
|
||||
Ability ability = factory.get();
|
||||
ability.typeId = typeId;
|
||||
return ability;
|
||||
return factory.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityBeam;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -45,7 +45,7 @@ public class AbilityBeam extends Ability {
|
||||
private transient Set<Integer> hitThisTick = new HashSet<>();
|
||||
|
||||
public AbilityBeam() {
|
||||
this.typeId = "cnpc:beam";
|
||||
this.typeId = "ability.cnpc.beam";
|
||||
this.name = "Beam";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 15.0f;
|
||||
|
||||
@@ -14,7 +14,7 @@ import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityCharge;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -43,7 +43,7 @@ public class AbilityCharge extends Ability {
|
||||
private transient float lockedYaw;
|
||||
|
||||
public AbilityCharge() {
|
||||
this.typeId = "cnpc:charge";
|
||||
this.typeId = "ability.cnpc.charge";
|
||||
this.name = "Charge";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 20.0f;
|
||||
|
||||
@@ -12,7 +12,7 @@ import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityCutter;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -58,7 +58,7 @@ public class AbilityCutter extends Ability {
|
||||
private transient float currentRotation = 0.0f;
|
||||
|
||||
public AbilityCutter() {
|
||||
this.typeId = "cnpc:cutter";
|
||||
this.typeId = "ability.cnpc.cutter";
|
||||
this.name = "Cutter";
|
||||
this.targetingMode = TargetingMode.AOE_SELF;
|
||||
this.maxRange = 8.0f;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityDash;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -82,7 +82,7 @@ public class AbilityDash extends Ability {
|
||||
private transient DashDirection chosenDirection;
|
||||
|
||||
public AbilityDash() {
|
||||
this.typeId = "cnpc:dash";
|
||||
this.typeId = "ability.cnpc.dash";
|
||||
this.name = "Dash";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 20.0f;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityGuard;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -36,7 +36,7 @@ public class AbilityGuard extends Ability {
|
||||
private transient boolean counterTriggered;
|
||||
|
||||
public AbilityGuard() {
|
||||
this.typeId = "cnpc:guard";
|
||||
this.typeId = "ability.cnpc.guard";
|
||||
this.name = "Guard";
|
||||
this.targetingMode = TargetingMode.SELF;
|
||||
this.lockMovement = true;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityHazard;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -77,7 +77,7 @@ public class AbilityHazard extends Ability {
|
||||
private transient Set<Integer> damagedThisTick = new HashSet<>();
|
||||
|
||||
public AbilityHazard() {
|
||||
this.typeId = "cnpc:hazard";
|
||||
this.typeId = "ability.cnpc.hazard";
|
||||
this.name = "Hazard";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 15.0f;
|
||||
|
||||
@@ -10,7 +10,7 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityHeal;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -36,7 +36,7 @@ public class AbilityHeal extends Ability {
|
||||
private transient List<EntityLivingBase> healedAllies = new ArrayList<>();
|
||||
|
||||
public AbilityHeal() {
|
||||
this.typeId = "cnpc:heal";
|
||||
this.typeId = "ability.cnpc.heal";
|
||||
this.name = "Heal";
|
||||
this.targetingMode = TargetingMode.SELF;
|
||||
this.lockMovement = true;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityHeavyHit;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -28,7 +28,7 @@ public class AbilityHeavyHit extends Ability {
|
||||
private int stunTicks = 40;
|
||||
|
||||
public AbilityHeavyHit() {
|
||||
this.typeId = "cnpc:heavy_hit";
|
||||
this.typeId = "ability.cnpc.heavy_hit";
|
||||
this.name = "Heavy Hit";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 3.0f;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityOrb;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -53,7 +53,7 @@ public class AbilityOrb extends Ability {
|
||||
private transient int ticksAlive = 0;
|
||||
|
||||
public AbilityOrb() {
|
||||
this.typeId = "cnpc:orb";
|
||||
this.typeId = "ability.cnpc.orb";
|
||||
this.name = "Orb";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 25.0f;
|
||||
|
||||
@@ -10,7 +10,7 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityProjectile;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -34,7 +34,7 @@ public class AbilityProjectile extends Ability {
|
||||
private float homingStrength = 0.1f;
|
||||
|
||||
public AbilityProjectile() {
|
||||
this.typeId = "cnpc:projectile";
|
||||
this.typeId = "ability.cnpc.projectile";
|
||||
this.name = "Projectile";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.minRange = 5.0f;
|
||||
|
||||
@@ -12,7 +12,7 @@ import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityShockwave;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -37,7 +37,7 @@ public class AbilityShockwave extends Ability {
|
||||
private transient boolean executed = false;
|
||||
|
||||
public AbilityShockwave() {
|
||||
this.typeId = "cnpc:shockwave";
|
||||
this.typeId = "ability.cnpc.shockwave";
|
||||
this.name = "Shockwave";
|
||||
this.targetingMode = TargetingMode.AOE_SELF;
|
||||
this.maxRange = 15.0f;
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilitySlam;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -47,7 +47,7 @@ public class AbilitySlam extends Ability {
|
||||
private transient int maxAirTicks = 60; // Timeout to prevent stuck in air
|
||||
|
||||
public AbilitySlam() {
|
||||
this.typeId = "cnpc:slam";
|
||||
this.typeId = "ability.cnpc.slam";
|
||||
this.name = "Slam";
|
||||
this.targetingMode = TargetingMode.AOE_SELF; // Can also be AOE_TARGET to leap to target
|
||||
this.windUpTicks = 30;
|
||||
@@ -127,6 +127,9 @@ public class AbilitySlam extends Ability {
|
||||
hasLanded = false;
|
||||
airTicks = 0;
|
||||
|
||||
// Reset fall distance to prevent fall damage during slam
|
||||
npc.fallDistance = 0;
|
||||
|
||||
// Calculate and apply leap velocity
|
||||
launchTowardTarget(npc);
|
||||
}
|
||||
@@ -230,6 +233,9 @@ public class AbilitySlam extends Ability {
|
||||
|
||||
airTicks++;
|
||||
|
||||
// Continuously reset fall distance during slam to prevent fall damage
|
||||
npc.fallDistance = 0;
|
||||
|
||||
// Check for landing
|
||||
if (npc.onGround && airTicks > 3) {
|
||||
// Landed!
|
||||
@@ -258,6 +264,9 @@ public class AbilitySlam extends Ability {
|
||||
hasLanded = true;
|
||||
npc.setNpcJumpingState(false);
|
||||
|
||||
// Reset fall distance to prevent fall damage on landing
|
||||
npc.fallDistance = 0;
|
||||
|
||||
// Stop horizontal momentum
|
||||
npc.motionX = 0;
|
||||
npc.motionZ = 0;
|
||||
@@ -415,9 +424,9 @@ public class AbilitySlam extends Ability {
|
||||
|
||||
@Override
|
||||
public void readTypeNBT(NBTTagCompound nbt) {
|
||||
damage = nbt.getFloat("damage");
|
||||
radius = nbt.getFloat("radius");
|
||||
knockbackStrength = nbt.getFloat("knockback");
|
||||
damage = nbt.hasKey("damage") ? nbt.getFloat("damage") : 20.0f;
|
||||
radius = nbt.hasKey("radius") ? nbt.getFloat("radius") : 5.0f;
|
||||
knockbackStrength = nbt.hasKey("knockback") ? nbt.getFloat("knockback") : 1.5f;
|
||||
leapSpeed = nbt.hasKey("leapSpeed") ? nbt.getFloat("leapSpeed") : 1.0f;
|
||||
minLeapDistance = nbt.hasKey("minLeapDistance") ? nbt.getFloat("minLeapDistance") : 2.0f;
|
||||
maxLeapDistance = nbt.hasKey("maxLeapDistance") ? nbt.getFloat("maxLeapDistance") : 15.0f;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityTeleport;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -60,7 +60,7 @@ public class AbilityTeleport extends Ability {
|
||||
private transient int ticksSinceLastBlink = 0;
|
||||
|
||||
public AbilityTeleport() {
|
||||
this.typeId = "cnpc:teleport";
|
||||
this.typeId = "ability.cnpc.teleport";
|
||||
this.name = "Teleport";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 30.0f;
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityTrap;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -68,7 +68,7 @@ public class AbilityTrap extends Ability {
|
||||
private transient Set<UUID> triggeredEntities = new HashSet<>();
|
||||
|
||||
public AbilityTrap() {
|
||||
this.typeId = "cnpc:trap";
|
||||
this.typeId = "ability.cnpc.trap";
|
||||
this.name = "Trap";
|
||||
this.targetingMode = TargetingMode.AGGRO_TARGET;
|
||||
this.maxRange = 15.0f;
|
||||
|
||||
@@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityVortex;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
@@ -47,7 +47,7 @@ public class AbilityVortex extends Ability {
|
||||
private transient boolean pullComplete = false;
|
||||
|
||||
public AbilityVortex() {
|
||||
this.typeId = "cnpc:vortex";
|
||||
this.typeId = "ability.cnpc.vortex";
|
||||
this.name = "Vortex";
|
||||
this.targetingMode = TargetingMode.AOE_SELF;
|
||||
this.maxRange = 15.0f;
|
||||
|
||||
@@ -17,6 +17,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
@@ -31,6 +32,9 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
// All available ability types (typeId -> index)
|
||||
private final HashMap<String, Integer> allAbilityTypes = new HashMap<>();
|
||||
|
||||
// Display name to typeId mapping for the available types scroll
|
||||
private final HashMap<String, String> displayNameToTypeId = new HashMap<>();
|
||||
|
||||
// NPC's current abilities
|
||||
private final List<Ability> npcAbilities = new ArrayList<>();
|
||||
|
||||
@@ -131,18 +135,20 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
if (id == 70) {
|
||||
if (availableTypesScroll.hasSelected()) {
|
||||
String displayName = availableTypesScroll.getSelected();
|
||||
String typeId = getTypeIdFromDisplayName(displayName);
|
||||
Ability newAbility = AbilityController.Instance.create(typeId);
|
||||
if (newAbility != null) {
|
||||
newAbility.setId("ability_" + System.currentTimeMillis());
|
||||
// Don't set custom name - let it default to type name
|
||||
npcAbilities.add(newAbility);
|
||||
// Auto-select the newly added ability
|
||||
selectedAbilityIndex = npcAbilities.size() - 1;
|
||||
updateNpcAbilitiesList();
|
||||
selectAbilityByIndex(selectedAbilityIndex);
|
||||
initGui();
|
||||
save();
|
||||
String typeId = displayNameToTypeId.get(displayName);
|
||||
if (typeId != null) {
|
||||
Ability newAbility = AbilityController.Instance.create(typeId);
|
||||
if (newAbility != null) {
|
||||
newAbility.setId(UUID.randomUUID().toString());
|
||||
// Don't set custom name - let it default to type name
|
||||
npcAbilities.add(newAbility);
|
||||
// Auto-select the newly added ability
|
||||
selectedAbilityIndex = npcAbilities.size() - 1;
|
||||
updateNpcAbilitiesList();
|
||||
selectAbilityByIndex(selectedAbilityIndex);
|
||||
initGui();
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -274,27 +280,18 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
|
||||
private List<String> getFilteredTypeList() {
|
||||
List<String> list = new ArrayList<>();
|
||||
displayNameToTypeId.clear();
|
||||
for (String typeId : allAbilityTypes.keySet()) {
|
||||
String displayName = getDisplayName(typeId);
|
||||
if (search.isEmpty() || typeId.toLowerCase().contains(search) || displayName.toLowerCase().contains(search)) {
|
||||
String displayName = I18n.format(typeId);
|
||||
// Search matches either the display name or the typeId
|
||||
if (search.isEmpty() || displayName.toLowerCase().contains(search) || typeId.toLowerCase().contains(search)) {
|
||||
list.add(displayName);
|
||||
displayNameToTypeId.put(displayName, typeId);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the typeId from a display name shown in the available types list.
|
||||
*/
|
||||
private String getTypeIdFromDisplayName(String displayName) {
|
||||
for (String typeId : allAbilityTypes.keySet()) {
|
||||
if (getDisplayName(typeId).equals(displayName)) {
|
||||
return typeId;
|
||||
}
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
private void updateNpcAbilitiesList() {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (int i = 0; i < npcAbilities.size(); i++) {
|
||||
@@ -335,35 +332,10 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
|
||||
/**
|
||||
* Gets the localized display name for an ability type.
|
||||
* Uses lang key "ability.type.cnpc_slam" for "cnpc:slam"
|
||||
* The typeId IS the lang key (e.g., "ability.cnpc.slam").
|
||||
*/
|
||||
private String getDisplayName(String typeId) {
|
||||
// Convert "cnpc:slam" to lang key "ability.type.cnpc_slam"
|
||||
String langKey = "ability.type." + typeId.replace(":", "_");
|
||||
String translated = I18n.format(langKey);
|
||||
|
||||
// If translation exists and is different from key, use it
|
||||
if (!translated.equals(langKey)) {
|
||||
return translated;
|
||||
}
|
||||
|
||||
// Fallback: Convert "cnpc:slam" to "Slam"
|
||||
if (typeId.contains(":")) {
|
||||
String name = typeId.substring(typeId.indexOf(":") + 1);
|
||||
name = name.replace("_", " ");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String word : name.split(" ")) {
|
||||
if (word.length() > 0) {
|
||||
sb.append(Character.toUpperCase(word.charAt(0)));
|
||||
if (word.length() > 1) {
|
||||
sb.append(word.substring(1));
|
||||
}
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
return typeId;
|
||||
return I18n.format(typeId);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
@@ -386,7 +358,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
*/
|
||||
public void loadAbility(Ability loadedAbility) {
|
||||
if (loadedAbility != null) {
|
||||
loadedAbility.setId("ability_" + System.currentTimeMillis());
|
||||
loadedAbility.setId(UUID.randomUUID().toString());
|
||||
npcAbilities.add(loadedAbility);
|
||||
// Auto-select the newly added ability
|
||||
selectedAbilityIndex = npcAbilities.size() - 1;
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
package noppes.npcs.client.gui.advanced;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.Condition;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
import kamkeel.npcs.controllers.data.ability.telegraph.TelegraphType;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.gui.SubGuiColorSelector;
|
||||
import noppes.npcs.client.gui.select.GuiAnimationSelection;
|
||||
import noppes.npcs.client.gui.select.GuiSoundSelection;
|
||||
import noppes.npcs.client.gui.util.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base SubGui for editing ability configuration with tabbed interface.
|
||||
* Uses GuiMenuTopButton for navigation tabs.
|
||||
*
|
||||
* Tabs:
|
||||
* - General: Type ID, Name, Weight, Lock Movement, Interruptible, Timing (Windup/Active/Recovery/Cooldown)
|
||||
* - General: Name, Weight, Lock Movement, Interruptible, Timing
|
||||
* - Type: Type-specific settings per Ability (override in subclasses)
|
||||
* - Target: Min/Max Range, Targeting Mode, Conditions
|
||||
* - Target: Min/Max Range, Targeting Mode, Conditions (up to 3)
|
||||
* - Effects: Sounds, Animations, Telegraph settings, Colors
|
||||
*
|
||||
* Subclasses should override initTypeTab() and handleTypeButton()/handleTypeTextField()
|
||||
@@ -57,6 +62,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
protected float minRange;
|
||||
protected float maxRange;
|
||||
protected TargetingMode targetingMode;
|
||||
protected List<Condition> conditions;
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// CACHED VALUES - Effects Tab
|
||||
@@ -77,6 +83,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
protected int editingColorId = 0;
|
||||
protected int editingSoundId = 0;
|
||||
protected int editingAnimationId = 0;
|
||||
protected int editingConditionIndex = -1;
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// ABILITY TYPE FEATURES
|
||||
@@ -106,6 +113,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
this.minRange = ability.getMinRange();
|
||||
this.maxRange = ability.getMaxRange();
|
||||
this.targetingMode = ability.getTargetingMode();
|
||||
this.conditions = new ArrayList<>(ability.getConditions());
|
||||
|
||||
// Effects
|
||||
this.windUpSound = ability.getWindUpSound();
|
||||
@@ -125,8 +133,8 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
this.hasTypeSettings = ability.hasTypeSettings();
|
||||
|
||||
setBackground("menubg.png");
|
||||
xSize = 420;
|
||||
ySize = 216;
|
||||
xSize = 356;
|
||||
ySize = 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,11 +166,11 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
effectsTab.active = (activeTab == TAB_EFFECTS);
|
||||
addTopButton(effectsTab);
|
||||
|
||||
// Close button on top right
|
||||
GuiMenuTopButton closeBtn = new GuiMenuTopButton(67, guiLeft + xSize - 22, guiTop - 17, "X");
|
||||
// Close button (X) in top menu bar - use -1000 to avoid any ID conflicts
|
||||
GuiMenuTopButton closeBtn = new GuiMenuTopButton(-1000, guiLeft + xSize - 22, guiTop - 17, "X");
|
||||
addTopButton(closeBtn);
|
||||
|
||||
int contentY = guiTop + 4;
|
||||
int contentY = guiTop + 5;
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// TAB CONTENT
|
||||
@@ -183,70 +191,66 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// BOTTOM ROW - Enabled toggle and Done button
|
||||
// BOTTOM ROW - Enabled toggle
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
addLabel(new GuiNpcLabel(99, "gui.enabled", guiLeft + 8, guiTop + ySize - 19));
|
||||
GuiNpcButton enabledBtn = new GuiNpcButton(2, guiLeft + 55, guiTop + ySize - 24, 50, 20, new String[]{"gui.no", "gui.yes"}, enabled ? 1 : 0);
|
||||
addLabel(new GuiNpcLabel(99, "gui.enabled", guiLeft + 8, guiTop + ySize - 18));
|
||||
GuiNpcButton enabledBtn = new GuiNpcButton(2, guiLeft + 55, guiTop + ySize - 24, 40, 20, new String[]{"gui.no", "gui.yes"}, enabled ? 1 : 0);
|
||||
enabledBtn.setTextColor(enabled ? 0x00FF00 : 0xFF0000);
|
||||
addButton(enabledBtn);
|
||||
|
||||
addButton(new GuiNpcButton(66, guiLeft + xSize - 65, guiTop + ySize - 24, 60, 20, "gui.done"));
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// GENERAL TAB
|
||||
// Type ID (label), Name, Weight, Lock Movement, Interruptible,
|
||||
// Ticks: Windup, Active, Recovery, Cooldown
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
private void initGeneralTab(int startY) {
|
||||
int y = startY;
|
||||
int col1LabelX = guiLeft + 8;
|
||||
int col1FieldX = guiLeft + 75;
|
||||
int col2LabelX = guiLeft + 215;
|
||||
int col2FieldX = guiLeft + 290;
|
||||
int col1FieldX = guiLeft + 70;
|
||||
int col2LabelX = guiLeft + 180;
|
||||
int col2FieldX = guiLeft + 248;
|
||||
|
||||
// Row 1: Type ID (read-only) + Name
|
||||
addLabel(new GuiNpcLabel(1, "ability.typeId", col1LabelX, y + 5));
|
||||
// Row 1: Type (read-only) + Name
|
||||
addLabel(new GuiNpcLabel(1, "gui.type", col1LabelX, y + 5));
|
||||
addLabel(new GuiNpcLabel(2, ability.getTypeId(), col1FieldX, y + 5));
|
||||
|
||||
addLabel(new GuiNpcLabel(3, "gui.name", col2LabelX, y + 5));
|
||||
GuiNpcTextField nameField = new GuiNpcTextField(1, this, fontRendererObj, col2FieldX, y, 120, 20, name);
|
||||
GuiNpcTextField nameField = new GuiNpcTextField(1, this, fontRendererObj, col2FieldX, y, 100, 20, name);
|
||||
addTextField(nameField);
|
||||
|
||||
y += 24;
|
||||
|
||||
// Row 2: Weight + Lock Movement
|
||||
addLabel(new GuiNpcLabel(4, "ability.weight", col1LabelX, y + 5));
|
||||
GuiNpcTextField weightField = new GuiNpcTextField(3, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf(weight));
|
||||
GuiNpcTextField weightField = new GuiNpcTextField(3, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf(weight));
|
||||
weightField.setIntegersOnly();
|
||||
weightField.setMinMaxDefault(1, 1000, 10);
|
||||
addTextField(weightField);
|
||||
|
||||
addLabel(new GuiNpcLabel(5, "ability.lockMove", col2LabelX, y + 5));
|
||||
addButton(new GuiNpcButton(16, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, lockMovement ? 1 : 0));
|
||||
addButton(new GuiNpcButton(16, col2FieldX, y, 40, 20, new String[]{"gui.no", "gui.yes"}, lockMovement ? 1 : 0));
|
||||
|
||||
y += 24;
|
||||
|
||||
// Row 3: Interruptible (no threshold anymore - just a toggle)
|
||||
// Row 3: Interruptible
|
||||
addLabel(new GuiNpcLabel(6, "ability.interruptible", col1LabelX, y + 5));
|
||||
addButton(new GuiNpcButton(14, col1FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, interruptible ? 1 : 0));
|
||||
addButton(new GuiNpcButton(14, guiLeft + 85, y, 40, 20, new String[]{"gui.no", "gui.yes"}, interruptible ? 1 : 0));
|
||||
|
||||
y += 30;
|
||||
y += 28;
|
||||
|
||||
// Separator - Timing section header
|
||||
addLabel(new GuiNpcLabel(7, "§n" + "ability.timing", col1LabelX, y));
|
||||
addLabel(new GuiNpcLabel(7, "ability.timing", col1LabelX, y));
|
||||
y += 14;
|
||||
|
||||
// Row 4: Windup Ticks + Active Ticks
|
||||
addLabel(new GuiNpcLabel(10, "ability.windup", col1LabelX, y + 5));
|
||||
GuiNpcTextField windupField = new GuiNpcTextField(11, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf(windUpTicks));
|
||||
GuiNpcTextField windupField = new GuiNpcTextField(11, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf(windUpTicks));
|
||||
windupField.setIntegersOnly();
|
||||
windupField.setMinMaxDefault(0, 1000, 20);
|
||||
addTextField(windupField);
|
||||
|
||||
addLabel(new GuiNpcLabel(11, "ability.active", col2LabelX, y + 5));
|
||||
GuiNpcTextField activeField = new GuiNpcTextField(12, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(activeTicks));
|
||||
GuiNpcTextField activeField = new GuiNpcTextField(12, this, fontRendererObj, col2FieldX, y, 40, 20, String.valueOf(activeTicks));
|
||||
activeField.setIntegersOnly();
|
||||
activeField.setMinMaxDefault(1, 1000, 10);
|
||||
addTextField(activeField);
|
||||
@@ -255,13 +259,13 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
|
||||
// Row 5: Recovery Ticks + Cooldown Ticks
|
||||
addLabel(new GuiNpcLabel(12, "ability.recovery", col1LabelX, y + 5));
|
||||
GuiNpcTextField recoveryField = new GuiNpcTextField(13, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf(recoveryTicks));
|
||||
GuiNpcTextField recoveryField = new GuiNpcTextField(13, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf(recoveryTicks));
|
||||
recoveryField.setIntegersOnly();
|
||||
recoveryField.setMinMaxDefault(0, 1000, 20);
|
||||
addTextField(recoveryField);
|
||||
|
||||
addLabel(new GuiNpcLabel(13, "ability.cooldown", col2LabelX, y + 5));
|
||||
GuiNpcTextField cooldownField = new GuiNpcTextField(10, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(cooldownTicks));
|
||||
GuiNpcTextField cooldownField = new GuiNpcTextField(10, this, fontRendererObj, col2FieldX, y, 40, 20, String.valueOf(cooldownTicks));
|
||||
cooldownField.setIntegersOnly();
|
||||
cooldownField.setMinMaxDefault(0, 10000, 100);
|
||||
addTextField(cooldownField);
|
||||
@@ -301,25 +305,24 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// TARGET TAB
|
||||
// Min/Max Range, Targeting Mode, Conditions
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
private void initTargetTab(int startY) {
|
||||
int y = startY;
|
||||
int col1LabelX = guiLeft + 8;
|
||||
int col1FieldX = guiLeft + 85;
|
||||
int col2LabelX = guiLeft + 215;
|
||||
int col2FieldX = guiLeft + 290;
|
||||
int col1FieldX = guiLeft + 70;
|
||||
int col2LabelX = guiLeft + 180;
|
||||
int col2FieldX = guiLeft + 248;
|
||||
|
||||
// Row 1: Min Range + Max Range
|
||||
addLabel(new GuiNpcLabel(20, "ability.minRange", col1LabelX, y + 5));
|
||||
GuiNpcTextField minRangeField = new GuiNpcTextField(5, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf((int) minRange));
|
||||
GuiNpcTextField minRangeField = new GuiNpcTextField(5, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf((int) minRange));
|
||||
minRangeField.setIntegersOnly();
|
||||
minRangeField.setMinMaxDefault(0, 100, 0);
|
||||
addTextField(minRangeField);
|
||||
|
||||
addLabel(new GuiNpcLabel(21, "ability.maxRange", col2LabelX, y + 5));
|
||||
GuiNpcTextField maxRangeField = new GuiNpcTextField(6, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf((int) maxRange));
|
||||
GuiNpcTextField maxRangeField = new GuiNpcTextField(6, this, fontRendererObj, col2FieldX, y, 40, 20, String.valueOf((int) maxRange));
|
||||
maxRangeField.setIntegersOnly();
|
||||
maxRangeField.setMinMaxDefault(1, 100, 20);
|
||||
addTextField(maxRangeField);
|
||||
@@ -331,21 +334,67 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
if (!targetingModeLocked) {
|
||||
String[] targetingModes = getAvailableTargetingModes();
|
||||
int selectedIndex = getTargetingModeIndex(targetingMode);
|
||||
addButton(new GuiNpcButton(4, col1FieldX, y, 100, 20, targetingModes, selectedIndex));
|
||||
addButton(new GuiNpcButton(4, col1FieldX, y, 90, 20, targetingModes, selectedIndex));
|
||||
} else {
|
||||
// Show as label if locked
|
||||
String modeName = "ability.target." + targetingMode.name().toLowerCase();
|
||||
addLabel(new GuiNpcLabel(23, modeName, col1FieldX, y + 5));
|
||||
}
|
||||
|
||||
y += 30;
|
||||
y += 28;
|
||||
|
||||
// Separator - Conditions section header
|
||||
addLabel(new GuiNpcLabel(24, "§n" + "ability.conditions", col1LabelX, y));
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// CONDITIONS SECTION (up to 3)
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
addLabel(new GuiNpcLabel(24, "ability.conditions", col1LabelX, y));
|
||||
y += 14;
|
||||
|
||||
// TODO: Add conditions UI here
|
||||
addLabel(new GuiNpcLabel(25, "ability.conditionsNote", col1LabelX, y + 5));
|
||||
// Display existing conditions (similar to Marks pattern)
|
||||
for (int i = 0; i < conditions.size() && i < 3; i++) {
|
||||
Condition cond = conditions.get(i);
|
||||
String condName = getConditionDisplayName(cond);
|
||||
|
||||
// Condition type button
|
||||
addButton(new GuiNpcButton(50 + i * 10, col1LabelX, y, 140, 20, condName));
|
||||
|
||||
// Edit button
|
||||
addButton(new GuiNpcButton(51 + i * 10, col1LabelX + 145, y, 40, 20, "gui.edit"));
|
||||
|
||||
// Delete button
|
||||
addButton(new GuiNpcButton(52 + i * 10, col1LabelX + 190, y, 20, 20, "X"));
|
||||
|
||||
y += 22;
|
||||
}
|
||||
|
||||
// Add button (if less than 3 conditions)
|
||||
if (conditions.size() < 3) {
|
||||
addButton(new GuiNpcButton(80, col1LabelX, y, 50, 20, "gui.add"));
|
||||
}
|
||||
}
|
||||
|
||||
private String getConditionDisplayName(Condition cond) {
|
||||
if (cond == null) return "None";
|
||||
String typeId = cond.getTypeId();
|
||||
switch (typeId) {
|
||||
case "hp_above":
|
||||
return StatCollector.translateToLocal("condition.hp_above") + " " + (int)(getConditionThreshold(cond) * 100) + "%";
|
||||
case "hp_below":
|
||||
return StatCollector.translateToLocal("condition.hp_below") + " " + (int)(getConditionThreshold(cond) * 100) + "%";
|
||||
case "target_hp_above":
|
||||
return StatCollector.translateToLocal("condition.target_hp_above") + " " + (int)(getConditionThreshold(cond) * 100) + "%";
|
||||
case "target_hp_below":
|
||||
return StatCollector.translateToLocal("condition.target_hp_below") + " " + (int)(getConditionThreshold(cond) * 100) + "%";
|
||||
case "hit_count":
|
||||
Condition.ConditionHitCount hitCount = (Condition.ConditionHitCount) cond;
|
||||
return StatCollector.translateToLocal("condition.hit_count") + ": " + hitCount.getRequiredHits() + "/" + hitCount.getWithinTicks() + "t";
|
||||
default:
|
||||
return typeId;
|
||||
}
|
||||
}
|
||||
|
||||
private float getConditionThreshold(Condition cond) {
|
||||
// Read threshold from NBT since inner classes don't expose it
|
||||
NBTTagCompound nbt = cond.writeNBT();
|
||||
return nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f;
|
||||
}
|
||||
|
||||
private String[] getAvailableTargetingModes() {
|
||||
@@ -373,85 +422,85 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// EFFECTS TAB
|
||||
// Sounds, Animations, Telegraph, Colors
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
private void initEffectsTab(int startY) {
|
||||
int y = startY;
|
||||
int col1LabelX = guiLeft + 8;
|
||||
int col1FieldX = guiLeft + 100;
|
||||
int col1ClearX = guiLeft + 185;
|
||||
int col2LabelX = guiLeft + 215;
|
||||
int col2FieldX = guiLeft + 290;
|
||||
int col1FieldX = guiLeft + 85;
|
||||
int col1ClearX = guiLeft + 160;
|
||||
int col2LabelX = guiLeft + 185;
|
||||
int col2FieldX = guiLeft + 255;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// SOUNDS SECTION
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
addLabel(new GuiNpcLabel(30, "§n" + "ability.sounds", col1LabelX, y));
|
||||
addLabel(new GuiNpcLabel(30, "ability.sounds", col1LabelX, y));
|
||||
y += 14;
|
||||
|
||||
// Wind Up Sound
|
||||
addLabel(new GuiNpcLabel(31, "ability.windUpSound", col1LabelX, y + 5));
|
||||
String windUpSoundDisplay = windUpSound != null && !windUpSound.isEmpty() ? truncateString(windUpSound, 12) : "None";
|
||||
addButton(new GuiNpcButton(30, col1FieldX, y, 80, 20, windUpSoundDisplay));
|
||||
String windUpSoundDisplay = windUpSound != null && !windUpSound.isEmpty() ? truncateString(windUpSound, 10) : StatCollector.translateToLocal("gui.none");
|
||||
addButton(new GuiNpcButton(30, col1FieldX, y, 70, 20, windUpSoundDisplay));
|
||||
addButton(new GuiNpcButton(35, col1ClearX, y, 20, 20, "X"));
|
||||
|
||||
// Active Sound
|
||||
addLabel(new GuiNpcLabel(32, "ability.activeSound", col2LabelX, y + 5));
|
||||
String activeSoundDisplay = activeSound != null && !activeSound.isEmpty() ? truncateString(activeSound, 12) : "None";
|
||||
addButton(new GuiNpcButton(31, col2FieldX, y, 80, 20, activeSoundDisplay));
|
||||
addButton(new GuiNpcButton(36, col2FieldX + 85, y, 20, 20, "X"));
|
||||
String activeSoundDisplay = activeSound != null && !activeSound.isEmpty() ? truncateString(activeSound, 10) : StatCollector.translateToLocal("gui.none");
|
||||
addButton(new GuiNpcButton(31, col2FieldX, y, 70, 20, activeSoundDisplay));
|
||||
addButton(new GuiNpcButton(36, col2FieldX + 75, y, 20, 20, "X"));
|
||||
|
||||
y += 28;
|
||||
y += 26;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// ANIMATIONS SECTION
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
addLabel(new GuiNpcLabel(33, "§n" + "ability.animations", col1LabelX, y));
|
||||
addLabel(new GuiNpcLabel(33, "ability.animations", col1LabelX, y));
|
||||
y += 14;
|
||||
|
||||
// Wind Up Animation
|
||||
addLabel(new GuiNpcLabel(34, "ability.windUpAnim", col1LabelX, y + 5));
|
||||
String windUpAnimName = getAnimationName(windUpAnimationId, true);
|
||||
addButton(new GuiNpcButton(32, col1FieldX, y, 80, 20, windUpAnimName));
|
||||
addButton(new GuiNpcButton(32, col1FieldX, y, 70, 20, windUpAnimName));
|
||||
addButton(new GuiNpcButton(37, col1ClearX, y, 20, 20, "X"));
|
||||
|
||||
// Active Animation
|
||||
addLabel(new GuiNpcLabel(35, "ability.activeAnim", col2LabelX, y + 5));
|
||||
String activeAnimName = getAnimationName(activeAnimationId, false);
|
||||
addButton(new GuiNpcButton(33, col2FieldX, y, 80, 20, activeAnimName));
|
||||
addButton(new GuiNpcButton(38, col2FieldX + 85, y, 20, 20, "X"));
|
||||
addButton(new GuiNpcButton(33, col2FieldX, y, 70, 20, activeAnimName));
|
||||
addButton(new GuiNpcButton(38, col2FieldX + 75, y, 20, 20, "X"));
|
||||
|
||||
y += 28;
|
||||
y += 26;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// TELEGRAPH SECTION (only if supported)
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
if (supportsTelegraph) {
|
||||
addLabel(new GuiNpcLabel(40, "§n" + "ability.telegraph", col1LabelX, y));
|
||||
addLabel(new GuiNpcLabel(40, "ability.telegraph", col1LabelX, y));
|
||||
y += 14;
|
||||
|
||||
// Show Telegraph + Type
|
||||
// Show Telegraph
|
||||
addLabel(new GuiNpcLabel(41, "ability.showTelegraph", col1LabelX, y + 5));
|
||||
addButton(new GuiNpcButton(20, col1FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, showTelegraph ? 1 : 0));
|
||||
addButton(new GuiNpcButton(20, guiLeft + 95, y, 40, 20, new String[]{"gui.no", "gui.yes"}, showTelegraph ? 1 : 0));
|
||||
|
||||
// Telegraph Type (separate column)
|
||||
String typeKey = ability.getTelegraphType().name().toLowerCase();
|
||||
addLabel(new GuiNpcLabel(42, "ability.telegraphType", col2LabelX, y + 5));
|
||||
addLabel(new GuiNpcLabel(43, "ability.telegraph." + typeKey, col2FieldX, y + 5));
|
||||
addLabel(new GuiNpcLabel(42, "ability.telegraphType", guiLeft + 200, y + 5));
|
||||
addLabel(new GuiNpcLabel(43, "ability.telegraph." + typeKey, guiLeft + 280, y + 5));
|
||||
|
||||
y += 24;
|
||||
|
||||
// Colors
|
||||
addLabel(new GuiNpcLabel(44, "ability.windUpColor", col1LabelX, y + 5));
|
||||
String windUpHex = String.format("%06X", windUpColor & 0xFFFFFF);
|
||||
GuiNpcButton windUpColorBtn = new GuiNpcButton(22, col1FieldX, y, 60, 20, windUpHex);
|
||||
GuiNpcButton windUpColorBtn = new GuiNpcButton(22, guiLeft + 95, y, 55, 20, windUpHex);
|
||||
windUpColorBtn.setEnabled(showTelegraph);
|
||||
windUpColorBtn.setTextColor(windUpColor & 0xFFFFFF);
|
||||
addButton(windUpColorBtn);
|
||||
|
||||
addLabel(new GuiNpcLabel(45, "ability.activeColor", col2LabelX, y + 5));
|
||||
addLabel(new GuiNpcLabel(45, "ability.activeColor", guiLeft + 200, y + 5));
|
||||
String activeHex = String.format("%06X", activeColor & 0xFFFFFF);
|
||||
GuiNpcButton activeColorBtn = new GuiNpcButton(24, col2FieldX, y, 60, 20, activeHex);
|
||||
GuiNpcButton activeColorBtn = new GuiNpcButton(24, guiLeft + 280, y, 55, 20, activeHex);
|
||||
activeColorBtn.setEnabled(showTelegraph);
|
||||
activeColorBtn.setTextColor(activeColor & 0xFFFFFF);
|
||||
addButton(activeColorBtn);
|
||||
@@ -469,10 +518,10 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
|
||||
private String getAnimationName(int animId, boolean isWindUp) {
|
||||
if (animId < 0) return "None";
|
||||
if (animId < 0) return StatCollector.translateToLocal("gui.none");
|
||||
String cachedName = isWindUp ? windUpAnimationName : activeAnimationName;
|
||||
if (cachedName != null && !cachedName.isEmpty()) {
|
||||
return truncateString(cachedName, 10);
|
||||
return truncateString(cachedName, 8);
|
||||
}
|
||||
return "ID: " + animId;
|
||||
}
|
||||
@@ -532,6 +581,39 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
}
|
||||
|
||||
// Close button (X in top menu) - use -1000 to avoid any ID conflicts
|
||||
else if (id == -1000) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Target tab - Condition buttons (50-79)
|
||||
else if (id >= 50 && id < 80) {
|
||||
int condIndex = (id - 50) / 10;
|
||||
int action = (id - 50) % 10;
|
||||
|
||||
if (action == 0 || action == 1) {
|
||||
// Click on condition name or Edit button - open edit subgui
|
||||
if (condIndex < conditions.size()) {
|
||||
editingConditionIndex = condIndex;
|
||||
setSubGui(new SubGuiConditionEdit(conditions.get(condIndex)));
|
||||
}
|
||||
} else if (action == 2) {
|
||||
// Delete button
|
||||
if (condIndex < conditions.size()) {
|
||||
conditions.remove(condIndex);
|
||||
initGui();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add condition button
|
||||
else if (id == 80) {
|
||||
if (conditions.size() < 3) {
|
||||
editingConditionIndex = conditions.size();
|
||||
setSubGui(new SubGuiConditionEdit(null));
|
||||
}
|
||||
}
|
||||
|
||||
// Effects tab - Telegraph
|
||||
else if (id == 20) {
|
||||
showTelegraph = ((GuiNpcButton) guibutton).getValue() == 1;
|
||||
@@ -589,17 +671,6 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
else if (id >= 100) {
|
||||
handleTypeButton(id, (GuiNpcButton) guibutton);
|
||||
}
|
||||
|
||||
// Done button
|
||||
else if (id == 66) {
|
||||
applyToAbility();
|
||||
callback.onAbilitySaved(ability);
|
||||
close();
|
||||
}
|
||||
// Close button (X in top right)
|
||||
else if (id == 67) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -680,9 +751,37 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
editingAnimationId = 0;
|
||||
initGui();
|
||||
} else if (subgui instanceof SubGuiConditionEdit) {
|
||||
SubGuiConditionEdit condEdit = (SubGuiConditionEdit) subgui;
|
||||
Condition result = condEdit.getResult();
|
||||
if (result != null && editingConditionIndex >= 0) {
|
||||
if (editingConditionIndex < conditions.size()) {
|
||||
conditions.set(editingConditionIndex, result);
|
||||
} else {
|
||||
conditions.add(result);
|
||||
}
|
||||
}
|
||||
editingConditionIndex = -1;
|
||||
initGui();
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// CLOSE - Save before closing
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Apply all cached values to the ability before closing
|
||||
applyToAbility();
|
||||
|
||||
// Notify callback that ability was saved
|
||||
callback.onAbilitySaved(ability);
|
||||
|
||||
// Close the GUI
|
||||
super.close();
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// APPLY TO ABILITY
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -706,6 +805,12 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
ability.setMaxRange(maxRange);
|
||||
ability.setTargetingMode(targetingMode);
|
||||
|
||||
// Conditions
|
||||
ability.getConditions().clear();
|
||||
for (Condition c : conditions) {
|
||||
ability.addCondition(c);
|
||||
}
|
||||
|
||||
// Effects
|
||||
ability.setWindUpSound(windUpSound);
|
||||
ability.setActiveSound(activeSound);
|
||||
@@ -747,6 +852,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
this.minRange = ability.getMinRange();
|
||||
this.maxRange = ability.getMaxRange();
|
||||
this.targetingMode = ability.getTargetingMode();
|
||||
this.conditions = new ArrayList<>(ability.getConditions());
|
||||
|
||||
this.showTelegraph = ability.isShowTelegraph();
|
||||
this.windUpColor = ability.getWindUpColor();
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
package noppes.npcs.client.gui.advanced;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Condition;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import noppes.npcs.client.gui.util.*;
|
||||
|
||||
/**
|
||||
* SubGui for editing a single ability condition.
|
||||
* Allows selecting condition type and configuring its parameters.
|
||||
*/
|
||||
public class SubGuiConditionEdit extends SubGuiInterface implements ITextfieldListener {
|
||||
|
||||
// Condition types
|
||||
private static final String[] CONDITION_TYPES = {
|
||||
"condition.hp_above",
|
||||
"condition.hp_below",
|
||||
"condition.target_hp_above",
|
||||
"condition.target_hp_below",
|
||||
"condition.hit_count"
|
||||
};
|
||||
|
||||
private static final String[] CONDITION_TYPE_IDS = {
|
||||
"hp_above",
|
||||
"hp_below",
|
||||
"target_hp_above",
|
||||
"target_hp_below",
|
||||
"hit_count"
|
||||
};
|
||||
|
||||
// Current condition being edited
|
||||
private Condition condition;
|
||||
private Condition result;
|
||||
|
||||
// State
|
||||
private int selectedTypeIndex = 0;
|
||||
private float threshold = 0.5f; // For HP conditions (0.0-1.0)
|
||||
private int requiredHits = 3; // For hit_count
|
||||
private int withinTicks = 60; // For hit_count
|
||||
|
||||
public SubGuiConditionEdit(Condition existing) {
|
||||
this.condition = existing;
|
||||
this.result = null;
|
||||
|
||||
if (existing != null) {
|
||||
String typeId = existing.getTypeId();
|
||||
for (int i = 0; i < CONDITION_TYPE_IDS.length; i++) {
|
||||
if (CONDITION_TYPE_IDS[i].equals(typeId)) {
|
||||
selectedTypeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
loadFromCondition(existing);
|
||||
}
|
||||
|
||||
setBackground("menubg.png");
|
||||
xSize = 220;
|
||||
ySize = 140;
|
||||
}
|
||||
|
||||
private void loadFromCondition(Condition cond) {
|
||||
String typeId = cond.getTypeId();
|
||||
if (typeId.equals("hit_count")) {
|
||||
Condition.ConditionHitCount hitCount = (Condition.ConditionHitCount) cond;
|
||||
requiredHits = hitCount.getRequiredHits();
|
||||
withinTicks = hitCount.getWithinTicks();
|
||||
} else {
|
||||
// HP-based conditions
|
||||
net.minecraft.nbt.NBTTagCompound nbt = cond.writeNBT();
|
||||
threshold = nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
int y = guiTop + 8;
|
||||
int labelX = guiLeft + 8;
|
||||
int fieldX = guiLeft + 90;
|
||||
|
||||
// Title
|
||||
addLabel(new GuiNpcLabel(0, "condition.edit", labelX, y));
|
||||
y += 18;
|
||||
|
||||
// Condition Type selector
|
||||
addLabel(new GuiNpcLabel(1, "gui.type", labelX, y + 5));
|
||||
addButton(new GuiNpcButton(1, fieldX, y, 115, 20, CONDITION_TYPES, selectedTypeIndex));
|
||||
y += 26;
|
||||
|
||||
// Type-specific fields
|
||||
String typeId = CONDITION_TYPE_IDS[selectedTypeIndex];
|
||||
if (typeId.equals("hit_count")) {
|
||||
// Hit count fields
|
||||
addLabel(new GuiNpcLabel(2, "condition.hits", labelX, y + 5));
|
||||
GuiNpcTextField hitsField = new GuiNpcTextField(2, this, fontRendererObj, fieldX, y, 40, 20, String.valueOf(requiredHits));
|
||||
hitsField.setIntegersOnly();
|
||||
hitsField.setMinMaxDefault(1, 100, 3);
|
||||
addTextField(hitsField);
|
||||
y += 24;
|
||||
|
||||
addLabel(new GuiNpcLabel(3, "condition.within", labelX, y + 5));
|
||||
GuiNpcTextField ticksField = new GuiNpcTextField(3, this, fontRendererObj, fieldX, y, 40, 20, String.valueOf(withinTicks));
|
||||
ticksField.setIntegersOnly();
|
||||
ticksField.setMinMaxDefault(1, 1200, 60);
|
||||
addTextField(ticksField);
|
||||
} else {
|
||||
// HP threshold field (as percentage)
|
||||
addLabel(new GuiNpcLabel(2, "condition.percent", labelX, y + 5));
|
||||
int percent = (int)(threshold * 100);
|
||||
GuiNpcTextField thresholdField = new GuiNpcTextField(4, this, fontRendererObj, fieldX, y, 40, 20, String.valueOf(percent));
|
||||
thresholdField.setIntegersOnly();
|
||||
thresholdField.setMinMaxDefault(1, 99, 50);
|
||||
addTextField(thresholdField);
|
||||
addLabel(new GuiNpcLabel(4, "%", fieldX + 45, y + 5));
|
||||
}
|
||||
|
||||
// Bottom buttons
|
||||
addButton(new GuiNpcButton(10, guiLeft + 8, guiTop + ySize - 28, 60, 20, "gui.cancel"));
|
||||
addButton(new GuiNpcButton(11, guiLeft + xSize - 68, guiTop + ySize - 28, 60, 20, "gui.done"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buttonEvent(GuiButton guibutton) {
|
||||
int id = guibutton.id;
|
||||
|
||||
if (id == 1) {
|
||||
// Type changed
|
||||
selectedTypeIndex = ((GuiNpcButton) guibutton).getValue();
|
||||
initGui();
|
||||
} else if (id == 10) {
|
||||
// Cancel - close without saving
|
||||
result = null;
|
||||
close();
|
||||
} else if (id == 11) {
|
||||
// Done - create condition and close
|
||||
result = createCondition();
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unFocused(GuiNpcTextField textField) {
|
||||
int id = textField.id;
|
||||
|
||||
if (id == 2) {
|
||||
requiredHits = textField.getInteger();
|
||||
} else if (id == 3) {
|
||||
withinTicks = textField.getInteger();
|
||||
} else if (id == 4) {
|
||||
int percent = textField.getInteger();
|
||||
threshold = percent / 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private Condition createCondition() {
|
||||
String typeId = CONDITION_TYPE_IDS[selectedTypeIndex];
|
||||
|
||||
switch (typeId) {
|
||||
case "hp_above":
|
||||
return new Condition.ConditionHPAbove(threshold);
|
||||
case "hp_below":
|
||||
return new Condition.ConditionHPBelow(threshold);
|
||||
case "target_hp_above":
|
||||
return new Condition.ConditionTargetHPAbove(threshold);
|
||||
case "target_hp_below":
|
||||
return new Condition.ConditionTargetHPBelow(threshold);
|
||||
case "hit_count":
|
||||
return new Condition.ConditionHitCount(requiredHits, withinTicks);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resulting condition after dialog closes.
|
||||
* Returns null if cancelled or no valid condition.
|
||||
*/
|
||||
public Condition getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityBeam;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityCharge;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
import noppes.npcs.client.gui.util.GuiNpcTextField;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityCutter;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityDash;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityGuard;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityHazard;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityHeal;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityHeavyHit;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
import noppes.npcs.client.gui.util.GuiNpcTextField;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityOrb;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityProjectile;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityShockwave;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilitySlam;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityTeleport;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityTrap;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.client.gui.advanced.ability;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.type.AbilityVortex;
|
||||
import noppes.npcs.client.gui.advanced.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
|
||||
@@ -1486,21 +1486,21 @@ ability.windUpAnim=Wind Up Anim
|
||||
ability.activeAnim=Active Anim
|
||||
gui.animations=Animations
|
||||
|
||||
ability.type.cnpc_slam=Slam
|
||||
ability.type.cnpc_heavy_hit=Heavy Hit
|
||||
ability.type.cnpc_cutter=Cutter
|
||||
ability.type.cnpc_beam=Beam
|
||||
ability.type.cnpc_projectile=Projectile
|
||||
ability.type.cnpc_orb=Orb
|
||||
ability.type.cnpc_charge=Charge
|
||||
ability.type.cnpc_dash=Dash
|
||||
ability.type.cnpc_teleport=Teleport
|
||||
ability.type.cnpc_vortex=Vortex
|
||||
ability.type.cnpc_shockwave=Shockwave
|
||||
ability.type.cnpc_guard=Guard
|
||||
ability.type.cnpc_heal=Heal
|
||||
ability.type.cnpc_hazard=Hazard
|
||||
ability.type.cnpc_trap=Trap
|
||||
ability.cnpc.slam=Slam
|
||||
ability.cnpc.heavy_hit=Heavy Hit
|
||||
ability.cnpc.cutter=Cutter
|
||||
ability.cnpc.beam=Beam
|
||||
ability.cnpc.projectile=Projectile
|
||||
ability.cnpc.orb=Orb
|
||||
ability.cnpc.charge=Charge
|
||||
ability.cnpc.dash=Dash
|
||||
ability.cnpc.teleport=Teleport
|
||||
ability.cnpc.vortex=Vortex
|
||||
ability.cnpc.shockwave=Shockwave
|
||||
ability.cnpc.guard=Guard
|
||||
ability.cnpc.heal=Heal
|
||||
ability.cnpc.hazard=Hazard
|
||||
ability.cnpc.trap=Trap
|
||||
|
||||
# Ability GUI - Type Tab
|
||||
ability.tab.type=Type
|
||||
@@ -1631,3 +1631,22 @@ ability.activeColor=Active Color
|
||||
# Shockwave Settings
|
||||
ability.pushRadius=Push Radius
|
||||
ability.pushStrength=Push Str
|
||||
|
||||
# Ability Config GUI
|
||||
ability.typeId=Type ID
|
||||
ability.tab.target=Target
|
||||
ability.conditions=Conditions
|
||||
ability.noTypeSettings=No type-specific settings
|
||||
ability.sounds=Sounds
|
||||
ability.animations=Animations
|
||||
|
||||
# Conditions
|
||||
condition.edit=Edit Condition
|
||||
condition.hp_above=NPC HP Above
|
||||
condition.hp_below=NPC HP Below
|
||||
condition.target_hp_above=Target HP Above
|
||||
condition.target_hp_below=Target HP Below
|
||||
condition.hit_count=Hit Count
|
||||
condition.percent=Threshold
|
||||
condition.hits=Required Hits
|
||||
condition.within=Within (ticks)
|
||||
Reference in new issue
Block a user