Player Ability Checking

Enhance ability validation: add method to check if an ability can be resolved without deep copy and prune invalid unlocked abilities during load
This commit is contained in:
Kam committed 2026-02-16 01:40:51 -05:00
commit f4ad421c2e
26 files changed
+1387 -97

No files matched your search

@@ -9,8 +9,11 @@ import noppes.npcs.LogWriter;
import noppes.npcs.api.handler.IAbilityHandler;
import noppes.npcs.util.NBTJsonUtil;
import net.minecraft.entity.player.EntityPlayer;
import java.io.File;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class AbilityController implements IAbilityHandler {
@@ -26,6 +29,7 @@ public class AbilityController implements IAbilityHandler {
private final Map<String, List<AbilityVariant>> externalVariants = new LinkedHashMap<>();
private final List<IAbilityFieldProvider> fieldProviders = new ArrayList<>();
private final List<IAbilityExtender> extenders = new ArrayList<>();
private final List<Predicate<EntityPlayer>> flightCheckers = new ArrayList<>();
// ── Derived State ────────────────────────────────────────────────────────
private final Set<String> builtInTypeIds = new HashSet<>();
@@ -413,6 +417,18 @@ public class AbilityController implements IAbilityHandler {
return extenders;
}
public void registerFlightChecker(Predicate<EntityPlayer> checker) {
flightCheckers.add(checker);
}
public boolean isPlayerFlying(EntityPlayer player) {
if (player.capabilities.isFlying) return true;
for (Predicate<EntityPlayer> checker : flightCheckers) {
if (checker.test(player)) return true;
}
return false;
}
/**
* Fire onAbilityStart on all extenders. Returns false if ANY extender cancels.
*/
@@ -3,6 +3,7 @@ package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import noppes.npcs.EventHooks;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
@@ -544,6 +545,9 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
MovingObjectPosition blockHit = worldObj.func_147447_a(currentPos, nextPos, false, true, false);
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileBlockImpact(this, blockHit.blockX, blockHit.blockY, blockHit.blockZ);
}
hasHit = true;
if (isExplosive()) {
posX = blockHit.hitVec.xCoord;
@@ -593,10 +597,22 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
return beamWidth;
}
public void setBeamWidth(float beamWidth) {
this.beamWidth = beamWidth;
}
public float getHeadSize() {
return headSize;
}
public void setHeadSize(float headSize) {
this.headSize = headSize;
}
public void setAttachedToOwner(boolean attached) {
this.attachedToOwner = attached;
}
/**
* Get interpolated head offset for smooth rendering.
* Returns offset RELATIVE to origin.
@@ -3,6 +3,7 @@ package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import noppes.npcs.EventHooks;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
@@ -344,6 +345,9 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
MovingObjectPosition blockHit = worldObj.func_147447_a(currentPos, nextPos, false, true, false);
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileBlockImpact(this, blockHit.blockX, blockHit.blockY, blockHit.blockZ);
}
hasHit = true;
if (isExplosive()) {
posX = blockHit.hitVec.xCoord;
@@ -413,14 +417,34 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
return discRadius;
}
public void setDiscRadius(float radius) {
this.discRadius = radius;
}
public float getDiscThickness() {
return discThickness;
}
public void setDiscThickness(float thickness) {
this.discThickness = thickness;
}
public boolean isBoomerang() {
return boomerang;
}
public void setBoomerang(boolean boomerang) {
this.boomerang = boomerang;
}
public int getBoomerangDelay() {
return boomerangDelay;
}
public void setBoomerangDelay(int delay) {
this.boomerangDelay = delay;
}
public boolean isReturning() {
return returning;
}
@@ -429,6 +453,10 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
return vertical;
}
public void setVertical(boolean vertical) {
this.vertical = vertical;
}
/**
* Get the yaw angle (degrees) from motion vector for vertical disc orientation.
* During charging, uses owner's facing direction.
@@ -3,6 +3,7 @@ package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import noppes.npcs.EventHooks;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
@@ -145,6 +146,9 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
endZ = startZ + dirZ * currentLength;
if (ticksSinceFullExtension >= lingerTicks) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileExpired(this);
}
this.setDead();
}
}
@@ -236,6 +240,9 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
MovingObjectPosition blockHit = worldObj.func_147447_a(start, end, false, true, false);
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileBlockImpact(this, blockHit.blockX, blockHit.blockY, blockHit.blockZ);
}
// Laser stops at block
currentLength = (float) Math.sqrt(
(blockHit.hitVec.xCoord - startX) * (blockHit.hitVec.xCoord - startX) +
@@ -355,6 +362,32 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
return laserWidth;
}
public void setLaserWidth(float width) {
this.laserWidth = width;
}
public float getExpansionSpeed() {
return expansionSpeed;
}
public void setExpansionSpeed(float speed) {
this.expansionSpeed = speed;
}
public int getLingerTicks() {
return lingerTicks;
}
public void setLingerTicks(int ticks) {
this.lingerTicks = ticks;
}
public void setDirection(double x, double y, double z) {
this.dirX = x;
this.dirY = y;
this.dirZ = z;
}
public float getCurrentLength() {
return currentLength;
}
@@ -3,6 +3,7 @@ package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import noppes.npcs.EventHooks;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
@@ -232,6 +233,9 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
MovingObjectPosition blockHit = worldObj.func_147447_a(currentPos, nextPos, false, true, false);
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileBlockImpact(this, blockHit.blockX, blockHit.blockY, blockHit.blockZ);
}
hasHit = true;
if (isExplosive()) {
posX = blockHit.hitVec.xCoord;
@@ -20,13 +20,17 @@ import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import noppes.npcs.EventHooks;
import noppes.npcs.NpcDamageSource;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.scripted.NpcAPI;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -36,7 +40,38 @@ import java.util.Map;
*
* Design inspired by LouisXIV's energy attack system.
*/
public abstract class EntityAbilityProjectile extends Entity implements IEnergyProjectile, IEntityAdditionalSpawnData {
public abstract class EntityAbilityProjectile extends Entity implements IEntityAdditionalSpawnData {
// ==================== ACTIVE PROJECTILE TRACKING ====================
private static final Map<Integer, List<WeakReference<EntityAbilityProjectile>>> activeProjectiles = new HashMap<>();
public static void trackProjectile(EntityAbilityProjectile projectile) {
int ownerId = projectile.getOwnerEntityId();
if (ownerId < 0) return;
List<WeakReference<EntityAbilityProjectile>> refs = activeProjectiles.get(ownerId);
if (refs == null) {
refs = new ArrayList<>();
activeProjectiles.put(ownerId, refs);
}
refs.add(new WeakReference<>(projectile));
}
public static List<EntityAbilityProjectile> getActiveProjectiles(int ownerEntityId) {
List<WeakReference<EntityAbilityProjectile>> refs = activeProjectiles.get(ownerEntityId);
if (refs == null) return Collections.emptyList();
List<EntityAbilityProjectile> result = new ArrayList<>();
Iterator<WeakReference<EntityAbilityProjectile>> it = refs.iterator();
while (it.hasNext()) {
EntityAbilityProjectile p = it.next().get();
if (p == null || p.isDead) {
it.remove();
} else {
result.add(p);
}
}
if (refs.isEmpty()) activeProjectiles.remove(ownerEntityId);
return result;
}
// ==================== VISUAL PROPERTIES ====================
protected float size = 1.0f;
@@ -174,6 +209,11 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
// Skip super.onUpdate() in preview mode to avoid world checks
if (!previewMode) {
super.onUpdate();
// Track on first server tick
if (ticksExisted == 1 && !worldObj.isRemote) {
trackProjectile(this);
}
}
// Update rotation
@@ -208,12 +248,18 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
// Check lifespan using world time (survives chunk unload/reload)
if (deathWorldTime > 0 && worldObj.getTotalWorldTime() >= deathWorldTime) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileExpired(this);
}
this.setDead();
return;
}
// Check max distance (subclass can override if needed)
if (checkMaxDistance()) {
if (!worldObj.isRemote) {
EventHooks.onEnergyProjectileExpired(this);
}
this.setDead();
return;
}
@@ -226,6 +272,11 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
// Subclass-specific update
updateProjectile();
// Fire tick event (server-side, non-preview only)
if (!previewMode && !worldObj.isRemote) {
EventHooks.onEnergyProjectileTick(this);
}
}
/**
@@ -328,6 +379,14 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
protected void applyDamage(EntityLivingBase target, float dmg, float kb) {
if (previewMode) return; // Skip damage in preview mode
// Fire entity impact event (may cancel or modify damage)
if (!worldObj.isRemote) {
float result = EventHooks.onEnergyProjectileEntityImpact(this, target, dmg);
if (result < 0) return; // Event was cancelled
dmg = result;
}
Entity owner = getOwnerEntity();
// Check for ability extenders (e.g., DBC Addon damage routing)
@@ -627,12 +686,14 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
return worldObj.getEntityByID(ownerEntityId);
}
@Override
public int getOwnerEntityId() {
return ownerEntityId;
}
@Override
public void setOwnerEntityId(int id) {
this.ownerEntityId = id;
}
public IEntity getOwner() {
if (previewMode) return null;
if (getOwnerEntity() == null) return null;
@@ -647,17 +708,19 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
this.previewOwner = owner;
}
@Override
public int getTargetEntityId() {
return targetEntityId;
}
public void setTargetEntityId(int id) {
this.targetEntityId = id;
}
public Entity getTargetEntity() {
if (targetEntityId == -1) return null;
return worldObj.getEntityByID(targetEntityId);
}
@Override
public IEntity getTarget() {
if (getTargetEntity() == null) return null;
return NpcAPI.Instance().getIEntity(getTargetEntity());
@@ -686,162 +749,135 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
return false;
}
// ==================== VISUAL GETTERS ====================
// ==================== VISUAL GETTERS & SETTERS ====================
@Override
public float getSize() {
return size;
public float getSize() { return size; }
public void setProjectileSize(float size) {
this.size = size;
this.renderCurrentSize = size;
this.prevRenderSize = size;
}
@Override
public int getInnerColor() {
return displayData.getInnerColor();
/**
* Set the start position for distance calculations.
* Used by factory methods when creating projectiles without the full constructor.
*/
public void setStartPosition(double x, double y, double z) {
this.startX = x;
this.startY = y;
this.startZ = z;
}
@Override
public int getOuterColor() {
return displayData.getOuterColor();
}
public int getInnerColor() { return displayData.getInnerColor(); }
public void setInnerColor(int color) { displayData.setInnerColor(color); }
@Override
public boolean isOuterColorEnabled() {
return displayData.isOuterColorEnabled();
}
public int getOuterColor() { return displayData.getOuterColor(); }
public void setOuterColor(int color) { displayData.setOuterColor(color); }
@Override
public float getOuterColorWidth() {
return displayData.getOuterColorWidth();
}
public boolean isOuterColorEnabled() { return displayData.isOuterColorEnabled(); }
public void setOuterColorEnabled(boolean enabled) { displayData.setOuterColorEnabled(enabled); }
@Override
public float getOuterColorAlpha() {
return displayData.getOuterColorAlpha();
}
public float getOuterColorWidth() { return displayData.getOuterColorWidth(); }
public void setOuterColorWidth(float width) { displayData.setOuterColorWidth(width); }
@Override
public float getRotationSpeed() {
return displayData.getRotationSpeed();
}
public float getOuterColorAlpha() { return displayData.getOuterColorAlpha(); }
public void setOuterColorAlpha(float alpha) { displayData.setOuterColorAlpha(alpha); }
public float getRotationSpeed() { return displayData.getRotationSpeed(); }
public void setRotationSpeed(float speed) { displayData.setRotationSpeed(speed); }
// ==================== ROTATION GETTERS ====================
@Override
public float getInterpolatedRotationX(float partialTicks) {
return this.prevRotationValX + (this.rotationValX - this.prevRotationValX) * partialTicks;
}
@Override
public float getInterpolatedRotationY(float partialTicks) {
return this.prevRotationValY + (this.rotationValY - this.prevRotationValY) * partialTicks;
}
@Override
public float getInterpolatedRotationZ(float partialTicks) {
return this.prevRotationValZ + (this.rotationValZ - this.prevRotationValZ) * partialTicks;
}
@Override
public float getInterpolatedSize(float partialTicks) {
return this.prevRenderSize + (this.renderCurrentSize - this.prevRenderSize) * partialTicks;
}
// ==================== LIGHTNING GETTERS ====================
// ==================== LIGHTNING GETTERS & SETTERS ====================
@Override
public boolean hasLightningEffect() {
return lightningData.isLightningEffect();
}
public boolean hasLightningEffect() { return lightningData.isLightningEffect(); }
public void setLightningEffect(boolean enabled) { lightningData.setLightningEffect(enabled); }
@Override
public float getLightningDensity() {
return lightningData.getLightningDensity();
}
public float getLightningDensity() { return lightningData.getLightningDensity(); }
public void setLightningDensity(float density) { lightningData.setLightningDensity(density); }
@Override
public float getLightningRadius() {
return lightningData.getLightningRadius();
}
public float getLightningRadius() { return lightningData.getLightningRadius(); }
public void setLightningRadius(float radius) { lightningData.setLightningRadius(radius); }
@Override
public int getLightningFadeTime() {
return lightningData.getLightningFadeTime();
}
public int getLightningFadeTime() { return lightningData.getLightningFadeTime(); }
public void setLightningFadeTime(int ticks) { lightningData.setLightningFadeTime(ticks); }
// ==================== LIFESPAN GETTERS ====================
// ==================== LIFESPAN GETTERS & SETTERS ====================
@Override
public float getMaxDistance() { return lifespanData.getMaxDistance(); }
public void setMaxDistance(float distance) { lifespanData.setMaxDistance(distance); }
@Override
public int getMaxLifetime() { return lifespanData.getMaxLifetime(); }
public void setMaxLifetime(int ticks) { lifespanData.setMaxLifetime(ticks); }
// ==================== COMBAT GETTERS ====================
// ==================== COMBAT GETTERS & SETTERS ====================
@Override
public float getDamage() { return combatData.getDamage(); }
public void setCombatDamage(float damage) { combatData.setDamage(damage); }
@Override
public float getKnockback() { return combatData.knockback; }
public void setCombatKnockback(float knockback) { combatData.setKnockback(knockback); }
@Override
public float getKnockbackUp() { return combatData.knockbackUp; }
public void setCombatKnockbackUp(float knockbackUp) { combatData.setKnockbackUp(knockbackUp); }
@Override
public boolean isExplosive() { return combatData.isExplosive(); }
public void setExplosive(boolean explosive) { combatData.setExplosive(explosive); }
@Override
public float getExplosionRadius() { return combatData.explosionRadius; }
public void setExplosionRadius(float radius) { combatData.setExplosionRadius(radius); }
@Override
public float getExplosionDamageFalloff() { return combatData.explosionDamageFalloff; }
public void setExplosionDamageFalloff(float falloff) { combatData.setExplosionDamageFalloff(falloff); }
// ==================== HOMING GETTERS ====================
// ==================== HOMING GETTERS & SETTERS ====================
@Override
public boolean isHoming() { return homingData.isHoming(); }
public void setHomingEnabled(boolean homing) { homingData.setHoming(homing); }
@Override
public float getHomingStrength() { return homingData.getHomingStrength(); }
public void setHomingStrength(float strength) { homingData.setHomingStrength(strength); }
@Override
public float getHomingRange() { return homingData.getHomingRange(); }
public void setHomingRange(float range) { homingData.setHomingRange(range); }
// ==================== TRAJECTORY GETTERS ====================
// ==================== SPEED & ANCHOR GETTERS & SETTERS ====================
// ==================== ANCHOR GETTERS ====================
@Override
public float getSpeed() { return homingData.getSpeed(); }
public void setSpeed(float speed) { homingData.setSpeed(speed); }
public AnchorPoint getAnchorPoint() { return anchorData.getAnchorPoint(); }
@Override
public int getAnchor() { return anchorData.getAnchor(); }
@Override
public float getAnchorOffsetX() { return anchorData.getAnchorOffsetX(); }
@Override
public float getAnchorOffsetY() { return anchorData.getAnchorOffsetY(); }
@Override
public float getAnchorOffsetZ() { return anchorData.getAnchorOffsetZ(); }
// ==================== MOVEMENT GETTERS ====================
@Override public double getStartX() { return startX; }
public double getStartX() { return startX; }
public double getStartY() { return startY; }
public double getStartZ() { return startZ; }
@Override public double getStartY() { return startY; }
// ==================== STATE GETTERS ====================
@Override public double getStartZ() { return startZ; }
@Override public double getMotionX() { return motionX; }
@Override public double getMotionY() { return motionY; }
@Override public double getMotionZ() { return motionZ; }
public boolean getHasHit() { return hasHit; }
// ==================== BRIGHTNESS ====================
+134
View File
@@ -1,6 +1,7 @@
package noppes.npcs;
import cpw.mods.fml.common.eventhandler.Event;
import kamkeel.npcs.entity.EntityAbilityProjectile;
import kamkeel.npcs.network.packets.data.AchievementPacket;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.Entity;
@@ -16,7 +17,10 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.event.entity.EntityEvent;
import net.minecraftforge.event.world.WorldEvent;
import noppes.npcs.api.IBlock;
import noppes.npcs.api.IPos;
import noppes.npcs.api.IWorld;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IAnimatable;
import noppes.npcs.api.entity.ICustomNpc;
import noppes.npcs.api.entity.IEntity;
@@ -52,6 +56,7 @@ import noppes.npcs.scripted.NpcAPI;
import noppes.npcs.scripted.event.AnimationEvent;
import noppes.npcs.scripted.event.BlockEvent;
import noppes.npcs.scripted.event.CustomNPCsEvent;
import noppes.npcs.scripted.event.EnergyProjectileEvent;
import noppes.npcs.scripted.event.ForgeEvent;
import noppes.npcs.scripted.event.ItemEvent;
import noppes.npcs.scripted.event.LinkedItemEvent;
@@ -448,6 +453,110 @@ public class EventHooks {
NpcAPI.EVENT_BUS.post(event);
}
// ==================== ENERGY PROJECTILE EVENTS ====================
public static void onEnergyProjectileFired(EntityAbilityProjectile projectile) {
IEnergyProjectile wrapped = (IEnergyProjectile) NpcAPI.Instance().getIEntity(projectile);
EnergyProjectileEvent.FiredEvent event = new EnergyProjectileEvent.FiredEvent(wrapped);
ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ENERGY_PROJECTILE_FIRED, event);
Entity owner = projectile.worldObj.getEntityByID(projectile.getOwnerEntityId());
if (owner instanceof EntityNPCInterface) {
((EntityNPCInterface) owner).script.callScript(EnumScriptType.ENERGY_PROJECTILE_FIRED, event);
} else if (owner instanceof EntityPlayer) {
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts((EntityPlayer) owner);
if (handler != null) {
handler.callScript(EnumScriptType.ENERGY_PROJECTILE_FIRED, event);
}
}
NpcAPI.EVENT_BUS.post(event);
}
public static void onEnergyProjectileTick(EntityAbilityProjectile projectile) {
IEnergyProjectile wrapped = (IEnergyProjectile) NpcAPI.Instance().getIEntity(projectile);
EnergyProjectileEvent.UpdateEvent event = new EnergyProjectileEvent.UpdateEvent(wrapped);
ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ENERGY_PROJECTILE_TICK, event);
Entity owner = projectile.worldObj.getEntityByID(projectile.getOwnerEntityId());
if (owner instanceof EntityNPCInterface) {
((EntityNPCInterface) owner).script.callScript(EnumScriptType.ENERGY_PROJECTILE_TICK, event);
} else if (owner instanceof EntityPlayer) {
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts((EntityPlayer) owner);
if (handler != null) {
handler.callScript(EnumScriptType.ENERGY_PROJECTILE_TICK, event);
}
}
NpcAPI.EVENT_BUS.post(event);
}
/**
* Fires the entity impact event. Returns the (possibly modified) damage, or -1 if cancelled.
*/
public static float onEnergyProjectileEntityImpact(EntityAbilityProjectile projectile, EntityLivingBase target, float damage) {
IEnergyProjectile wrapped = (IEnergyProjectile) NpcAPI.Instance().getIEntity(projectile);
IEntity wrappedTarget = NpcAPI.Instance().getIEntity(target);
EnergyProjectileEvent.EntityImpactEvent event = new EnergyProjectileEvent.EntityImpactEvent(wrapped, wrappedTarget, damage);
ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ENERGY_PROJECTILE_ENTITY_IMPACT, event);
Entity owner = projectile.worldObj.getEntityByID(projectile.getOwnerEntityId());
if (owner instanceof EntityNPCInterface) {
((EntityNPCInterface) owner).script.callScript(EnumScriptType.ENERGY_PROJECTILE_ENTITY_IMPACT, event);
} else if (owner instanceof EntityPlayer) {
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts((EntityPlayer) owner);
if (handler != null) {
handler.callScript(EnumScriptType.ENERGY_PROJECTILE_ENTITY_IMPACT, event);
}
}
NpcAPI.EVENT_BUS.post(event);
if (event.isCanceled()) {
return -1;
}
return event.getDamage();
}
public static void onEnergyProjectileBlockImpact(EntityAbilityProjectile projectile, int blockX, int blockY, int blockZ) {
IEnergyProjectile wrapped = (IEnergyProjectile) NpcAPI.Instance().getIEntity(projectile);
IPos pos = NpcAPI.Instance().getIPos(blockX, blockY, blockZ);
IWorld world = NpcAPI.Instance().getIWorld(projectile.worldObj);
IBlock block = NpcAPI.Instance().getIBlock(world, pos);
EnergyProjectileEvent.BlockImpactEvent event = new EnergyProjectileEvent.BlockImpactEvent(wrapped, block);
ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ENERGY_PROJECTILE_BLOCK_IMPACT, event);
Entity owner = projectile.worldObj.getEntityByID(projectile.getOwnerEntityId());
if (owner instanceof EntityNPCInterface) {
((EntityNPCInterface) owner).script.callScript(EnumScriptType.ENERGY_PROJECTILE_BLOCK_IMPACT, event);
} else if (owner instanceof EntityPlayer) {
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts((EntityPlayer) owner);
if (handler != null) {
handler.callScript(EnumScriptType.ENERGY_PROJECTILE_BLOCK_IMPACT, event);
}
}
NpcAPI.EVENT_BUS.post(event);
}
public static void onEnergyProjectileExpired(EntityAbilityProjectile projectile) {
IEnergyProjectile wrapped = (IEnergyProjectile) NpcAPI.Instance().getIEntity(projectile);
EnergyProjectileEvent.ExpiredEvent event = new EnergyProjectileEvent.ExpiredEvent(wrapped);
ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ENERGY_PROJECTILE_EXPIRED, event);
Entity owner = projectile.worldObj.getEntityByID(projectile.getOwnerEntityId());
if (owner instanceof EntityNPCInterface) {
((EntityNPCInterface) owner).script.callScript(EnumScriptType.ENERGY_PROJECTILE_EXPIRED, event);
} else if (owner instanceof EntityPlayer) {
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts((EntityPlayer) owner);
if (handler != null) {
handler.callScript(EnumScriptType.ENERGY_PROJECTILE_EXPIRED, event);
}
}
NpcAPI.EVENT_BUS.post(event);
}
public static void onPlayerInit(PlayerDataScript handler, IPlayer player) {
PlayerEvent.InitEvent event = new PlayerEvent.InitEvent(player);
handler.callScript(EnumScriptType.INIT, event);
@@ -693,6 +802,31 @@ public class EventHooks {
return NpcAPI.EVENT_BUS.post(event);
}
public static boolean onPlayerAbilityStart(PlayerDataScript handler, PlayerAbilityEvent.StartEvent event) {
handler.callScript(EnumScriptType.ABILITY_START, event);
return NpcAPI.EVENT_BUS.post(event);
}
public static boolean onPlayerAbilityExecute(PlayerDataScript handler, PlayerAbilityEvent.ExecuteEvent event) {
handler.callScript(EnumScriptType.ABILITY_EXECUTE, event);
return NpcAPI.EVENT_BUS.post(event);
}
public static void onPlayerAbilityTick(PlayerDataScript handler, PlayerAbilityEvent.TickEvent event) {
handler.callScript(EnumScriptType.ABILITY_TICK, event);
NpcAPI.EVENT_BUS.post(event);
}
public static void onPlayerAbilityInterrupt(PlayerDataScript handler, PlayerAbilityEvent.InterruptEvent event) {
handler.callScript(EnumScriptType.ABILITY_INTERRUPT, event);
NpcAPI.EVENT_BUS.post(event);
}
public static void onPlayerAbilityComplete(PlayerDataScript handler, PlayerAbilityEvent.CompleteEvent event) {
handler.callScript(EnumScriptType.ABILITY_COMPLETE, event);
NpcAPI.EVENT_BUS.post(event);
}
public static boolean onPlayerAbilityHit(PlayerDataScript handler, PlayerAbilityEvent.HitEvent event) {
handler.callScript(EnumScriptType.ABILITY_HIT, event);
return NpcAPI.EVENT_BUS.post(event);
@@ -9,6 +9,7 @@ import kamkeel.npcs.addon.DBCAddon;
import kamkeel.npcs.controllers.AttributeController;
import kamkeel.npcs.controllers.SyncController;
import kamkeel.npcs.controllers.data.ability.Ability;
import kamkeel.npcs.controllers.data.ability.AbilityController;
import kamkeel.npcs.util.AttributeAttackUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
@@ -106,7 +107,9 @@ public class ScriptPlayerEventHandler {
Ability current = playerData.abilityData.getCurrentAbility();
if (current == null || !current.hasAbilityMovement()) {
player.motionX = 0;
player.motionY = Math.min(player.motionY, 0); // Prevent jumping, allow gravity
if (!AbilityController.Instance.isPlayerFlying(player)) {
player.motionY = Math.min(player.motionY, 0);
}
player.motionZ = 0;
player.velocityChanged = true;
}
@@ -6,6 +6,7 @@ import cpw.mods.fml.common.gameevent.InputEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import kamkeel.npcs.client.renderer.lightning.LightningBolt;
import kamkeel.npcs.controllers.data.ability.AbilityController;
import kamkeel.npcs.controllers.data.telegraph.TelegraphManager;
import kamkeel.npcs.network.PacketClient;
import kamkeel.npcs.network.packets.player.CheckPlayerValue;
@@ -133,9 +134,10 @@ public class ClientTickHandler {
mc.thePlayer.motionZ = 0;
}
// Prevent jumping: clamp upward motion when locked (allow gravity)
// Prevent jumping when locked (allow gravity only if not flying)
if ((ClientAbilityState.movementLocked || ClientAbilityState.positionLocked)
&& !ClientAbilityState.hasAbilityMovement) {
&& !ClientAbilityState.hasAbilityMovement
&& !AbilityController.Instance.isPlayerFlying(mc.thePlayer)) {
mc.thePlayer.motionY = Math.min(mc.thePlayer.motionY, 0);
}
}
@@ -125,7 +125,13 @@ public enum EnumScriptType {
ABILITY_INTERRUPT("abilityInterrupt"),
ABILITY_COMPLETE("abilityComplete"),
ABILITY_HIT("abilityHit"),
ABILITY_TICK("abilityTick");
ABILITY_TICK("abilityTick"),
ENERGY_PROJECTILE_FIRED("energyProjectileFired"),
ENERGY_PROJECTILE_TICK("energyProjectileTick"),
ENERGY_PROJECTILE_ENTITY_IMPACT("energyProjectileEntityImpact"),
ENERGY_PROJECTILE_BLOCK_IMPACT("energyProjectileBlockImpact"),
ENERGY_PROJECTILE_EXPIRED("energyProjectileExpired");
public String function;
@@ -1,14 +1,17 @@
package noppes.npcs.constants;
import noppes.npcs.api.event.IAbilityEvent;
import noppes.npcs.api.event.IAnimationEvent;
import noppes.npcs.api.event.IBlockEvent;
import noppes.npcs.api.event.ICustomGuiEvent;
import noppes.npcs.api.event.IDialogEvent;
import noppes.npcs.api.event.IEnergyProjectileEvent;
import noppes.npcs.api.event.IFactionEvent;
import noppes.npcs.api.event.IForgeEvent;
import noppes.npcs.api.event.IItemEvent;
import noppes.npcs.api.event.INpcEvent;
import noppes.npcs.api.event.IPartyEvent;
import noppes.npcs.api.event.IPlayerAbilityEvent;
import noppes.npcs.api.event.IPlayerEvent;
import noppes.npcs.api.event.IProjectileEvent;
import noppes.npcs.api.event.IQuestEvent;
@@ -52,7 +55,10 @@ public class ScriptContext {
public static final ScriptContext NPC = register("NPC", "npc",
INpcEvent.class,
IProjectileEvent.class
IProjectileEvent.class,
IEnergyProjectileEvent.class,
IAbilityEvent.class,
IAnimationEvent.class
);
public static final ScriptContext PLAYER = register("PLAYER", "player",
@@ -62,7 +68,9 @@ public class ScriptContext {
IDialogEvent.class,
IQuestEvent.class,
IFactionEvent.class,
ICustomGuiEvent.class
ICustomGuiEvent.class,
IEnergyProjectileEvent.class,
IPlayerAbilityEvent.class
);
public static final ScriptContext BLOCK = register("BLOCK", "block",
@@ -2,10 +2,12 @@ package noppes.npcs.controllers;
import noppes.npcs.api.event.IAbilityEvent;
import noppes.npcs.api.event.IAnimationEvent;
import noppes.npcs.api.event.IPlayerAbilityEvent;
import noppes.npcs.api.event.IBlockEvent;
import noppes.npcs.api.event.ICustomGuiEvent;
import noppes.npcs.api.event.ICustomNPCsEvent;
import noppes.npcs.api.event.IDialogEvent;
import noppes.npcs.api.event.IEnergyProjectileEvent;
import noppes.npcs.api.event.IFactionEvent;
import noppes.npcs.api.event.IForgeEvent;
import noppes.npcs.api.event.IItemEvent;
@@ -106,6 +108,13 @@ public class ScriptHookController implements IScriptHookHandler {
hook(NPC, PROJECTILE_TICK, IProjectileEvent.UpdateEvent.class);
hook(NPC, PROJECTILE_IMPACT, IProjectileEvent.ImpactEvent.class);
// Energy Projectile
hook(NPC, ENERGY_PROJECTILE_FIRED, IEnergyProjectileEvent.FiredEvent.class);
hook(NPC, ENERGY_PROJECTILE_TICK, IEnergyProjectileEvent.UpdateEvent.class);
hook(NPC, ENERGY_PROJECTILE_ENTITY_IMPACT, IEnergyProjectileEvent.EntityImpactEvent.class);
hook(NPC, ENERGY_PROJECTILE_BLOCK_IMPACT, IEnergyProjectileEvent.BlockImpactEvent.class);
hook(NPC, ENERGY_PROJECTILE_EXPIRED, IEnergyProjectileEvent.ExpiredEvent.class);
// Ability
hook(NPC, ABILITY_START, IAbilityEvent.StartEvent.class);
hook(NPC, ABILITY_EXECUTE, IAbilityEvent.ExecuteEvent.class);
@@ -113,6 +122,12 @@ public class ScriptHookController implements IScriptHookHandler {
hook(NPC, ABILITY_TICK, IAbilityEvent.TickEvent.class);
hook(NPC, ABILITY_INTERRUPT, IAbilityEvent.InterruptEvent.class);
hook(NPC, ABILITY_COMPLETE, IAbilityEvent.CompleteEvent.class);
// Animation
hook(NPC, ANIMATION_START, IAnimationEvent.Started.class);
hook(NPC, ANIMATION_END, IAnimationEvent.Ended.class);
hook(NPC, ANIMATION_FRAME_ENTER, IAnimationEvent.IFrameEvent.Entered.class);
hook(NPC, ANIMATION_FRAME_EXIT, IAnimationEvent.IFrameEvent.Exited.class);
}
private void initializePlayerHooks() {
@@ -208,6 +223,21 @@ public class ScriptHookController implements IScriptHookHandler {
hook(PLAYER, ANIMATION_FRAME_ENTER, IAnimationEvent.IFrameEvent.Entered.class);
hook(PLAYER, ANIMATION_FRAME_EXIT, IAnimationEvent.IFrameEvent.Exited.class);
// Energy Projectile
hook(PLAYER, ENERGY_PROJECTILE_FIRED, IEnergyProjectileEvent.FiredEvent.class);
hook(PLAYER, ENERGY_PROJECTILE_TICK, IEnergyProjectileEvent.UpdateEvent.class);
hook(PLAYER, ENERGY_PROJECTILE_ENTITY_IMPACT, IEnergyProjectileEvent.EntityImpactEvent.class);
hook(PLAYER, ENERGY_PROJECTILE_BLOCK_IMPACT, IEnergyProjectileEvent.BlockImpactEvent.class);
hook(PLAYER, ENERGY_PROJECTILE_EXPIRED, IEnergyProjectileEvent.ExpiredEvent.class);
// Ability
hook(PLAYER, ABILITY_START, IPlayerAbilityEvent.StartEvent.class);
hook(PLAYER, ABILITY_EXECUTE, IPlayerAbilityEvent.ExecuteEvent.class);
hook(PLAYER, ABILITY_HIT, IPlayerAbilityEvent.HitEvent.class);
hook(PLAYER, ABILITY_TICK, IPlayerAbilityEvent.TickEvent.class);
hook(PLAYER, ABILITY_INTERRUPT, IPlayerAbilityEvent.InterruptEvent.class);
hook(PLAYER, ABILITY_COMPLETE, IPlayerAbilityEvent.CompleteEvent.class);
// Profile
hook(PLAYER, PROFILE_CHANGE, IPlayerEvent.ProfileEvent.Changed.class);
hook(PLAYER, PROFILE_REMOVE, IPlayerEvent.ProfileEvent.Removed.class);
@@ -16,9 +16,14 @@ import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.DamageSource;
import noppes.npcs.LogWriter;
import noppes.npcs.EventHooks;
import noppes.npcs.api.ability.IPlayerAbilityData;
import noppes.npcs.api.entity.IPlayer;
import noppes.npcs.controllers.AnimationController;
import noppes.npcs.controllers.ScriptController;
import noppes.npcs.controllers.data.Animation;
import noppes.npcs.scripted.NpcAPI;
import noppes.npcs.scripted.event.player.PlayerAbilityEvent;
import kamkeel.npcs.network.packets.data.ability.PlayerAbilityStatePacket;
import kamkeel.npcs.network.packets.data.ability.PlayerAbilitySyncPacket;
@@ -156,6 +161,9 @@ public class PlayerAbilityData implements IPlayerAbilityData {
// Tick advances time and possibly changes phase
boolean phaseChanged = currentAbility.tick();
// Fire tick event for scripts
firePlayerTickEvent(player, currentAbility, currentTarget);
// Fire extender tick hook (e.g., per-tick resource drain)
if (!AbilityController.Instance.fireOnAbilityTick(currentAbility, player, currentTarget,
currentAbility.getPhase(), currentAbility.getCurrentTick())) {
@@ -213,6 +221,11 @@ public class PlayerAbilityData implements IPlayerAbilityData {
playAbilitySound(player, currentAbility.getActiveSound());
playAbilityAnimation(currentAbility.getActiveAnimation());
// Fire execute event (cancelable)
if (firePlayerExecuteEvent(player, currentAbility, currentTarget)) {
return; // Cancelled
}
// Call onExecute
currentAbility.onExecute(player, currentTarget);
@@ -270,6 +283,9 @@ public class PlayerAbilityData implements IPlayerAbilityData {
currentAbility.onComplete(player, currentTarget);
// Fire complete event
firePlayerCompleteEvent(player, currentAbility, currentTarget);
// Release all locks
releaseRotationControl();
releaseLockedPosition();
@@ -342,6 +358,11 @@ public class PlayerAbilityData implements IPlayerAbilityData {
return false;
}
// Fire start event (cancelable)
if (firePlayerStartEvent(player, ability)) {
return false; // Cancelled
}
// Start the ability
currentAbility = ability;
currentAbilityKey = key;
@@ -382,6 +403,11 @@ public class PlayerAbilityData implements IPlayerAbilityData {
playAbilitySound(player, ability.getActiveSound());
playAbilityAnimation(ability.getActiveAnimation());
// Fire execute event (cancelable)
if (firePlayerExecuteEvent(player, ability, currentTarget)) {
return; // Cancelled
}
// Call onExecute
ability.onExecute(player, currentTarget);
@@ -540,10 +566,17 @@ public class PlayerAbilityData implements IPlayerAbilityData {
}
public void interruptCurrentAbility() {
interruptCurrentAbility(null, 0);
}
public void interruptCurrentAbility(DamageSource source, float damage) {
if (currentAbility != null && currentAbility.isExecuting()) {
// Fire extender complete hook (interrupted)
AbilityController.Instance.fireOnAbilityComplete(currentAbility, playerData.player, currentTarget, true);
// Fire interrupt event
firePlayerInterruptEvent(playerData.player, currentAbility, currentTarget, source, damage);
currentAbility.interrupt();
stopAbilityAnimation();
releaseRotationControl();
@@ -596,7 +629,7 @@ public class PlayerAbilityData implements IPlayerAbilityData {
// Check for ability interruption
if (currentAbility != null && currentAbility.canInterrupt(source)) {
interruptCurrentAbility();
interruptCurrentAbility(source, amount);
}
return amount;
@@ -836,6 +869,73 @@ public class PlayerAbilityData implements IPlayerAbilityData {
}
}
// ═══════════════════════════════════════════════════════════════════
// SCRIPT EVENTS
// ═══════════════════════════════════════════════════════════════════
/**
* Fire the ability start event. Returns true if cancelled.
*/
private boolean firePlayerStartEvent(EntityPlayer player, Ability ability) {
if (ScriptController.Instance == null) return false;
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts(player);
if (handler == null) return false;
IPlayer iPlayer = (IPlayer) NpcAPI.Instance().getIEntity(player);
PlayerAbilityEvent.StartEvent event = new PlayerAbilityEvent.StartEvent(iPlayer, ability, null);
return EventHooks.onPlayerAbilityStart(handler, event);
}
/**
* Fire the ability execute event. Returns true if cancelled.
*/
private boolean firePlayerExecuteEvent(EntityPlayer player, Ability ability, EntityLivingBase target) {
if (ScriptController.Instance == null) return false;
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts(player);
if (handler == null) return false;
IPlayer iPlayer = (IPlayer) NpcAPI.Instance().getIEntity(player);
PlayerAbilityEvent.ExecuteEvent event = new PlayerAbilityEvent.ExecuteEvent(iPlayer, ability, target);
return EventHooks.onPlayerAbilityExecute(handler, event);
}
/**
* Fire the ability tick event.
*/
private void firePlayerTickEvent(EntityPlayer player, Ability ability, EntityLivingBase target) {
if (ScriptController.Instance == null) return;
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts(player);
if (handler == null) return;
IPlayer iPlayer = (IPlayer) NpcAPI.Instance().getIEntity(player);
PlayerAbilityEvent.TickEvent event = new PlayerAbilityEvent.TickEvent(
iPlayer, ability, target, ability.getPhase().ordinal(), ability.getCurrentTick());
EventHooks.onPlayerAbilityTick(handler, event);
}
/**
* Fire the ability interrupt event.
*/
private void firePlayerInterruptEvent(EntityPlayer player, Ability ability, EntityLivingBase target,
DamageSource source, float damage) {
if (ScriptController.Instance == null) return;
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts(player);
if (handler == null) return;
IPlayer iPlayer = (IPlayer) NpcAPI.Instance().getIEntity(player);
PlayerAbilityEvent.InterruptEvent event = new PlayerAbilityEvent.InterruptEvent(
iPlayer, ability, target, source, damage);
EventHooks.onPlayerAbilityInterrupt(handler, event);
}
/**
* Fire the ability complete event.
*/
private void firePlayerCompleteEvent(EntityPlayer player, Ability ability, EntityLivingBase target) {
if (ScriptController.Instance == null) return;
PlayerDataScript handler = ScriptController.Instance.getPlayerScripts(player);
if (handler == null) return;
IPlayer iPlayer = (IPlayer) NpcAPI.Instance().getIEntity(player);
PlayerAbilityEvent.CompleteEvent event = new PlayerAbilityEvent.CompleteEvent(iPlayer, ability, target);
EventHooks.onPlayerAbilityComplete(handler, event);
}
// ═══════════════════════════════════════════════════════════════════
// NBT SERIALIZATION
// ═══════════════════════════════════════════════════════════════════
@@ -7,6 +7,10 @@ import kamkeel.npcs.controllers.AttributeController;
import kamkeel.npcs.controllers.ProfileController;
import kamkeel.npcs.controllers.TelegraphController;
import kamkeel.npcs.controllers.data.ability.AbilityController;
import kamkeel.npcs.entity.EntityAbilityBeam;
import kamkeel.npcs.entity.EntityAbilityDisc;
import kamkeel.npcs.entity.EntityAbilityLaser;
import kamkeel.npcs.entity.EntityAbilityOrb;
import net.minecraft.block.Block;
import net.minecraft.command.CommandHandler;
import net.minecraft.entity.Entity;
@@ -119,6 +123,10 @@ import noppes.npcs.items.ItemScripted;
import noppes.npcs.scripted.entity.ScriptAnimal;
import noppes.npcs.scripted.entity.ScriptArrow;
import noppes.npcs.scripted.entity.ScriptDBCPlayer;
import noppes.npcs.scripted.entity.ScriptEnergyBeam;
import noppes.npcs.scripted.entity.ScriptEnergyDisc;
import noppes.npcs.scripted.entity.ScriptEnergyLaser;
import noppes.npcs.scripted.entity.ScriptEnergyOrb;
import noppes.npcs.scripted.entity.ScriptEntity;
import noppes.npcs.scripted.entity.ScriptEntityItem;
import noppes.npcs.scripted.entity.ScriptFishHook;
@@ -454,6 +462,14 @@ public class NpcAPI extends AbstractNpcAPI {
data = new ScriptEntityData(new ScriptArrow<>((EntityArrow) entity));
else if (entity instanceof EntityFishHook)
data = new ScriptEntityData(new ScriptFishHook<>((EntityFishHook) entity));
else if (entity instanceof EntityAbilityOrb)
data = new ScriptEntityData(new ScriptEnergyOrb<>((EntityAbilityOrb) entity));
else if (entity instanceof EntityAbilityBeam)
data = new ScriptEntityData(new ScriptEnergyBeam<>((EntityAbilityBeam) entity));
else if (entity instanceof EntityAbilityDisc)
data = new ScriptEntityData(new ScriptEnergyDisc<>((EntityAbilityDisc) entity));
else if (entity instanceof EntityAbilityLaser)
data = new ScriptEntityData(new ScriptEnergyLaser<>((EntityAbilityLaser) entity));
else
data = new ScriptEntityData(new ScriptEntity<>(entity));
entity.registerExtendedProperties("ScriptedObject", data);
@@ -21,6 +21,10 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.world.BlockEvent;
import kamkeel.npcs.entity.EntityAbilityBeam;
import kamkeel.npcs.entity.EntityAbilityDisc;
import kamkeel.npcs.entity.EntityAbilityLaser;
import kamkeel.npcs.entity.EntityAbilityOrb;
import noppes.npcs.CustomNpcs;
import noppes.npcs.NoppesUtilServer;
import noppes.npcs.api.IBlock;
@@ -28,6 +32,10 @@ import noppes.npcs.api.IParticle;
import noppes.npcs.api.IPos;
import noppes.npcs.api.ITileEntity;
import noppes.npcs.api.IWorld;
import noppes.npcs.api.entity.IEnergyBeam;
import noppes.npcs.api.entity.IEnergyDisc;
import noppes.npcs.api.entity.IEnergyLaser;
import noppes.npcs.api.entity.IEnergyOrb;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.api.entity.IPlayer;
import noppes.npcs.api.handler.data.ISound;
@@ -1242,6 +1250,48 @@ public class ScriptWorld implements IWorld {
return "DIM" + this.getDimensionID();
}
@Override
public IEnergyOrb createEnergyOrb(IEntity owner, double x, double y, double z, float size) {
EntityAbilityOrb entity = new EntityAbilityOrb(world);
entity.setPosition(x, y, z);
entity.setStartPosition(x, y, z);
entity.setOwnerEntityId(owner.getMCEntity().getEntityId());
entity.setProjectileSize(size);
return (IEnergyOrb) NpcAPI.Instance().getIEntity(entity);
}
@Override
public IEnergyBeam createEnergyBeam(IEntity owner, double x, double y, double z, float beamWidth, float headSize) {
EntityAbilityBeam entity = new EntityAbilityBeam(world);
entity.setPosition(x, y, z);
entity.setStartPosition(x, y, z);
entity.setOwnerEntityId(owner.getMCEntity().getEntityId());
entity.setBeamWidth(beamWidth);
entity.setHeadSize(headSize);
return (IEnergyBeam) NpcAPI.Instance().getIEntity(entity);
}
@Override
public IEnergyDisc createEnergyDisc(IEntity owner, double x, double y, double z, float radius, float thickness) {
EntityAbilityDisc entity = new EntityAbilityDisc(world);
entity.setPosition(x, y, z);
entity.setStartPosition(x, y, z);
entity.setOwnerEntityId(owner.getMCEntity().getEntityId());
entity.setDiscRadius(radius);
entity.setDiscThickness(thickness);
return (IEnergyDisc) NpcAPI.Instance().getIEntity(entity);
}
@Override
public IEnergyLaser createEnergyLaser(IEntity owner, double x, double y, double z, float laserWidth) {
EntityAbilityLaser entity = new EntityAbilityLaser(world);
entity.setPosition(x, y, z);
entity.setStartPosition(x, y, z);
entity.setOwnerEntityId(owner.getMCEntity().getEntityId());
entity.setLaserWidth(laserWidth);
return (IEnergyLaser) NpcAPI.Instance().getIEntity(entity);
}
@Override
public void broadcast(String message) {
world.func_73046_m().getConfigurationManager().sendChatMsg(new ChatComponentText(message));
@@ -15,4 +15,8 @@ public class EntityType {
public static final int THROWABLE = 11;
public static final int FISH_HOOK = 12;
public static final int ENERGY_PROJECTILE = 13;
public static final int ENERGY_ORB = 14;
public static final int ENERGY_BEAM = 15;
public static final int ENERGY_DISC = 16;
public static final int ENERGY_LASER = 17;
}
@@ -0,0 +1,69 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.entity.EntityAbilityBeam;
import net.minecraft.entity.EntityLivingBase;
import noppes.npcs.api.entity.IEnergyBeam;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.scripted.constants.EntityType;
public class ScriptEnergyBeam<T extends EntityAbilityBeam> extends ScriptEnergyProjectile<T> implements IEnergyBeam {
public ScriptEnergyBeam(T entity) {
super(entity);
}
@Override
public int getType() {
return EntityType.ENERGY_BEAM;
}
@Override
public boolean typeOf(int type) {
return type == EntityType.ENERGY_BEAM || super.typeOf(type);
}
@Override
public int getEnergyType() {
return 1;
}
// ==================== BEAM-SPECIFIC ====================
public float getBeamWidth() { return entity.getBeamWidth(); }
public void setBeamWidth(float width) { entity.setBeamWidth(width); }
public float getHeadSize() { return entity.getHeadSize(); }
public void setHeadSize(float size) { entity.setHeadSize(size); }
public boolean isAttachedToOwner() { return entity.isAttachedToOwner(); }
public void setAttachedToOwner(boolean attached) { entity.setAttachedToOwner(attached); }
public boolean shouldRenderTailOrb() { return entity.shouldRenderTailOrb(); }
// ==================== FIRE ====================
@Override
public void fire(IEntity target) {
ensureSpawned();
EntityLivingBase mcTarget = null;
if (target != null && target.getMCEntity() instanceof EntityLivingBase) {
mcTarget = (EntityLivingBase) target.getMCEntity();
}
entity.startFiring(mcTarget);
}
@Override
public void fire(double x, double y, double z) {
ensureSpawned();
double dx = x - entity.posX;
double dy = y - entity.posY;
double dz = z - entity.posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
entity.motionX = (dx / len) * entity.getSpeed();
entity.motionY = (dy / len) * entity.getSpeed();
entity.motionZ = (dz / len) * entity.getSpeed();
}
entity.startFiring(null);
}
}
@@ -0,0 +1,75 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.entity.EntityAbilityDisc;
import net.minecraft.entity.EntityLivingBase;
import noppes.npcs.api.entity.IEnergyDisc;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.scripted.constants.EntityType;
public class ScriptEnergyDisc<T extends EntityAbilityDisc> extends ScriptEnergyProjectile<T> implements IEnergyDisc {
public ScriptEnergyDisc(T entity) {
super(entity);
}
@Override
public int getType() {
return EntityType.ENERGY_DISC;
}
@Override
public boolean typeOf(int type) {
return type == EntityType.ENERGY_DISC || super.typeOf(type);
}
@Override
public int getEnergyType() {
return 2;
}
// ==================== DISC-SPECIFIC ====================
public float getDiscRadius() { return entity.getDiscRadius(); }
public void setDiscRadius(float radius) { entity.setDiscRadius(radius); }
public float getDiscThickness() { return entity.getDiscThickness(); }
public void setDiscThickness(float thickness) { entity.setDiscThickness(thickness); }
public boolean isVertical() { return entity.isVertical(); }
public void setVertical(boolean vertical) { entity.setVertical(vertical); }
public boolean isBoomerang() { return entity.isBoomerang(); }
public void setBoomerang(boolean boomerang) { entity.setBoomerang(boomerang); }
public int getBoomerangDelay() { return entity.getBoomerangDelay(); }
public void setBoomerangDelay(int ticks) { entity.setBoomerangDelay(ticks); }
public boolean isReturning() { return entity.isReturning(); }
// ==================== FIRE ====================
@Override
public void fire(IEntity target) {
ensureSpawned();
EntityLivingBase mcTarget = null;
if (target != null && target.getMCEntity() instanceof EntityLivingBase) {
mcTarget = (EntityLivingBase) target.getMCEntity();
}
entity.startMoving(mcTarget);
}
@Override
public void fire(double x, double y, double z) {
ensureSpawned();
double dx = x - entity.posX;
double dy = y - entity.posY;
double dz = z - entity.posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
entity.motionX = (dx / len) * entity.getSpeed();
entity.motionY = (dy / len) * entity.getSpeed();
entity.motionZ = (dz / len) * entity.getSpeed();
}
entity.startMoving(null);
}
}
@@ -0,0 +1,82 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.entity.EntityAbilityLaser;
import net.minecraft.entity.EntityLivingBase;
import noppes.npcs.api.entity.IEnergyLaser;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.scripted.constants.EntityType;
public class ScriptEnergyLaser<T extends EntityAbilityLaser> extends ScriptEnergyProjectile<T> implements IEnergyLaser {
public ScriptEnergyLaser(T entity) {
super(entity);
}
@Override
public int getType() {
return EntityType.ENERGY_LASER;
}
@Override
public boolean typeOf(int type) {
return type == EntityType.ENERGY_LASER || super.typeOf(type);
}
@Override
public int getEnergyType() {
return 3;
}
// ==================== LASER-SPECIFIC ====================
public float getLaserWidth() { return entity.getLaserWidth(); }
public void setLaserWidth(float width) { entity.setLaserWidth(width); }
public float getExpansionSpeed() { return entity.getExpansionSpeed(); }
public void setExpansionSpeed(float speed) { entity.setExpansionSpeed(speed); }
public int getLingerTicks() { return entity.getLingerTicks(); }
public void setLingerTicks(int ticks) { entity.setLingerTicks(ticks); }
public float getCurrentLength() { return entity.getCurrentLength(); }
public boolean isFullyExtended() { return entity.isFullyExtended(); }
public double getDirX() { return entity.getDirX(); }
public double getDirY() { return entity.getDirY(); }
public double getDirZ() { return entity.getDirZ(); }
public void setDirection(double x, double y, double z) { entity.setDirection(x, y, z); }
public double getEndX() { return entity.getEndX(); }
public double getEndY() { return entity.getEndY(); }
public double getEndZ() { return entity.getEndZ(); }
public float getLingerAlpha() { return entity.getLingerAlpha(); }
public boolean isLockVerticalDirection() { return entity.isLockVerticalDirection(); }
public void setLockVerticalDirection(boolean lock) { entity.setLockVerticalDirection(lock); }
// ==================== FIRE ====================
@Override
public void fire(IEntity target) {
ensureSpawned();
EntityLivingBase mcTarget = null;
if (target != null && target.getMCEntity() instanceof EntityLivingBase) {
mcTarget = (EntityLivingBase) target.getMCEntity();
}
entity.startMoving(mcTarget);
}
@Override
public void fire(double x, double y, double z) {
ensureSpawned();
double dx = x - entity.posX;
double dy = y - entity.posY;
double dz = z - entity.posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
entity.setDirection(dx / len, dy / len, dz / len);
}
entity.startMoving(null);
}
}
@@ -0,0 +1,53 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.entity.EntityAbilityOrb;
import net.minecraft.entity.EntityLivingBase;
import noppes.npcs.api.entity.IEnergyOrb;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.scripted.constants.EntityType;
public class ScriptEnergyOrb<T extends EntityAbilityOrb> extends ScriptEnergyProjectile<T> implements IEnergyOrb {
public ScriptEnergyOrb(T entity) {
super(entity);
}
@Override
public int getType() {
return EntityType.ENERGY_ORB;
}
@Override
public boolean typeOf(int type) {
return type == EntityType.ENERGY_ORB || super.typeOf(type);
}
@Override
public int getEnergyType() {
return 0;
}
@Override
public void fire(IEntity target) {
ensureSpawned();
EntityLivingBase mcTarget = null;
if (target != null && target.getMCEntity() instanceof EntityLivingBase) {
mcTarget = (EntityLivingBase) target.getMCEntity();
}
entity.startMoving(mcTarget);
}
@Override
public void fire(double x, double y, double z) {
ensureSpawned();
double dx = x - entity.posX;
double dy = y - entity.posY;
double dz = z - entity.posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
entity.motionX = (dx / len) * entity.getSpeed();
entity.motionY = (dy / len) * entity.getSpeed();
entity.motionZ = (dz / len) * entity.getSpeed();
}
}
}
@@ -0,0 +1,252 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.entity.EntityAbilityProjectile;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.api.entity.IEntityLivingBase;
import noppes.npcs.EventHooks;
import noppes.npcs.scripted.NpcAPI;
import noppes.npcs.scripted.constants.EntityType;
public class ScriptEnergyProjectile<T extends EntityAbilityProjectile> extends ScriptEntity<T> implements IEnergyProjectile {
protected T entity;
public ScriptEnergyProjectile(T entity) {
super(entity);
this.entity = entity;
}
// ==================== TYPE ====================
@Override
public int getType() {
return EntityType.ENERGY_PROJECTILE;
}
@Override
public boolean typeOf(int type) {
return type == EntityType.ENERGY_PROJECTILE || super.typeOf(type);
}
public int getEnergyType() {
return -1;
}
// ==================== OWNER & TARGET ====================
public int getOwnerEntityId() {
return entity.getOwnerEntityId();
}
public IEntity getOwner() {
return entity.getOwner();
}
public void setOwner(IEntity owner) {
if (owner != null) {
entity.setOwnerEntityId(owner.getMCEntity().getEntityId());
}
}
public int getTargetEntityId() {
return entity.getTargetEntityId();
}
public IEntity getTarget() {
return entity.getTarget();
}
public void setTarget(IEntity target) {
if (target != null) {
entity.setTargetEntityId(target.getMCEntity().getEntityId());
} else {
entity.setTargetEntityId(-1);
}
}
// ==================== SIZE ====================
public float getSize() {
return entity.getSize();
}
public void setSize(float size) {
entity.setProjectileSize(size);
}
// ==================== DISPLAY ====================
public int getInnerColor() { return entity.getInnerColor(); }
public void setInnerColor(int color) { entity.setInnerColor(color); }
public int getOuterColor() { return entity.getOuterColor(); }
public void setOuterColor(int color) { entity.setOuterColor(color); }
public boolean isOuterColorEnabled() { return entity.isOuterColorEnabled(); }
public void setOuterColorEnabled(boolean enabled) { entity.setOuterColorEnabled(enabled); }
public float getOuterColorWidth() { return entity.getOuterColorWidth(); }
public void setOuterColorWidth(float width) { entity.setOuterColorWidth(width); }
public float getOuterColorAlpha() { return entity.getOuterColorAlpha(); }
public void setOuterColorAlpha(float alpha) { entity.setOuterColorAlpha(alpha); }
public float getRotationSpeed() { return entity.getRotationSpeed(); }
public void setRotationSpeed(float speed) { entity.setRotationSpeed(speed); }
// ==================== INTERPOLATION ====================
public float getInterpolatedRotationX(float partialTicks) { return entity.getInterpolatedRotationX(partialTicks); }
public float getInterpolatedRotationY(float partialTicks) { return entity.getInterpolatedRotationY(partialTicks); }
public float getInterpolatedRotationZ(float partialTicks) { return entity.getInterpolatedRotationZ(partialTicks); }
public float getInterpolatedSize(float partialTicks) { return entity.getInterpolatedSize(partialTicks); }
// ==================== LIGHTNING ====================
public boolean hasLightningEffect() { return entity.hasLightningEffect(); }
public void setLightningEffect(boolean enabled) { entity.setLightningEffect(enabled); }
public float getLightningDensity() { return entity.getLightningDensity(); }
public void setLightningDensity(float density) { entity.setLightningDensity(density); }
public float getLightningRadius() { return entity.getLightningRadius(); }
public void setLightningRadius(float radius) { entity.setLightningRadius(radius); }
public int getLightningFadeTime() { return entity.getLightningFadeTime(); }
public void setLightningFadeTime(int ticks) { entity.setLightningFadeTime(ticks); }
// ==================== LIFESPAN ====================
public float getMaxDistance() { return entity.getMaxDistance(); }
public void setMaxDistance(float distance) { entity.setMaxDistance(distance); }
public int getMaxLifetime() { return entity.getMaxLifetime(); }
public void setMaxLifetime(int ticks) { entity.setMaxLifetime(ticks); }
// ==================== COMBAT ====================
public float getDamage() { return entity.getDamage(); }
public void setDamage(float damage) { entity.setCombatDamage(damage); }
public float getKnockback() { return entity.getKnockback(); }
public void setKnockback(float knockback) { entity.setCombatKnockback(knockback); }
public float getKnockbackUp() { return entity.getKnockbackUp(); }
public void setKnockbackUp(float knockbackUp) { entity.setCombatKnockbackUp(knockbackUp); }
public boolean isExplosive() { return entity.isExplosive(); }
public void setExplosive(boolean explosive) { entity.setExplosive(explosive); }
public float getExplosionRadius() { return entity.getExplosionRadius(); }
public void setExplosionRadius(float radius) { entity.setExplosionRadius(radius); }
public float getExplosionDamageFalloff() { return entity.getExplosionDamageFalloff(); }
public void setExplosionDamageFalloff(float falloff) { entity.setExplosionDamageFalloff(falloff); }
// ==================== MOVEMENT ====================
public float getSpeed() { return entity.getSpeed(); }
public void setSpeed(float speed) { entity.setSpeed(speed); }
public boolean isHoming() { return entity.isHoming(); }
public void setHoming(boolean homing) { entity.setHomingEnabled(homing); }
public float getHomingStrength() { return entity.getHomingStrength(); }
public void setHomingStrength(float strength) { entity.setHomingStrength(strength); }
public float getHomingRange() { return entity.getHomingRange(); }
public void setHomingRange(float range) { entity.setHomingRange(range); }
// ==================== ANCHOR ====================
public int getAnchor() { return entity.getAnchor(); }
public float getAnchorOffsetX() { return entity.getAnchorOffsetX(); }
public float getAnchorOffsetY() { return entity.getAnchorOffsetY(); }
public float getAnchorOffsetZ() { return entity.getAnchorOffsetZ(); }
// ==================== POSITION ====================
public double getStartX() { return entity.getStartX(); }
public double getStartY() { return entity.getStartY(); }
public double getStartZ() { return entity.getStartZ(); }
// ==================== STATE ====================
public boolean hasHit() { return entity.getHasHit(); }
public boolean isCharging() { return entity.isCharging(); }
public float getChargeProgress() { return entity.getChargeProgress(); }
// ==================== FIRE ====================
public void fire(IEntity target) {
if (target != null) {
Entity mcTarget = target.getMCEntity();
setMotionToward(mcTarget.posX, mcTarget.posY + mcTarget.getEyeHeight(), mcTarget.posZ);
}
ensureSpawned();
}
public void fire(double x, double y, double z) {
setMotionToward(x, y, z);
ensureSpawned();
}
public void fire(float yaw, float pitch) {
float yawRad = (float) Math.toRadians(yaw);
float pitchRad = (float) Math.toRadians(pitch);
entity.motionX = -Math.sin(yawRad) * Math.cos(pitchRad) * entity.getSpeed();
entity.motionY = -Math.sin(pitchRad) * entity.getSpeed();
entity.motionZ = Math.cos(yawRad) * Math.cos(pitchRad) * entity.getSpeed();
ensureSpawned();
}
public void fire(IEntityLivingBase caster) {
if (caster == null) return;
initFromCaster(caster);
fire(caster.getRotation(), caster.getPitch());
}
public void fire(IEntityLivingBase caster, IEntity target) {
if (caster == null) return;
initFromCaster(caster);
fire(target);
}
/**
* Sets owner from caster and positions projectile at caster's eye level.
*/
private void initFromCaster(IEntityLivingBase caster) {
EntityLivingBase mc = (EntityLivingBase) caster.getMCEntity();
entity.setOwnerEntityId(mc.getEntityId());
double eyeY = mc.posY + mc.getEyeHeight();
entity.setPosition(mc.posX, eyeY, mc.posZ);
entity.setStartPosition(mc.posX, eyeY, mc.posZ);
}
/**
* Calculates and sets motion from the projectile's current position toward a target point.
*/
private void setMotionToward(double x, double y, double z) {
double dx = x - entity.posX;
double dy = y - entity.posY;
double dz = z - entity.posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
entity.motionX = (dx / len) * entity.getSpeed();
entity.motionY = (dy / len) * entity.getSpeed();
entity.motionZ = (dz / len) * entity.getSpeed();
}
}
protected void ensureSpawned() {
if (!entity.addedToChunk && entity.worldObj != null) {
entity.worldObj.spawnEntityInWorld(entity);
if (!entity.worldObj.isRemote) {
EventHooks.onEnergyProjectileFired(entity);
}
}
}
}
@@ -1,5 +1,10 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.entity.EntityAbilityBeam;
import kamkeel.npcs.entity.EntityAbilityDisc;
import kamkeel.npcs.entity.EntityAbilityLaser;
import kamkeel.npcs.entity.EntityAbilityOrb;
import kamkeel.npcs.entity.EntityAbilityProjectile;
import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
@@ -526,6 +531,16 @@ public class ScriptEntity<T extends Entity> implements IEntity {
cls = EntityMob.class;
else if (type == EntityType.NPC)
cls = EntityNPCInterface.class;
else if (type == EntityType.ENERGY_PROJECTILE)
cls = EntityAbilityProjectile.class;
else if (type == EntityType.ENERGY_ORB)
cls = EntityAbilityOrb.class;
else if (type == EntityType.ENERGY_BEAM)
cls = EntityAbilityBeam.class;
else if (type == EntityType.ENERGY_DISC)
cls = EntityAbilityDisc.class;
else if (type == EntityType.ENERGY_LASER)
cls = EntityAbilityLaser.class;
List<Entity> entities = entity.worldObj.getEntitiesWithinAABB(cls, entity.boundingBox.expand(range, range, range));
List<IEntity> list = new ArrayList<IEntity>();
@@ -7,6 +7,7 @@ import noppes.npcs.api.IPos;
import noppes.npcs.api.ITimers;
import noppes.npcs.api.ability.IDataAbilities;
import noppes.npcs.api.entity.ICustomNpc;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IEntityLivingBase;
import noppes.npcs.api.entity.IPlayer;
import noppes.npcs.api.entity.data.IModelData;
@@ -28,6 +29,7 @@ import noppes.npcs.constants.EnumMovingType;
import noppes.npcs.constants.EnumNavType;
import noppes.npcs.constants.EnumRoleType;
import noppes.npcs.constants.EnumStandingType;
import kamkeel.npcs.entity.EntityAbilityProjectile;
import noppes.npcs.controllers.FactionController;
import noppes.npcs.controllers.data.DialogOption;
import noppes.npcs.controllers.data.Line;
@@ -1463,4 +1465,13 @@ public class ScriptNpc<T extends EntityNPCInterface> extends ScriptLiving<T> imp
public IDataAbilities getAbilityData() {
return new ScriptDataAbilities(npc);
}
public IEnergyProjectile[] getActiveEnergyProjectiles() {
java.util.List<EntityAbilityProjectile> entities = EntityAbilityProjectile.getActiveProjectiles(npc.getEntityId());
IEnergyProjectile[] result = new IEnergyProjectile[entities.size()];
for (int i = 0; i < entities.size(); i++) {
result[i] = (IEnergyProjectile) NpcAPI.Instance().getIEntity(entities.get(i));
}
return result;
}
}
@@ -1,6 +1,7 @@
package noppes.npcs.scripted.entity;
import kamkeel.npcs.controllers.AttributeController;
import kamkeel.npcs.entity.EntityAbilityProjectile;
import kamkeel.npcs.network.PacketHandler;
import kamkeel.npcs.network.packets.data.AchievementPacket;
import kamkeel.npcs.network.packets.data.ChatAlertPacket;
@@ -31,6 +32,7 @@ import noppes.npcs.api.IPos;
import noppes.npcs.api.IScreenSize;
import noppes.npcs.api.ITimers;
import noppes.npcs.api.IWorld;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.api.entity.IPlayer;
import noppes.npcs.api.gui.ICustomGui;
@@ -933,4 +935,13 @@ public class ScriptPlayer<T extends EntityPlayerMP> extends ScriptLivingBase<T>
public String getFormattedCurrencyBalance() {
return getData().tradeData.formatBalance();
}
public IEnergyProjectile[] getActiveEnergyProjectiles() {
List<EntityAbilityProjectile> entities = EntityAbilityProjectile.getActiveProjectiles(player.getEntityId());
IEnergyProjectile[] result = new IEnergyProjectile[entities.size()];
for (int i = 0; i < entities.size(); i++) {
result[i] = (IEnergyProjectile) NpcAPI.Instance().getIEntity(entities.get(i));
}
return result;
}
}
@@ -0,0 +1,132 @@
package noppes.npcs.scripted.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import noppes.npcs.api.IBlock;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.api.event.IEnergyProjectileEvent;
import noppes.npcs.constants.EnumScriptType;
public class EnergyProjectileEvent extends CustomNPCsEvent implements IEnergyProjectileEvent {
public final IEnergyProjectile projectile;
public final IEntity owner;
public EnergyProjectileEvent(IEnergyProjectile projectile) {
this.projectile = projectile;
this.owner = projectile.getOwner();
}
@Override
public IEnergyProjectile getProjectile() {
return projectile;
}
@Override
public IEntity getOwner() {
return owner;
}
@Override
public String getHookName() {
return "energyProjectileEvent";
}
/**
* energyProjectileFired
*/
public static class FiredEvent extends EnergyProjectileEvent implements IEnergyProjectileEvent.FiredEvent {
public FiredEvent(IEnergyProjectile projectile) {
super(projectile);
}
@Override
public String getHookName() {
return EnumScriptType.ENERGY_PROJECTILE_FIRED.function;
}
}
/**
* energyProjectileTick
*/
public static class UpdateEvent extends EnergyProjectileEvent implements IEnergyProjectileEvent.UpdateEvent {
public UpdateEvent(IEnergyProjectile projectile) {
super(projectile);
}
@Override
public String getHookName() {
return EnumScriptType.ENERGY_PROJECTILE_TICK.function;
}
}
/**
* energyProjectileEntityImpact
*/
@Cancelable
public static class EntityImpactEvent extends EnergyProjectileEvent implements IEnergyProjectileEvent.EntityImpactEvent {
private final IEntity target;
private float damage;
public EntityImpactEvent(IEnergyProjectile projectile, IEntity target, float damage) {
super(projectile);
this.target = target;
this.damage = damage;
}
@Override
public IEntity getTarget() {
return target;
}
@Override
public float getDamage() {
return damage;
}
@Override
public void setDamage(float damage) {
this.damage = damage;
}
@Override
public String getHookName() {
return EnumScriptType.ENERGY_PROJECTILE_ENTITY_IMPACT.function;
}
}
/**
* energyProjectileBlockImpact
*/
public static class BlockImpactEvent extends EnergyProjectileEvent implements IEnergyProjectileEvent.BlockImpactEvent {
private final IBlock block;
public BlockImpactEvent(IEnergyProjectile projectile, IBlock block) {
super(projectile);
this.block = block;
}
@Override
public IBlock getBlock() {
return block;
}
@Override
public String getHookName() {
return EnumScriptType.ENERGY_PROJECTILE_BLOCK_IMPACT.function;
}
}
/**
* energyProjectileExpired
*/
public static class ExpiredEvent extends EnergyProjectileEvent implements IEnergyProjectileEvent.ExpiredEvent {
public ExpiredEvent(IEnergyProjectile projectile) {
super(projectile);
}
@Override
public String getHookName() {
return EnumScriptType.ENERGY_PROJECTILE_EXPIRED.function;
}
}
}
@@ -3,6 +3,8 @@ package noppes.npcs.scripted.event.player;
import cpw.mods.fml.common.eventhandler.Cancelable;
import kamkeel.npcs.controllers.data.ability.Ability;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.DamageSource;
import noppes.npcs.api.IDamageSource;
import noppes.npcs.api.ability.IAbility;
import noppes.npcs.api.entity.IEntityLivingBase;
import noppes.npcs.api.entity.IPlayer;
@@ -38,6 +40,108 @@ public class PlayerAbilityEvent extends PlayerEvent implements IPlayerAbilityEve
return "playerAbilityEvent";
}
/**
* Fired when a player's ability starts executing (enters WINDUP phase).
*/
@Cancelable
public static class StartEvent extends PlayerAbilityEvent implements IPlayerAbilityEvent.StartEvent {
public StartEvent(IPlayer player, Ability ability, EntityLivingBase target) {
super(player, ability, target);
}
@Override
public String getHookName() {
return EnumScriptType.ABILITY_START.function;
}
}
/**
* Fired when a player's ability enters the ACTIVE phase and performs its effect.
*/
@Cancelable
public static class ExecuteEvent extends PlayerAbilityEvent implements IPlayerAbilityEvent.ExecuteEvent {
public ExecuteEvent(IPlayer player, Ability ability, EntityLivingBase target) {
super(player, ability, target);
}
@Override
public String getHookName() {
return EnumScriptType.ABILITY_EXECUTE.function;
}
}
/**
* Fired when a player's ability is interrupted by damage.
*/
public static class InterruptEvent extends PlayerAbilityEvent implements IPlayerAbilityEvent.InterruptEvent {
private final IDamageSource damageSource;
private final float damage;
public InterruptEvent(IPlayer player, Ability ability, EntityLivingBase target, DamageSource source, float damage) {
super(player, ability, target);
this.damageSource = source != null ? NpcAPI.Instance().getIDamageSource(source) : null;
this.damage = damage;
}
@Override
public IDamageSource getDamageSource() {
return damageSource;
}
@Override
public float getDamage() {
return damage;
}
@Override
public String getHookName() {
return EnumScriptType.ABILITY_INTERRUPT.function;
}
}
/**
* Fired when a player's ability completes its full execution cycle.
*/
public static class CompleteEvent extends PlayerAbilityEvent implements IPlayerAbilityEvent.CompleteEvent {
public CompleteEvent(IPlayer player, Ability ability, EntityLivingBase target) {
super(player, ability, target);
}
@Override
public String getHookName() {
return EnumScriptType.ABILITY_COMPLETE.function;
}
}
/**
* Fired every tick while a player's ability is executing.
*/
public static class TickEvent extends PlayerAbilityEvent implements IPlayerAbilityEvent.TickEvent {
private final int abilityPhase;
private final int tick;
public TickEvent(IPlayer player, Ability ability, EntityLivingBase target, int phase, int tick) {
super(player, ability, target);
this.abilityPhase = phase;
this.tick = tick;
}
@Override
public int getAbilityPhase() {
return abilityPhase;
}
@Override
public int getTick() {
return tick;
}
@Override
public String getHookName() {
return EnumScriptType.ABILITY_TICK.function;
}
}
/**
* Fired when a player's ability hits an entity with damage.
* Canceling prevents the damage from being applied.