use of org.bukkit.entity.LivingEntity in project MagicPlugin by elBukkit.
the class EntityMageData method tick.
public void tick(Mage mage) {
List<MageTrigger> intervalTriggers = getTriggers(MageTriggerType.INTERVAL);
if (intervalTriggers == null)
return;
Entity entity = mage.getLivingEntity();
Creature creature = (entity instanceof Creature) ? (Creature) entity : null;
if (requiresTarget && (creature == null || creature.getTarget() == null))
return;
if (requiresWand != null && entity instanceof LivingEntity) {
LivingEntity li = (LivingEntity) entity;
ItemStack itemInHand = li.getEquipment().getItemInMainHand();
if (itemInHand == null || itemInHand.getType() != requiresWand.getType())
return;
}
for (MageTrigger trigger : intervalTriggers) {
trigger.execute(mage);
}
}
use of org.bukkit.entity.LivingEntity in project MagicPlugin by elBukkit.
the class PotionEffectAction method perform.
@Override
public SpellResult perform(CastContext context) {
Entity entity = context.getTargetEntity();
if (!(entity instanceof LivingEntity)) {
return SpellResult.NO_TARGET;
}
LivingEntity targetEntity = (LivingEntity) entity;
context.registerPotionEffects(targetEntity);
boolean effected = false;
if (addEffects != null && addEffects.size() > 0) {
effected = true;
CompatibilityUtils.applyPotionEffects(targetEntity, addEffects);
}
if (removeEffects != null) {
Collection<PotionEffect> currentEffects = targetEntity.getActivePotionEffects();
for (PotionEffect effect : currentEffects) {
PotionEffectType removeType = effect.getType();
if (removeEffects.contains(removeType) && effect.getDuration() < Integer.MAX_VALUE / 4) {
targetEntity.removePotionEffect(removeType);
effected = true;
}
}
}
return effected ? SpellResult.CAST : SpellResult.NO_TARGET;
}
use of org.bukkit.entity.LivingEntity in project MagicPlugin by elBukkit.
the class ProjectileAction method start.
@Override
public SpellResult start(CastContext context) {
MageController controller = context.getController();
Mage mage = context.getMage();
// Modify with wand power
// Turned some of this off for now
// int count = this.count * mage.getRadiusMultiplier();
// int speed = this.speed * damageMultiplier;
int size = (int) (mage.getRadiusMultiplier() * this.size);
double damageMultiplier = mage.getDamageMultiplier("projectile");
double damage = damageMultiplier * this.damage;
float radiusMultiplier = mage.getRadiusMultiplier();
float spread = this.spread;
if (radiusMultiplier > 1) {
spread = spread / radiusMultiplier;
}
Random random = context.getRandom();
Class<?> projectileType = NMSUtils.getBukkitClass("net.minecraft.server.Entity" + projectileTypeName);
if (!CompatibilityUtils.isValidProjectileClass(projectileType)) {
controller.getLogger().warning("Bad projectile class: " + projectileTypeName);
return SpellResult.FAIL;
}
// Prepare parameters
Location location = sourceLocation.getLocation(context);
Vector direction = location.getDirection();
if (startDistance > 0) {
location = location.clone().add(direction.clone().multiply(startDistance));
}
// Spawn projectiles
LivingEntity shootingEntity = context.getLivingEntity();
ProjectileSource source = null;
if (shootingEntity != null) {
source = shootingEntity;
}
for (int i = 0; i < count; i++) {
try {
// Spawn a new projectile
Projectile projectile = CompatibilityUtils.spawnProjectile(projectileType, location, direction, source, speed, spread, i > 0 ? spread : 0, random);
if (projectile == null) {
return SpellResult.FAIL;
}
if (shootingEntity != null) {
projectile.setShooter(shootingEntity);
}
if (projectile instanceof Fireball) {
Fireball fireball = (Fireball) projectile;
fireball.setIsIncendiary(useFire);
fireball.setYield(size);
}
if (projectile instanceof Arrow) {
Arrow arrow = (Arrow) projectile;
if (useFire) {
arrow.setFireTicks(300);
}
if (damage > 0) {
CompatibilityUtils.setDamage(projectile, damage);
}
if (tickIncrease > 0) {
CompatibilityUtils.decreaseLifespan(projectile, tickIncrease);
}
if (pickupStatus != null && !pickupStatus.isEmpty()) {
CompatibilityUtils.setPickupStatus(arrow, pickupStatus);
}
}
if (!breakBlocks) {
projectile.setMetadata("cancel_explosion", new FixedMetadataValue(controller.getPlugin(), true));
}
track(context, projectile);
} catch (Exception ex) {
ex.printStackTrace();
}
}
return checkTracking(context);
}
use of org.bukkit.entity.LivingEntity in project MagicPlugin by elBukkit.
the class RepairItemAction method perform.
@Override
public SpellResult perform(CastContext context) {
Entity entity = context.getTargetEntity();
if (entity instanceof LivingEntity && (armor || heldItem)) {
boolean repaired = false;
LivingEntity li = (LivingEntity) entity;
EntityEquipment equipment = li.getEquipment();
if (equipment == null) {
return SpellResult.NO_TARGET;
}
if (armor) {
ItemStack item = equipment.getHelmet();
repaired = repair(context, item) || repaired;
item = equipment.getChestplate();
repaired = repair(context, item) || repaired;
item = equipment.getLeggings();
repaired = repair(context, item) || repaired;
item = equipment.getBoots();
repaired = repair(context, item) || repaired;
}
if (heldItem) {
ItemStack item = equipment.getItemInMainHand();
repaired = repair(context, item) || repaired;
}
return repaired ? SpellResult.CAST : SpellResult.NO_TARGET;
}
if (entity == null || !(entity instanceof Item)) {
return SpellResult.NO_TARGET;
}
Item item = (Item) entity;
ItemStack itemStack = item.getItemStack();
return repair(context, itemStack) ? SpellResult.CAST : SpellResult.NO_TARGET;
}
use of org.bukkit.entity.LivingEntity in project MagicPlugin by elBukkit.
the class CustomProjectileAction method step.
@Override
public SpellResult step(CastContext context) {
long now = System.currentTimeMillis();
if (now < nextUpdate) {
return SpellResult.PENDING;
}
if (attachedDeadline > 0) {
Entity targetEntity = actionContext.getTargetEntity();
if (attachedOffset != null && targetEntity != null) {
Location targetLocation = targetEntity.getLocation();
targetLocation.add(attachedOffset);
actionContext.setTargetLocation(targetLocation);
if (effectLocation != null) {
effectLocation.updateFrom(targetLocation);
}
}
if (now > attachedDeadline) {
return finishAttach();
}
return SpellResult.PENDING;
}
if (now > deadline) {
return miss();
}
if (targetSelfDeadline > 0 && now > targetSelfDeadline && actionContext != null) {
targetSelfDeadline = 0;
actionContext.setTargetsCaster(true);
}
nextUpdate = now + interval;
// Check for initialization required
// TODO: Move this to start()?
Location projectileLocation = null;
if (velocity == null) {
projectileLocation = sourceLocation.getLocation(context).clone();
/* This feels confusing however...
* Looking straight down in Minecraft gives a pitch of 90
* While looking straight up is a pitch of -90
* We don't want to normalize these values as other functions need the non-normalize numbers.
* So if the projectile pitch value is found to be higher or lower than the min or max, it's set to the min or max respectively
*/
if (pitchMin < projectileLocation.getPitch()) {
projectileLocation.setPitch(pitchMin);
} else if (pitchMax > projectileLocation.getPitch()) {
projectileLocation.setPitch(pitchMax);
}
launchLocation = projectileLocation.clone();
velocity = projectileLocation.getDirection().clone().normalize();
if (spread > 0) {
Random random = context.getRandom();
velocity.setX(velocity.getX() + (random.nextDouble() * spread - spread / 2));
velocity.setY(velocity.getY() + (random.nextDouble() * spread - spread / 2));
velocity.setZ(velocity.getZ() + (random.nextDouble() * spread - spread / 2));
velocity.normalize();
}
if (startDistance != 0) {
projectileLocation.add(velocity.clone().multiply(startDistance));
}
if (reverseDirection) {
velocity = velocity.multiply(-1);
}
projectileLocation.setDirection(velocity);
actionContext.setTargetLocation(projectileLocation);
actionContext.setTargetEntity(null);
actionContext.setDirection(velocity);
// Start up projectile FX
startProjectileEffects(context, projectileEffectKey);
context.getMage().sendDebugMessage(ChatColor.BLUE + "Projectile launched from " + ChatColor.GRAY + projectileLocation.toVector() + ChatColor.BLUE, 7);
} else {
projectileLocation = actionContext.getTargetLocation();
if (effectLocation != null) {
effectLocation.updateFrom(projectileLocation);
effectLocation.setDirection(velocity);
}
}
// Check plan
if (plan != null && !plan.isEmpty()) {
PlanStep next = plan.peek();
if ((next.distance > 0 && distanceTravelled > next.distance) || (next.time > 0 && flightTime > next.time) || (next.returnBuffer > 0 && returnDistanceAway != null && returnDistanceAway < next.returnBuffer)) {
plan.remove();
if (next.parameters != null) {
modifyParameters(next.parameters);
}
if (next.effectsKey != null) {
startProjectileEffects(context, next.effectsKey);
}
context.getMage().sendDebugMessage("Changing flight plan at distance " + ((int) distanceTravelled) + " and time " + flightTime, 4);
if (resetTimeOnPathChange) {
flightTime = 0;
}
}
}
if (updateLaunchLocation) {
launchLocation = context.getCastLocation().clone();
}
// Advance position
// We default to 50 ms travel time (one tick) for the first iteration.
long delta = lastUpdate > 0 ? now - lastUpdate : 50;
lastUpdate = now;
flightTime += delta;
// Apply gravity, drag or other velocity modifiers
Vector targetVelocity = null;
if (trackEntity) {
Entity targetEntity = context.getTargetEntity();
if (targetEntity != null && targetEntity.isValid() && context.canTarget(targetEntity)) {
Location targetLocation = targetEntity instanceof LivingEntity ? ((LivingEntity) targetEntity).getEyeLocation() : targetEntity.getLocation();
targetVelocity = targetLocation.toVector().subtract(projectileLocation.toVector()).normalize();
}
} else if (trackCursorRange > 0) {
/* We need to first find out where the player is looking and multiply it by how far the player wants the whip to extend
* Finally after all that, we adjust the velocity of the projectile to go towards the cursor point
*/
Vector playerCursor = context.getMage().getDirection().clone().normalize();
Vector targetPoint = playerCursor.multiply(trackCursorRange);
Vector worldPoint = targetPoint.add(context.getMage().getEyeLocation().clone().toVector());
Vector projectileOffset = worldPoint.subtract(projectileLocation.clone().toVector());
targetVelocity = projectileOffset.normalize();
} else if (reorient) {
targetVelocity = context.getMage().getDirection().clone().normalize();
} else {
if (gravity > 0) {
// Reduce / change speed based on gravity
velocity.normalize().multiply(speed);
velocity.setY(velocity.getY() - gravity * delta / 50);
speed = velocity.length();
velocity.normalize();
}
if (drag > 0) {
speed -= drag * delta / 50;
if (speed <= 0) {
return miss();
}
}
}
if (targetVelocity != null) {
if (trackSpeed > 0) {
double steerDistanceSquared = trackSpeed * trackSpeed;
double distanceSquared = targetVelocity.distanceSquared(velocity);
if (distanceSquared <= steerDistanceSquared) {
velocity = targetVelocity;
} else {
Vector targetDirection = targetVelocity.subtract(velocity).normalize().multiply(steerDistanceSquared);
velocity.add(targetDirection);
}
} else {
velocity = targetVelocity;
}
launchLocation.setDirection(velocity);
}
if (velocityTransform != null) {
targetVelocity = velocityTransform.get(launchLocation, (double) flightTime / 1000);
// with targeting and range-checking
if (targetVelocity != null) {
speed = targetVelocity.length();
if (speed > 0) {
targetVelocity.normalize();
} else {
targetVelocity.setX(1);
}
velocity = targetVelocity;
}
}
if (returnToCaster) {
Vector targetLocation = context.getMage().getEyeLocation().toVector();
if (returnOffset != null) {
targetLocation.add(returnOffset);
}
if (returnRelativeOffset != null) {
Vector relativeOffset = VectorUtils.rotateVector(returnRelativeOffset, context.getMage().getEyeLocation());
targetLocation.add(relativeOffset);
}
Vector projectileOffset = targetLocation.clone().subtract(projectileLocation.toVector());
returnDistanceAway = projectileOffset.length();
velocity = projectileOffset.normalize();
}
if (projectileFollowPlayer) {
Vector currentLocation = context.getMage().getLocation().toVector();
if (previousLocation != null) {
Vector offset = currentLocation.clone().subtract(previousLocation);
previousLocation = currentLocation;
velocity = velocity.add(offset);
} else {
previousLocation = currentLocation;
}
}
projectileLocation.setDirection(velocity);
// Advance targeting to find Entity or Block
distanceTravelledThisTick = speed * delta / 1000;
if (range > 0) {
distanceTravelledThisTick = Math.min(distanceTravelledThisTick, range - distanceTravelled);
}
context.addWork((int) Math.ceil(distanceTravelledThisTick));
Location targetLocation;
Targeting.TargetingResult targetingResult = Targeting.TargetingResult.MISS;
Target target = null;
if (!ignoreTargeting) {
targeting.start(projectileLocation);
target = targeting.target(actionContext, distanceTravelledThisTick);
targetingResult = targeting.getResult();
targetLocation = target.getLocation();
boolean keepGoing = distanceTravelled < minRange;
Location tempLocation = projectileLocation.clone();
int checkIterations = 0;
while (keepGoing) {
// TODO if all of these distance() calls are necessary, they should be optimized to distanceSquared()
if (targetingResult == Targeting.TargetingResult.MISS) {
keepGoing = false;
} else if (targetingResult != null && targetLocation.distance(projectileLocation) + distanceTravelled >= minRange) {
keepGoing = false;
} else if (targetLocation.distance(projectileLocation) + distanceTravelled >= minEntityRange && targetingResult == Targeting.TargetingResult.ENTITY) {
keepGoing = false;
} else if (targetLocation.distance(projectileLocation) + distanceTravelled >= minBlockRange && targetingResult == Targeting.TargetingResult.BLOCK) {
keepGoing = false;
} else if (targetLocation.distance(projectileLocation) >= distanceTravelledThisTick) {
keepGoing = false;
} else if (checkIterations > 1000) {
keepGoing = false;
} else {
if (tempLocation.distance(projectileLocation) < targetLocation.distance(projectileLocation)) {
tempLocation.add(velocity.clone().multiply(targetLocation.distance(projectileLocation) + 0.1));
} else {
tempLocation.add(velocity.clone().multiply(0.2));
}
actionContext.setTargetLocation(tempLocation);
actionContext.setTargetEntity(null);
actionContext.setDirection(velocity);
// TODO: This whole procedure, particularly retargeting, is going to be very costly
// This is hopefully an easier way
targeting.start(tempLocation);
target = targeting.target(actionContext, distanceTravelledThisTick - tempLocation.distance(projectileLocation));
targetingResult = targeting.getResult();
targetLocation = target.getLocation();
checkIterations++;
}
}
}
if (targetingResult == Targeting.TargetingResult.MISS) {
if (hasBlockMissEffects && target != null) {
actionContext.setTargetLocation(target.getLocation());
actionContext.playEffects("blockmiss");
}
targetLocation = projectileLocation.clone().add(velocity.clone().multiply(distanceTravelledThisTick));
context.getMage().sendDebugMessage(ChatColor.DARK_BLUE + "Projectile miss: " + ChatColor.DARK_PURPLE + " at " + targetLocation.getBlock().getType() + " : " + targetLocation.toVector() + " from range of " + distanceTravelledThisTick + " over time " + delta, 14);
} else {
if (hasPreHitEffects) {
actionContext.playEffects("prehit");
}
targetLocation = target.getLocation();
// Debugging
if (targetLocation == null) {
targetLocation = projectileLocation;
context.getLogger().warning("Targeting hit, with no target location: " + targetingResult + " with " + targeting.getTargetType() + " from " + context.getSpell().getName());
}
context.getMage().sendDebugMessage(ChatColor.BLUE + "Projectile hit: " + ChatColor.LIGHT_PURPLE + targetingResult.name().toLowerCase() + ChatColor.BLUE + " at " + ChatColor.GOLD + targetLocation.getBlock().getType() + ChatColor.BLUE + " from " + ChatColor.GRAY + projectileLocation.getBlock() + ChatColor.BLUE + " to " + ChatColor.GRAY + targetLocation.toVector() + ChatColor.BLUE + " from range of " + ChatColor.GOLD + distanceTravelledThisTick + ChatColor.BLUE + " over time " + ChatColor.DARK_PURPLE + delta, 8);
distanceTravelledThisTick = targetLocation.distance(projectileLocation);
}
distanceTravelled += distanceTravelledThisTick;
effectDistanceTravelled += distanceTravelledThisTick;
// Max Height check
int y = targetLocation.getBlockY();
boolean maxHeight = y >= targetLocation.getWorld().getMaxHeight();
boolean minHeight = y <= 0;
if (maxHeight) {
targetLocation.setY(targetLocation.getWorld().getMaxHeight());
} else if (minHeight) {
targetLocation.setY(0);
}
if (hasTickEffects && effectDistanceTravelled > tickSize) {
// Sane limit here
Vector speedVector = velocity.clone().multiply(tickSize);
for (int i = 0; i < 256; i++) {
actionContext.setTargetLocation(projectileLocation);
actionContext.playEffects(tickEffectKey);
projectileLocation.add(speedVector);
effectDistanceTravelled -= tickSize;
if (effectDistanceTravelled < tickSize)
break;
}
}
actionContext.setTargetLocation(targetLocation);
if (target != null) {
actionContext.setTargetEntity(target.getEntity());
}
if (hasStepEffects) {
actionContext.playEffects("step");
}
if (maxHeight || minHeight) {
return miss();
}
if (range > 0 && distanceTravelled >= range) {
return miss();
}
Block block = targetLocation.getBlock();
if (!block.getChunk().isLoaded()) {
return miss();
}
if (distanceTravelled < minRange && targetingResult != null) {
// TODO : Should this be < ?
if (distanceTravelled >= minBlockRange && targetingResult == Targeting.TargetingResult.BLOCK) {
return miss();
}
if (distanceTravelled >= minEntityRange && targetingResult == Targeting.TargetingResult.ENTITY) {
return miss();
}
} else if (targetingResult == Targeting.TargetingResult.BLOCK) {
return hitBlock(block);
} else if (targetingResult == Targeting.TargetingResult.ENTITY) {
return hitEntity(target);
}
if (hasTickActions) {
return startActions("tick");
}
return SpellResult.PENDING;
}
Aggregations