diff --git a/src/api b/src/api index e4ddefb25..465075c63 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit e4ddefb2578a5fed9f45578600f4089f08cdf3b2 +Subproject commit 465075c63167b29960569915db8b7d0ba6cd053d diff --git a/src/main/java/kamkeel/npcs/entity/EntityAbilityZone.java b/src/main/java/kamkeel/npcs/entity/EntityAbilityZone.java index 1cd553cd6..23120b80b 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityAbilityZone.java +++ b/src/main/java/kamkeel/npcs/entity/EntityAbilityZone.java @@ -6,6 +6,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import io.netty.buffer.ByteBuf; import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.EnergyController; import kamkeel.npcs.controllers.data.ability.Ability; import kamkeel.npcs.controllers.data.ability.data.effect.AbilityPotionEffect; import kamkeel.npcs.controllers.data.ability.util.AbilityTargetHelper; @@ -174,6 +175,13 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD private transient Ability sourceAbility = null; + /** + * Custom damage data for script-created zones that don't have a sourceAbility. + * Used by EnergyController handlers (e.g. DBC Addon) to carry damage configuration + * directly on the entity. Synced via spawn data for client sync. + */ + private NBTTagCompound customDamageData = null; + private boolean previewMode = false; private EntityLivingBase previewOwner = null; @@ -199,6 +207,30 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD this.setPosition(x, groundY, z); } + /** + * Initialize as a hazard zone with default values. Used by EnergyController factory. + * Scripts can then configure properties before calling spawn(). + */ + public void initAsHazard(Entity owner, double x, double y, double z) { + this.zoneType = ZoneType.HAZARD; + this.ownerEntityId = owner.getEntityId(); + double groundY = Ability.findGroundLevel(worldObj, x, y, z) + GROUND_OFFSET; + this.setPosition(x, groundY, z); + this.ticksSinceDamage = damageInterval; + } + + /** + * Initialize as a trap zone with default values. Used by EnergyController factory. + * Scripts can then configure properties before calling spawn(). + */ + public void initAsTrap(Entity owner, double x, double y, double z) { + this.zoneType = ZoneType.TRAP; + this.ownerEntityId = owner.getEntityId(); + double groundY = Ability.findGroundLevel(worldObj, x, y, z) + GROUND_OFFSET; + this.setPosition(x, groundY, z); + this.ticksSinceLastTrigger = triggerCooldown; + } + public static EntityAbilityZone createTrap(World world, EntityLivingBase owner, double x, double y, double z, ZoneShape shape, @@ -516,6 +548,14 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD sourceAbility, (EntityLivingBase) owner, target, dmg, 0.0f, 0.0f, dx, dz, 1.0f); } + // Fallback: route through EnergyController for script-created entities with custom damage data + if (!handled && customDamageData != null && owner instanceof EntityLivingBase) { + double dx = target.posX - posX; + double dz = target.posZ - posZ; + handled = EnergyController.Instance.fireOnEnergyDamage( + this, (EntityLivingBase) owner, target, + dmg, 0.0f, 0.0f, dx, dz, 1.0f, customDamageData); + } if (!handled) { if (owner instanceof EntityNPCInterface) { @@ -564,6 +604,14 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD this.sourceAbility = ability; } + public NBTTagCompound getCustomDamageData() { + return customDamageData; + } + + public void setCustomDamageData(NBTTagCompound data) { + this.customDamageData = data; + } + // ═══════════════════════════════════════════════════════════════════ // RENDERING SUPPORT // ═══════════════════════════════════════════════════════════════════ @@ -737,6 +785,51 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD this.particleGlow = particleGlow; } + // ═══════════════════════════════════════════════════════════════════ + // PUBLIC SETTERS (for EnergyController / scripting API) + // ═══════════════════════════════════════════════════════════════════ + + public void setShape(ZoneShape shape) { this.shape = shape; } + public void setRadius(float radius) { this.radius = radius; } + public void setZoneHeight(float height) { this.zoneHeight = height; } + public void setDurationTicks(int ticks) { this.durationTicks = ticks; this.maxTicks = ticks; } + public void setInnerColor(int color) { this.innerColor = color; } + public void setOuterColor(int color) { this.outerColor = color; } + public void setOuterColorEnabled(boolean enabled) { this.outerColorEnabled = enabled; } + public void setParticleDensity(float density) { this.particleDensity = density; } + public void setParticleScale(float scale) { this.particleScale = scale; } + public void setAnimSpeed(float speed) { this.animSpeed = speed; } + public void setIgnoreIFrames(boolean ignore) { this.ignoreIFrames = ignore; } + + // Hazard-specific + public float getDamagePerSecond() { return damagePerSecond; } + public void setDamagePerSecond(float dps) { this.damagePerSecond = dps; } + public int getDamageInterval() { return damageInterval; } + public void setDamageInterval(int ticks) { this.damageInterval = ticks; } + public boolean isAffectsCaster() { return affectsCaster; } + public void setAffectsCaster(boolean affects) { this.affectsCaster = affects; } + + // Trap-specific + public float getTriggerRadius() { return triggerRadius; } + public void setTriggerRadius(float radius) { this.triggerRadius = radius; } + public int getArmTime() { return armTime; } + public void setArmTime(int ticks) { this.armTime = ticks; } + public int getMaxTriggers() { return maxTriggers; } + public void setMaxTriggers(int max) { this.maxTriggers = max; } + public int getTriggerCooldown() { return triggerCooldown; } + public void setTriggerCooldown(int ticks) { this.triggerCooldown = ticks; } + public float getDamage() { return damage; } + public void setDamage(float damage) { this.damage = damage; } + public float getDamageRadius() { return damageRadius; } + public void setDamageRadius(float radius) { this.damageRadius = radius; } + public float getKnockback() { return knockback; } + public void setKnockback(float knockback) { this.knockback = knockback; } + public void setVisible(boolean visible) { this.visible = visible; } + + public boolean isIgnoreIFrames() { return ignoreIFrames; } + + public int getOwnerEntityId() { return ownerEntityId; } + // ═══════════════════════════════════════════════════════════════════ // NBT SERIALIZATION // ═══════════════════════════════════════════════════════════════════ @@ -804,6 +897,17 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD } catch (java.io.IOException e) { noppes.npcs.LogWriter.error("Error writing zone effects spawn data", e); } + + // Custom damage data + boolean hasDamageData = customDamageData != null; + buffer.writeBoolean(hasDamageData); + if (hasDamageData) { + try { + ByteBufUtils.writeNBT(buffer, customDamageData); + } catch (java.io.IOException e) { + noppes.npcs.LogWriter.error("Error writing zone custom damage data", e); + } + } } @Override @@ -866,5 +970,14 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD } } } + + // Custom damage data + if (buffer.readableBytes() > 0 && buffer.readBoolean()) { + try { + this.customDamageData = ByteBufUtils.readNBT(buffer); + } catch (java.io.IOException e) { + noppes.npcs.LogWriter.error("Error reading zone custom damage data", e); + } + } } } diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java index cb7c92534..dcf435904 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java @@ -43,6 +43,14 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit * The ability that spawned this entity. Transient, not saved to NBT. */ protected transient Ability sourceAbility = null; + + /** + * Custom damage data for script-created entities that don't have a sourceAbility. + * Used by EnergyController handlers (e.g. DBC Addon) to carry damage configuration + * directly on the entity. Persistent — saved to spawn data for client sync. + */ + protected NBTTagCompound customDamageData = null; + protected boolean ignoreIFrames = false; protected boolean previewMode = false; protected EntityLivingBase previewOwner = null; @@ -141,6 +149,16 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit this.sourceAbility = ability; } + // ==================== CUSTOM DAMAGE DATA ==================== + + public NBTTagCompound getCustomDamageData() { + return customDamageData; + } + + public void setCustomDamageData(NBTTagCompound data) { + this.customDamageData = data; + } + public boolean isIgnoreIFrames() { return ignoreIFrames; } @@ -325,6 +343,9 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit nbt.setBoolean("IgnoreIFrames", ignoreIFrames); displayData.writeNBT(nbt); lightningData.writeNBT(nbt); + if (customDamageData != null) { + nbt.setTag("CustomDamageData", customDamageData); + } } /** @@ -336,6 +357,9 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit this.ignoreIFrames = nbt.getBoolean("IgnoreIFrames"); displayData.readNBT(nbt); lightningData.readNBT(nbt); + if (nbt.hasKey("CustomDamageData")) { + this.customDamageData = nbt.getCompoundTag("CustomDamageData"); + } } // ==================== SPAWN DATA ==================== diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java index 66f40c04f..f279e69bd 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java @@ -3,6 +3,7 @@ package kamkeel.npcs.entity; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.EnergyController; import kamkeel.npcs.controllers.data.ability.Ability; import kamkeel.npcs.controllers.data.ability.data.energy.EnergyBarrierData; import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData; @@ -227,6 +228,14 @@ public class EntityEnergyPanel extends EntityEnergyBarrier { sourceAbility, (EntityLivingBase) owner, target, panelData.launchDamage, panelData.launchKnockback, 0.0f, dx, dz, 1.0f); } + // Fallback: route through EnergyController for script-created entities with custom damage data + if (!handled && customDamageData != null && owner instanceof EntityLivingBase) { + double dx = target.posX - posX; + double dz = target.posZ - posZ; + handled = EnergyController.Instance.fireOnEnergyDamage( + this, (EntityLivingBase) owner, target, + panelData.launchDamage, panelData.launchKnockback, 0.0f, dx, dz, 1.0f, customDamageData); + } if (!handled) { if (owner instanceof EntityNPCInterface) { @@ -655,6 +664,15 @@ public class EntityEnergyPanel extends EntityEnergyBarrier { return panelData; } + public void setPanelYaw(float yaw) { + this.panelYaw = yaw; + this.prevPanelYaw = yaw; + } + + public void setMode(PanelMode mode) { + this.mode = mode; + } + // ==================== NBT ==================== @Override diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java index df3d320c0..b9b6560e9 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java @@ -3,6 +3,7 @@ package kamkeel.npcs.entity; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.EnergyController; import kamkeel.npcs.controllers.data.ability.Ability; import kamkeel.npcs.controllers.data.ability.type.energy.AbilityEnergyProjectile; import kamkeel.npcs.controllers.data.ability.data.effect.AbilityPotionEffect; @@ -926,6 +927,15 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility { sourceAbility, (EntityLivingBase) owner, target, dmg, kb, kbUp, dx, dz, damageMultiplier); } + // Fallback: route through EnergyController for script-created entities with custom damage data + if (!handled && customDamageData != null && owner instanceof EntityLivingBase) { + double dx = target.posX - posX; + double dz = target.posZ - posZ; + float kbUp = getKnockbackUp() > 0 ? getKnockbackUp() : 0.1f; + handled = EnergyController.Instance.fireOnEnergyDamage( + this, (EntityLivingBase) owner, target, + dmg, kb, kbUp, dx, dz, damageMultiplier, customDamageData); + } int previousHurtResistantTime = Ability.clearHurtResistanceIfNeeded(target, ignoreIFrames); try { diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergySweeper.java b/src/main/java/kamkeel/npcs/entity/EntityEnergySweeper.java index 7ce8eeaf1..d8596cf08 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergySweeper.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergySweeper.java @@ -3,6 +3,7 @@ package kamkeel.npcs.entity; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.EnergyController; import kamkeel.npcs.controllers.data.ability.Ability; import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData; import kamkeel.npcs.util.CNPCDebug; @@ -322,6 +323,14 @@ public class EntityEnergySweeper extends EntityEnergyAbility { sourceAbility, (EntityLivingBase) owner, target, damage, 0.0f, 0.2f, dx, dz, 1.0f); } + // Fallback: route through EnergyController for script-created entities with custom damage data + if (!handled && customDamageData != null && owner instanceof EntityLivingBase) { + double dx = target.posX - posX; + double dz = target.posZ - posZ; + handled = EnergyController.Instance.fireOnEnergyDamage( + this, (EntityLivingBase) owner, target, + damage, 0.0f, 0.2f, dx, dz, 1.0f, customDamageData); + } if (!handled) { if (owner instanceof EntityNPCInterface) { @@ -394,6 +403,24 @@ public class EntityEnergySweeper extends EntityEnergyAbility { return baseYaw; } + // ==================== PUBLIC SETTERS (for EnergyController / scripting API) ==================== + + public void setBeamLength(float length) { this.beamLength = length; } + public void setBeamWidth(float width) { this.beamWidth = width; } + public void setBeamHeight(float height) { this.beamHeight = height; } + public float getDamage() { return damage; } + public void setDamage(float damage) { this.damage = damage; } + public int getDamageInterval() { return damageInterval; } + public void setDamageInterval(int interval) { this.damageInterval = interval; } + public boolean isPiercing() { return piercing; } + public void setPiercing(boolean piercing) { this.piercing = piercing; } + public float getSweepSpeed() { return sweepSpeed; } + public void setSweepSpeed(float speed) { this.sweepSpeed = speed; } + public int getNumberOfRotations() { return numberOfRotations; } + public void setNumberOfRotations(int rotations) { this.numberOfRotations = rotations; } + public boolean isLockOnTarget() { return lockOnTarget; } + public void setLockOnTarget(boolean lock) { this.lockOnTarget = lock; } + // ==================== NBT ==================== @Override diff --git a/src/main/java/noppes/npcs/scripted/NpcAPI.java b/src/main/java/noppes/npcs/scripted/NpcAPI.java index 0864e16ec..c1871d9b9 100644 --- a/src/main/java/noppes/npcs/scripted/NpcAPI.java +++ b/src/main/java/noppes/npcs/scripted/NpcAPI.java @@ -5,9 +5,11 @@ import cpw.mods.fml.common.eventhandler.EventBus; import foxz.command.ScriptedCommand; import kamkeel.npcs.controllers.AbilityController; import kamkeel.npcs.controllers.AttributeController; +import kamkeel.npcs.controllers.EnergyController; import kamkeel.npcs.controllers.ProfileController; import kamkeel.npcs.controllers.TelegraphController; import kamkeel.npcs.entity.EntityAbilityBeam; +import kamkeel.npcs.entity.EntityAbilityZone; import kamkeel.npcs.entity.EntityAbilityDisc; import kamkeel.npcs.entity.EntityEnergyDome; import kamkeel.npcs.entity.EntityAbilityLaser; @@ -60,6 +62,7 @@ import noppes.npcs.api.IBlock; import noppes.npcs.api.ICommand; import noppes.npcs.api.IContainer; import noppes.npcs.api.IDamageSource; +import noppes.npcs.api.IEnergyController; import noppes.npcs.api.INbt; import noppes.npcs.api.IParticle; import noppes.npcs.api.IPos; @@ -105,6 +108,7 @@ import noppes.npcs.scripted.entity.ScriptEnergyPanel; import noppes.npcs.scripted.entity.ScriptEnergyProjectile; import noppes.npcs.scripted.entity.ScriptEnergySlicer; import noppes.npcs.scripted.entity.ScriptEnergySweeper; +import noppes.npcs.scripted.entity.ScriptEnergyZone; import noppes.npcs.scripted.entity.ScriptEntity; import noppes.npcs.scripted.entity.ScriptEntityItem; import noppes.npcs.scripted.entity.ScriptFishHook; @@ -462,6 +466,8 @@ public class NpcAPI extends AbstractNpcAPI { data = new ScriptEntityData(new ScriptEnergyPanel<>((EntityEnergyPanel) entity)); else if (entity instanceof EntityEnergySweeper) data = new ScriptEntityData(new ScriptEnergySweeper<>((EntityEnergySweeper) entity)); + else if (entity instanceof EntityAbilityZone) + data = new ScriptEntityData(new ScriptEnergyZone<>((EntityAbilityZone) entity)); else data = new ScriptEntityData(new ScriptEntity<>(entity)); entity.registerExtendedProperties("ScriptedObject", data); @@ -612,6 +618,11 @@ public class NpcAPI extends AbstractNpcAPI { return instance; } + @Override + public IEnergyController getEnergyController() { + return EnergyController.Instance; + } + public EventBus events() { return EVENT_BUS; } diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyAbility.java b/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyAbility.java index 4983b59b2..1c6c28ad2 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyAbility.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyAbility.java @@ -2,6 +2,8 @@ package noppes.npcs.scripted.entity; import kamkeel.npcs.entity.EntityEnergyAbility; import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.api.INbt; import noppes.npcs.api.entity.IEnergyAbility; import noppes.npcs.api.entity.IEntity; import noppes.npcs.scripted.NpcAPI; @@ -128,4 +130,23 @@ public abstract class ScriptEnergyAbility extends public void setIgnoreIFrames(boolean ignore) { entity.setIgnoreIFrames(ignore); } + + // ==================== CUSTOM DAMAGE DATA ==================== + + public INbt getDamageData() { + NBTTagCompound data = entity.getCustomDamageData(); + if (data == null) { + data = new NBTTagCompound(); + entity.setCustomDamageData(data); + } + return NpcAPI.Instance().getINbt(data); + } + + public void setDamageData(INbt data) { + if (data == null) { + entity.setCustomDamageData(null); + } else { + entity.setCustomDamageData((NBTTagCompound) data.getMCNBT()); + } + } } diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyPanel.java b/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyPanel.java index 04c730fad..edcf90795 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyPanel.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptEnergyPanel.java @@ -54,4 +54,23 @@ public class ScriptEnergyPanel extends ScriptEnergy public boolean isLaunched() { return entity.getMode() == EntityEnergyPanel.PanelMode.LAUNCHED; } + + public void setPanelYaw(float yaw) { + entity.setPanelYaw(yaw); + } + + public void setPanelMode(int mode) { + EntityEnergyPanel.PanelMode[] values = EntityEnergyPanel.PanelMode.values(); + if (mode >= 0 && mode < values.length) { + entity.setMode(values[mode]); + } + } + + // ==================== SPAWNING ==================== + + public void spawn() { + if (!entity.addedToChunk && entity.worldObj != null) { + entity.worldObj.spawnEntityInWorld(entity); + } + } } diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptEnergySweeper.java b/src/main/java/noppes/npcs/scripted/entity/ScriptEnergySweeper.java index 52207238d..021bcafb5 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptEnergySweeper.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptEnergySweeper.java @@ -1,9 +1,116 @@ package noppes.npcs.scripted.entity; import kamkeel.npcs.entity.EntityEnergySweeper; +import noppes.npcs.api.entity.IEnergySweeper; + +public class ScriptEnergySweeper extends ScriptEnergyAbility implements IEnergySweeper { -public class ScriptEnergySweeper extends ScriptEnergyAbility { public ScriptEnergySweeper(T entity) { super(entity); } + + // ==================== BEAM DIMENSIONS ==================== + + @Override + public float getBeamLength() { + return entity.getBeamLength(); + } + + @Override + public void setBeamLength(float length) { + entity.setBeamLength(length); + } + + @Override + public float getBeamWidth() { + return entity.getBeamWidth(); + } + + @Override + public void setBeamWidth(float width) { + entity.setBeamWidth(width); + } + + @Override + public float getBeamHeight() { + return entity.getBeamHeight(); + } + + @Override + public void setBeamHeight(float height) { + entity.setBeamHeight(height); + } + + // ==================== ROTATION ==================== + + @Override + public float getSweepSpeed() { + return entity.getSweepSpeed(); + } + + @Override + public void setSweepSpeed(float degreesPerTick) { + entity.setSweepSpeed(degreesPerTick); + } + + @Override + public int getNumberOfRotations() { + return entity.getNumberOfRotations(); + } + + @Override + public void setNumberOfRotations(int rotations) { + entity.setNumberOfRotations(rotations); + } + + @Override + public boolean isLockOnTarget() { + return entity.isLockOnTarget(); + } + + @Override + public void setLockOnTarget(boolean lock) { + entity.setLockOnTarget(lock); + } + + // ==================== DAMAGE ==================== + + @Override + public float getDamage() { + return entity.getDamage(); + } + + @Override + public void setDamage(float damage) { + entity.setDamage(damage); + } + + @Override + public int getDamageInterval() { + return entity.getDamageInterval(); + } + + @Override + public void setDamageInterval(int ticks) { + entity.setDamageInterval(ticks); + } + + @Override + public boolean isPiercing() { + return entity.isPiercing(); + } + + @Override + public void setPiercing(boolean piercing) { + entity.setPiercing(piercing); + } + + // ==================== SPAWNING ==================== + + @Override + public void spawn() { + if (!entity.addedToChunk && entity.worldObj != null) { + entity.worldObj.spawnEntityInWorld(entity); + } + } }