diff --git a/build.properties b/build.properties index 3330ca6..7e9ce39 100644 --- a/build.properties +++ b/build.properties @@ -1,5 +1,5 @@ mod_name = AcademyMonster -mod_ver = 1.0.0pr3 +mod_ver = 1.0.0pr4 mod_group = cn.paindar mc_ver = 1.7.10 forge_ver = 10.13.4.1517-1.7.10 @@ -9,6 +9,6 @@ ccl_ver = 1.1.3.136 ccc_ver = 1.0.6.43 lambdalib_ver = 1.2.3 -academycraft_ver = 1.0.6 +academycraft_ver = 1.0.4 diff --git a/src/main/java/cn/paindar/academymonster/ability/AIArcGen.java b/src/main/java/cn/paindar/academymonster/ability/AIArcGen.java index 0b7a3fd..6b03bcb 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIArcGen.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIArcGen.java @@ -34,7 +34,7 @@ public class AIArcGen extends BaseSkill private float slowdown; public AIArcGen(EntityLivingBase speller, float exp) { - super(speller, (int)lerpf(40,20,exp), exp,ArcGen.getFullName()); + super(speller, (int)lerpf(40,20,exp), exp,"electromaster.arc_gen"); damage=lerpf(5,9,exp); range=lerpf(6,15,exp); prob=lerpf(0,0.6f,exp); diff --git a/src/main/java/cn/paindar/academymonster/ability/AIBodyIntensify.java b/src/main/java/cn/paindar/academymonster/ability/AIBodyIntensify.java index 928d72f..baa3e88 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIBodyIntensify.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIBodyIntensify.java @@ -15,7 +15,7 @@ public class AIBodyIntensify extends BaseSkill { public AIBodyIntensify(EntityLivingBase speller, float exp) { - super(speller, (int)lerpf(300, 100,exp), exp,BodyIntensify.getFullName()); + super(speller, (int)lerpf(300, 100,exp), exp,"electromaster.body_intensify"); } @@ -25,7 +25,7 @@ private double getProbability() } private int getBuffTime() { - return (int)lerpf(3f,10f, getSkillExp()); + return (int)lerpf(30f,100f, getSkillExp()); } private int getBuffLevel() { diff --git a/src/main/java/cn/paindar/academymonster/ability/AIDirectedShock.java b/src/main/java/cn/paindar/academymonster/ability/AIDirectedShock.java index 42d0682..eff2152 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIDirectedShock.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIDirectedShock.java @@ -25,7 +25,7 @@ public class AIDirectedShock extends BaseSkill private float damage; public AIDirectedShock(EntityLivingBase speller, float exp) { - super(speller, (int)lerpf(60, 20, exp), exp,DirectedShock.getFullName()); + super(speller, (int)lerpf(60, 20, exp), exp,"vecmanip.dir_shock"); damage=lerpf(7, 15,exp); } diff --git a/src/main/java/cn/paindar/academymonster/ability/AIElectronBomb.java b/src/main/java/cn/paindar/academymonster/ability/AIElectronBomb.java index a483d51..0b22ad1 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIElectronBomb.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIElectronBomb.java @@ -27,7 +27,7 @@ public class AIElectronBomb extends BaseSkill private float damage; public AIElectronBomb(EntityLivingBase speller,float exp) { - super(speller,(int)lerpf(40,10, exp), exp,ElectronBomb.getFullName()); + super(speller,(int)lerpf(40,10, exp), exp,"meltdowner.electron_bomb"); damage=lerpf(6, 12, exp); maxDistance=lerpf(7,15,exp); } diff --git a/src/main/java/cn/paindar/academymonster/ability/AIElectronMissile.java b/src/main/java/cn/paindar/academymonster/ability/AIElectronMissile.java new file mode 100644 index 0000000..71ae069 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/ability/AIElectronMissile.java @@ -0,0 +1,87 @@ +package cn.paindar.academymonster.ability; + +import cn.lambdalib.util.generic.VecUtils; +import cn.lambdalib.util.helper.Motion3D; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.entity.EntityMdBallNative; +import cn.paindar.academymonster.network.NetworkManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.Vec3; + +import java.util.ArrayList; +import java.util.List; + +import static cn.lambdalib.util.generic.MathUtils.lerpf; + +/** + * Created by Paindar on 2017/3/12. + */ +public class AIElectronMissile extends BaseSkill +{ + private List ballList=new ArrayList<>(); + private int freq; + private int time; + private int maxTick; + private float range; + private float damage; + public AIElectronMissile(EntityLivingBase speller, float exp) + { + super(speller, (int)lerpf(800,400,exp), exp, "meltdowner.electron_missile"); + freq=(int)lerpf(20,10,exp); + maxTick=(int)lerpf(100,200,exp); + range=(int)lerpf(8,12,exp); + damage=lerpf(5,12,exp); + } + + @Override + public void spell() + { + if(!available()) + return; + isChanting=true; + time=0; + } + + @Override + public void onTick() + { + if(!isChanting) + return; + + time++; + if(speller.isDead || time>=maxTick) + { + isChanting=false; + super.spell(); + for(EntityMdBallNative ball:ballList) + { + ball.setDead(); + } + } + if(time%freq==0) + { + EntityMdBallNative ball=new EntityMdBallNative(speller,2333333); + ballList.add(ball); + speller.worldObj.spawnEntityInWorld(ball); + } + List list=WorldUtils.getEntities(speller,range,EntitySelectors.exclude(speller).and(EntitySelectors.living())); + if(!list.isEmpty() && !ballList.isEmpty()) + { + Vec3 str= VecUtils.vec(ballList.get(0).posX, ballList.get(0).posY, ballList.get(0).posZ); + Vec3 dst=new Motion3D(list.get(0),5,true).getPosVec(); + attack((EntityLivingBase) list.get(0), damage); + list= WorldUtils.getEntities(speller, 25, EntitySelectors.player()); + for(Entity e:list) + { + NetworkManager.sendMdRayEffectTo(str,dst,(EntityPlayerMP)e); + } + ballList.get(0).setDead(); + ballList.remove(0); + } + } + + public float getMaxDistance(){return range;} +} diff --git a/src/main/java/cn/paindar/academymonster/ability/AIFlashing.java b/src/main/java/cn/paindar/academymonster/ability/AIFlashing.java new file mode 100644 index 0000000..ef6c475 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/ability/AIFlashing.java @@ -0,0 +1,75 @@ +package cn.paindar.academymonster.ability; + +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.network.NetworkManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; + +import java.util.List; + +import static cn.lambdalib.util.generic.MathUtils.lerpf; + +/** + * Created by voidcl on 2017/3/10. + */ +public class AIFlashing extends BaseSkill{ + private float maxDistance; + private int time; + private int maxtime; + private int ilCD=0; + public AIFlashing(EntityLivingBase speller, float exp) { + super(speller,(int)lerpf(200, 100, exp), exp,"teleporter.flashing"); + time=0; + maxtime=60; + maxDistance=lerpf(3,10, getSkillExp()); + } + + public float getMaxDistance(){return maxDistance;} + + @Override + public boolean available() + { + return isChanting || !isSkillInCooldown(); + } + + public void spell(double x, double y, double z) + { + if((!isChanting && isSkillInCooldown())||ilCD>0) + return; + if(speller.isRiding()) + speller.mountEntity(null); + speller.setPositionAndUpdate(x,y,z); + if(!isChanting){ + isChanting=true; + time=0; + } + speller.fallDistance = 0; + ilCD=5; + if(!speller.worldObj.isRemote) + { + List list= WorldUtils.getEntities(speller, 25, EntitySelectors.player()); + for(Entity e:list) + { + NetworkManager.sendSoundTo("tp.tp",speller,.5f,(EntityPlayerMP)e); + } + } + } + @Override + protected void onTick() + { + if(!isChanting) + { + return; + } + if(time>=maxtime) + { + isChanting=false; + super.spell(); + return; + } + if(ilCD>0) ilCD--; + time ++; + } +} diff --git a/src/main/java/cn/paindar/academymonster/ability/AIFleshRipping.java b/src/main/java/cn/paindar/academymonster/ability/AIFleshRipping.java index 6012747..adba028 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIFleshRipping.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIFleshRipping.java @@ -23,7 +23,7 @@ public class AIFleshRipping extends BaseSkill private float damage; public AIFleshRipping(EntityLivingBase speller, float skillExp) { - super(speller, (int)lerpf(90, 40, skillExp), skillExp,FleshRipping.getFullName()); + super(speller, (int)lerpf(90, 40, skillExp), skillExp,"teleporter.flesh_ripping"); maxDistance=lerpf(2, 5, skillExp); damage=lerpf(5, 12, skillExp); } diff --git a/src/main/java/cn/paindar/academymonster/ability/AILightShield.java b/src/main/java/cn/paindar/academymonster/ability/AILightShield.java index d938432..ba342d5 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AILightShield.java +++ b/src/main/java/cn/paindar/academymonster/ability/AILightShield.java @@ -1,11 +1,9 @@ package cn.paindar.academymonster.ability; -import cn.academy.vanilla.meltdowner.skill.LightShield; -import cn.lambdalib.util.entityx.EntityAdvanced; + import cn.lambdalib.util.generic.MathUtils; import cn.lambdalib.util.mc.EntitySelectors; import cn.lambdalib.util.mc.WorldUtils; -import cn.paindar.academymonster.core.AcademyMonster; import cn.paindar.academymonster.entity.EntityLightShield; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.entity.Entity; @@ -15,7 +13,6 @@ import net.minecraftforge.event.entity.living.LivingHurtEvent; import java.util.List; -import java.util.function.Predicate; import static cn.lambdalib.util.generic.MathUtils.lerpf; @@ -32,7 +29,7 @@ public class AILightShield extends BaseSkill public AILightShield(EntityLivingBase speller, float exp) { - super(speller, (int)lerpf(100,40,exp), exp, LightShield.getFullName()); + super(speller, (int)lerpf(100,40,exp), exp, "meltdowner.light_shield"); maxTime=(int)lerpf(100,300,exp); touchDamage=lerpf(2, 6, exp); absorbDamage=lerpf(150,300,exp); @@ -53,6 +50,7 @@ public void spell() return; isChanting=true; shield = new EntityLightShield(speller); + shield.setPosition(speller.posX,speller.posY,speller.posZ); speller.worldObj.spawnEntityInWorld(shield); time=0; } diff --git a/src/main/java/cn/paindar/academymonster/ability/AIMeltdowner.java b/src/main/java/cn/paindar/academymonster/ability/AIMeltdowner.java new file mode 100644 index 0000000..9a8b8e4 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/ability/AIMeltdowner.java @@ -0,0 +1,148 @@ +package cn.paindar.academymonster.ability; + +import cn.academy.core.event.BlockDestroyEvent; +import cn.lambdalib.util.generic.MathUtils; +import cn.lambdalib.util.generic.RandUtils; +import cn.lambdalib.util.generic.VecUtils; +import cn.lambdalib.util.helper.Motion3D; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.config.AMConfig; +import cn.paindar.academymonster.network.NetworkManager; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import static cn.lambdalib.util.generic.MathUtils.lerpf; +import static cn.lambdalib.util.generic.VecUtils.*; + +/** + * Created by Paindar on 2017/3/12. + */ +public class AIMeltdowner extends BaseSkill +{ + private static final double STEP = 0.5; + private float damage; + private float range =2; + private int maxIncrement = 16; + public AIMeltdowner(EntityLivingBase speller,float exp) + { + super(speller, (int)lerpf(800, 600, exp), exp,"meltdowner.meltdowner"); + maxIncrement=(int)lerpf(12,25,exp); + damage=lerpf(40, 150, exp); + } + + + public float getMaxDistance(){return maxIncrement;} + + private void destroyBlock(World world, int x, int y, int z) { + Block block = world.getBlock(x, y, z); + float hardness = block.getBlockHardness(world, x, y, z); + if(hardness < 0) + return ; + if(!MinecraftForge.EVENT_BUS.post(new BlockDestroyEvent(world, x, y, z))) + { + if(block.getMaterial() != Material.air) { + block.dropBlockAsItemWithChance(world, x, y, z, + world.getBlockMetadata(x, y, z), 0.05f, 0); + } + world.setBlockToAir(x, y, z); + } + } + + @Override + public void spell() + { + if(isSkillInCooldown()) + return; + super.spell(); + Motion3D motion=new Motion3D(speller, true).move(0.1).normalize(); + float yaw = -MathUtils.PI_F * 0.5f - motion.getRotationYawRadians(), + pitch = motion.getRotationPitchRadians(); + Set processed = new HashSet<>(); + World world=speller.worldObj; + Vec3 start = motion.getPosVec(); + Vec3 slope = motion.getMotionVec(); + + Vec3 vp0 = VecUtils.vec(0, 0, 1); + vp0.rotateAroundZ(pitch); + vp0.rotateAroundY(yaw); + + Vec3 vp1 = VecUtils.vec(0, 1, 0); + vp1.rotateAroundZ(pitch); + vp1.rotateAroundY(yaw); + + + /* Apply Entity Damage */ + { + Vec3 v0 = add(start, add(multiply(vp0, -range), multiply(vp1, -range))), + v1 = add(start, add(multiply(vp0, range), multiply(vp1, -range))), + v2 = add(start, add(multiply(vp0, range), multiply(vp1, range))), + v3 = add(start, add(multiply(vp0, -range), multiply(vp1, range))), + v4 = add(v0, multiply(slope, maxIncrement)), + v5 = add(v1, multiply(slope, maxIncrement)), + v6 = add(v2, multiply(slope, maxIncrement)), + v7 = add(v3, multiply(slope, maxIncrement)); + AxisAlignedBB aabb = WorldUtils.minimumBounds(v0, v1, v2, v3, v4, v5, v6, v7); + + Predicate areaSelector = target -> { + Vec3 dv = subtract(vec(target.posX, target.posY, target.posZ), start); + Vec3 proj = dv.crossProduct(slope); + return proj.lengthVector() < range * 1.2; + }; + List targets = WorldUtils.getEntities(speller.worldObj, aabb, EntitySelectors.everything().and(areaSelector).and(EntitySelectors.exclude(speller))); + + for (Entity e : targets) + { + if (e instanceof EntityLivingBase) + { + attack((EntityLivingBase) e, damage); + } else + { + e.setDead(); + } + } + } + + if(AMConfig.getBoolean("am.skill.meltdowner.destroyBlock",true)) + { + for(int i=1;i rr * rr) + continue; + Vec3 pos = VecUtils.add(str, + VecUtils.add( + VecUtils.multiply(vp0, s), + VecUtils.multiply(vp1, t))); + destroyBlock(world,(int) pos.xCoord,(int) pos.yCoord,(int) pos.zCoord); + } + } + } + } + if(!speller.worldObj.isRemote) + { + List list=WorldUtils.getEntities(speller, 40, EntitySelectors.player()); + for(Entity e:list) + { + NetworkManager.sendMeltdownerEffectTo(speller,maxIncrement,(EntityPlayerMP)e); + } + } + } +} diff --git a/src/main/java/cn/paindar/academymonster/ability/AIPenetrateTeleport.java b/src/main/java/cn/paindar/academymonster/ability/AIPenetrateTeleport.java index 8bf42a4..091d001 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIPenetrateTeleport.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIPenetrateTeleport.java @@ -19,7 +19,7 @@ public class AIPenetrateTeleport extends BaseSkill { private float maxDistance; public AIPenetrateTeleport(EntityLivingBase speller,float exp) { - super(speller,(int)lerpf(200, 100, exp), exp,PenetrateTeleport.getFullName()); + super(speller,(int)lerpf(200, 100, exp), exp,"teleporter.penetrate_teleport"); maxDistance=lerpf(3,10, getSkillExp()); } diff --git a/src/main/java/cn/paindar/academymonster/ability/AIRailgun.java b/src/main/java/cn/paindar/academymonster/ability/AIRailgun.java index 02b4dca..932858c 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIRailgun.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIRailgun.java @@ -47,7 +47,7 @@ public class AIRailgun extends BaseSkill private EntityCoinThrowingNative coin; public AIRailgun(EntityLivingBase speller, float exp) { - super(speller, (int)lerpf(800, 600, exp), exp,Railgun.getFullName()); + super(speller, (int)lerpf(800, 600, exp), exp,"electromaster.railgun"); maxIncrement=(int)lerpf(12,25,exp); damage=lerpf(20, 50, exp); } diff --git a/src/main/java/cn/paindar/academymonster/ability/AIScatterBomb.java b/src/main/java/cn/paindar/academymonster/ability/AIScatterBomb.java new file mode 100644 index 0000000..1133308 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/ability/AIScatterBomb.java @@ -0,0 +1,111 @@ +package cn.paindar.academymonster.ability; + +import cn.lambdalib.util.generic.RandUtils; +import cn.lambdalib.util.generic.VecUtils; +import cn.lambdalib.util.helper.Motion3D; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.Raytrace; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.entity.EntityMdBallNative; +import cn.paindar.academymonster.network.NetworkManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +import java.util.ArrayList; +import java.util.List; + +import static cn.lambdalib.util.generic.MathUtils.lerpf; + +/** + * Created by Paindar on 2017/3/12. + */ +public class AIScatterBomb extends BaseSkill +{ + private List ballList=new ArrayList<>(); + private float damage; + private float range; + private float time; + private final float maxTime=240; + public AIScatterBomb(EntityLivingBase speller, float exp) + { + super(speller, (int)lerpf(160,100,exp), exp, "meltdowner.scatter_bomb"); + damage=lerpf(3,9,exp); + range=lerpf(5,11,exp); + } + + @Override + public void spell() + { + if(isSkillInCooldown()) + return; + if(isChanting) + { + List trgList= WorldUtils.getEntities(speller,range, EntitySelectors.living().and(EntitySelectors.exclude(speller))); + Vec3 dst=new Motion3D(speller, 5, true).move(range).getPosVec(); + for(EntityMdBallNative ball:ballList) + { + Vec3 str= VecUtils.vec(ball.posX, ball.posY, ball.posZ); + if(!trgList.isEmpty()) + { + dst=new Motion3D(trgList.get(RandUtils.nextInt(trgList.size())),5,true).getPosVec(); + } + MovingObjectPosition trace = Raytrace.perform(speller.worldObj,str,dst + , EntitySelectors.exclude(speller).and(EntitySelectors.living())); + if (trace != null && trace.entityHit != null) + { + attack((EntityLivingBase) trace.entityHit, damage); + List list= WorldUtils.getEntities(speller, 25, EntitySelectors.player()); + for(Entity e:list) + { + NetworkManager.sendMdRayEffectTo(str,dst,(EntityPlayerMP)e); + } + } + ball.setDead(); + } + ballList.clear(); + isChanting=false; + super.spell(); + } + else + { + isChanting=true; + time=0; + + } + } + + @Override + public void onTick() + { + if(!isChanting) + return; + + time++; + if(speller.isDead) + { + isChanting=false; + for(EntityMdBallNative ball:ballList) + { + ball.setDead(); + super.spell(); + } + } + if(time>20&&time%10==0 && time<=100) + { + EntityMdBallNative ball=new EntityMdBallNative(speller,2333333); + ballList.add(ball); + speller.worldObj.spawnEntityInWorld(ball); + } + else if(time>=maxTime) + { + spell(); + } + } + + public int getBallSize(){return ballList.size();} + + public float getMaxDistance(){return range;} +} diff --git a/src/main/java/cn/paindar/academymonster/ability/AIThunderBolt.java b/src/main/java/cn/paindar/academymonster/ability/AIThunderBolt.java new file mode 100644 index 0000000..8be41de --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/ability/AIThunderBolt.java @@ -0,0 +1,118 @@ +package cn.paindar.academymonster.ability; + +import cn.academy.core.client.sound.ACSounds; +import cn.academy.vanilla.electromaster.client.effect.ArcPatterns; +import cn.academy.vanilla.electromaster.entity.EntityArc; +import cn.lambdalib.util.entityx.handlers.Life; +import cn.lambdalib.util.generic.RandUtils; +import cn.lambdalib.util.helper.Motion3D; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.Raytrace; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.entity.EntityArcNative; +import cn.paindar.academymonster.network.NetworkManager; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +import java.util.List; +import java.util.function.Predicate; + +import static cn.lambdalib.util.generic.MathUtils.lerpf; + +/** + * Created by Paindar on 2017/3/7. + */ +public class AIThunderBolt extends BaseSkill +{ + private float aoeDamage; + private float damage; + private static float range=20f; + private static float aoeRange=7f; + + public AIThunderBolt(EntityLivingBase speller, float exp) + { + super(speller, (int)lerpf(200,100,exp), exp, "electromaster.thunder_bolt"); + aoeDamage = lerpf(9.6f, 17.4f, exp); + damage = lerpf(16f, 29f, exp); + } + + public void spell() + { + MovingObjectPosition result = Raytrace.traceLiving(speller, range); + Vec3 end; + if(result == null) { + end = new Motion3D(speller).move(range).getPosVec(); + } else { + end = result.hitVec; + if(result.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) { + end.yCoord += result.entityHit.getEyeHeight(); + } + } + + boolean hitEntity = !(result == null || result.entityHit == null); + Predicate exclusion= (hitEntity)? EntitySelectors.exclude(speller) : EntitySelectors.exclude(speller, result.entityHit); + EntityLivingBase target = (hitEntity)? (EntityLivingBase)result.entityHit : null; + List aoes = WorldUtils.getEntities( + speller.worldObj, end.xCoord, end.yCoord, end.zCoord, + aoeRange, EntitySelectors.living().and(exclusion)); + + + if(target != null) + { + attack(target, damage); + if(getSkillExp() > 0.2 && RandUtils.ranged(0, 1) < 0.8 ) { + target.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 40, 3)); + } + } + + for(Entity e:aoes) + { + attack((EntityLivingBase) e, aoeDamage); + + if (getSkillExp() > 0.2 && RandUtils.ranged(0, 1) < 0.8) + { + ((EntityLivingBase)e).addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 20, 3)); + } + } + List list= WorldUtils.getEntities(speller, 40, EntitySelectors.player()); + for(Entity e:list) + { + NetworkManager.sendThunderBoltTo(speller,target,aoes,(EntityPlayerMP)e); + } + + super.spell(); + } + + public float getMaxDistance(){return range;} + + @SideOnly(Side.CLIENT) + public static void spawnEffect(EntityLivingBase ori,EntityLivingBase target,List aoes) + { + for(int i= 0 ;i<2;i++) + { + EntityArcNative mainArc = new EntityArcNative(ori, ArcPatterns.strongArc); + mainArc.length = range; + ori.worldObj.spawnEntityInWorld(mainArc); + mainArc.addMotionHandler(new Life(20)); + } + + for(Entity e:aoes) + { + EntityArcNative aoeArc = new EntityArcNative(ori, ArcPatterns.aoeArc); + aoeArc.lengthFixed = false; + aoeArc.setFromTo(target.posX, target.posY,target.posZ, + e.posX, e.posY + e.getEyeHeight(), e.posZ); + aoeArc.addMotionHandler(new Life(RandUtils.rangei(15, 25))); + ori.worldObj.spawnEntityInWorld(aoeArc); + } + + ACSounds.playClient(ori, "em.arc_strong", 0.6f); + } +} diff --git a/src/main/java/cn/paindar/academymonster/ability/AIThunderClap.java b/src/main/java/cn/paindar/academymonster/ability/AIThunderClap.java index 2c55fbc..5f173db 100644 --- a/src/main/java/cn/paindar/academymonster/ability/AIThunderClap.java +++ b/src/main/java/cn/paindar/academymonster/ability/AIThunderClap.java @@ -21,7 +21,7 @@ public class AIThunderClap extends BaseSkill private float distance=15; public AIThunderClap(EntityLivingBase speller, float exp) { - super(speller,(int) lerpf(600,300,exp), exp, ThunderClap.getFullName()); + super(speller,(int) lerpf(600,300,exp), exp,"electromaster.thunder_clap"); damage=lerpf(18,120,exp); range=lerpf(10,25,exp); } diff --git a/src/main/java/cn/paindar/academymonster/ability/AIVecReflect.java b/src/main/java/cn/paindar/academymonster/ability/AIVecReflect.java new file mode 100644 index 0000000..c5014be --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/ability/AIVecReflect.java @@ -0,0 +1,203 @@ +package cn.paindar.academymonster.ability; + +import cn.academy.ability.api.event.ReflectEvent; +import cn.academy.vanilla.vecmanip.skill.EntityAffection; +import cn.lambdalib.util.generic.VecUtils; +import cn.lambdalib.util.helper.Motion3D; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.Raytrace; +import cn.lambdalib.util.mc.RichEntity; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.core.AcademyMonster; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.projectile.EntityFireball; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.entity.projectile.EntitySmallFireball; +import net.minecraft.entity.projectile.EntityThrowable; +import net.minecraft.util.DamageSource; +import net.minecraft.util.Vec3; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingHurtEvent; + +import java.util.List; + +import static cn.lambdalib.util.generic.MathUtils.lerpf; + +/** + * Created by Paindar on 2017/3/11. + */ +public class AIVecReflect extends BaseSkill +{ + private int time=0; + private int maxTime; + private float reflectRate; + public AIVecReflect(EntityLivingBase speller, float exp) + { + super(speller, (int)lerpf(400,300,exp), exp, "vecmanip.vec_reflection"); + maxTime=(int)lerpf(60,120,exp); + reflectRate=lerpf(0.3f,2f,exp); + MinecraftForge.EVENT_BUS.register(this); + } + @Override + public void spell() + { + throw new RuntimeException(); + } + + @Override + public void onTick() + { + if (time == 0) + { + if(isChanting) + { + isChanting = false; + super.spell(); + } + return; + } + time--; + if(speller==null) + return; + // + List entities = WorldUtils.getEntities(speller, 5, (Entity entity) -> (!EntityAffection.isMarked(entity))); + for (Entity entity : entities) + { + + if (entity instanceof EntityFireball) + { + createNewFireball((EntityFireball) entity); + } + else if(!(entity instanceof EntityLivingBase)) + { + reflect(entity, speller); + + EntityAffection.mark(entity); + } + + + } + } + + @SubscribeEvent + public void onReflect(ReflectEvent evt) + { + if (evt.target.equals(speller)&&isChanting) { + evt.setCanceled(true); + + Vec3 dpos = VecUtils.subtract(new RichEntity(evt.player).headPosition(), new RichEntity(speller).headPosition()); + } + } + + /** + * @param passby If passby=true, and this isn't a complete absorb, the action will not perform. Else it will. + * @return (Whether action had been really performed, processed damage) + */ + private float handleAttack(DamageSource dmgSource, float dmg,Boolean passby) + { + + float returnRatio = reflectRate; + if (!passby) { // Perform the action. + Entity sourceEntity = dmgSource.getSourceOfDamage(); + + if (sourceEntity != null && sourceEntity != speller) { + if(sourceEntity instanceof EntityLivingBase) + attack((EntityLivingBase) sourceEntity, returnRatio*dmg); + else + { + reflect(sourceEntity, speller); + EntityAffection.mark(sourceEntity); + } + } + return Math.max(0,dmg*(1-returnRatio)); + } else { + return Math.max(0,dmg*(1-returnRatio)); + } + } + + @SubscribeEvent + public void onLivingAttack(LivingAttackEvent evt) + { + if (evt.entityLiving.equals(speller)&&isChanting) { + + if ( handleAttack(evt.source, evt.ammount, true)<=0) { + evt.setCanceled(true); + } + } +} + @SubscribeEvent + public void onLivingHurt(LivingHurtEvent evt) + { + if(isSkillInCooldown()&&!isChanting) + return; + if(!isChanting) + { + isChanting = true; + time=maxTime; + } + if (evt.entityLiving.equals(speller)) + { + evt.ammount = handleAttack(evt.source, evt.ammount, false); + } +} + + private static void reflect(Entity entity,EntityLivingBase player) + { +// Vec3 lookPos = Vec3.createVectorHelper(player.posX-entity.posX,player.posY-entity.posY,player.posZ-entity.posZ); +// VecUtils.multiply(lookPos,20.0/lookPos.lengthVector()); + Vec3 lookPos = Raytrace.getLookingPos(player, 20).getLeft(); + double speed = VecUtils.vec(entity.motionX, entity.motionY, entity.motionZ).lengthVector(); + Vec3 vel = VecUtils.multiply(VecUtils.subtract(lookPos,(new RichEntity(entity)).headPosition()).normalize(),speed); + new RichEntity(entity).setVel(vel); + + } + + private void createNewFireball(EntityFireball source) + { + source.setDead(); + + EntityLivingBase shootingEntity = source.shootingEntity; + EntityFireball fireball = null; + if(source instanceof EntityLargeFireball) + { + fireball = new EntityLargeFireball(((EntityLargeFireball) source).worldObj, shootingEntity, shootingEntity.posX, + shootingEntity.posY, shootingEntity.posZ); + ((EntityLargeFireball)fireball).field_92057_e = ((EntityLargeFireball)source).field_92057_e; + } + else + { + if(source.shootingEntity==null) + { + fireball = new EntitySmallFireball(source.worldObj, source.posX, source.posY, source.posZ, + source.posX, source.posY, source.posZ); + + } + else + { + fireball = new EntitySmallFireball(source.worldObj, shootingEntity, shootingEntity.posX, + shootingEntity.posY, shootingEntity.posZ); + } + } + fireball.setPosition(source.posX, source.posY, source.posZ); + Vec3 lookPos = Raytrace.getLookingPos(speller, 20).getLeft(); + double speed = VecUtils.vec(source.motionX, source.motionY, source.motionZ).lengthVector(); + Vec3 vel = VecUtils.multiply(VecUtils.subtract(lookPos,(new RichEntity(source)).headPosition()).normalize(),speed); + new RichEntity(fireball).setVel(vel); + EntityAffection.mark(fireball); + source.worldObj.spawnEntityInWorld(fireball); + } + + @Override + @SubscribeEvent + public void onSpellerDeath(LivingDeathEvent event) + { + MinecraftForge.EVENT_BUS.unregister(this); + super.onSpellerDeath(event); + } + +} diff --git a/src/main/java/cn/paindar/academymonster/ability/BaseSkill.java b/src/main/java/cn/paindar/academymonster/ability/BaseSkill.java index 5e7a5c3..90412d0 100644 --- a/src/main/java/cn/paindar/academymonster/ability/BaseSkill.java +++ b/src/main/java/cn/paindar/academymonster/ability/BaseSkill.java @@ -8,6 +8,7 @@ import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent; import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.StatCollector; +import net.minecraftforge.event.entity.living.LivingDeathEvent; /** * Created by Paindar on 2017/2/9. @@ -30,7 +31,7 @@ public BaseSkill(EntityLivingBase speller,int maxCooldown,float abilityExp,Strin FMLCommonHandler.instance().bus().register(this); } - float getSkillExp(){return skillExp;} + public float getSkillExp(){return skillExp;} protected int getMaxCooldown(){return maxCooldown;} @@ -88,5 +89,10 @@ public boolean available() public String getUnlocalizedSkillName(){return "ac.ability." + skillName + ".name";} public String getSkillName(){return StatCollector.translateToLocal(skillName);} + @SubscribeEvent + public void onSpellerDeath(LivingDeathEvent event) + { + FMLCommonHandler.instance().bus().unregister(this); + } } diff --git a/src/main/java/cn/paindar/academymonster/core/AcademyMonster.java b/src/main/java/cn/paindar/academymonster/core/AcademyMonster.java old mode 100644 new mode 100755 index cf3483b..3900ac0 --- a/src/main/java/cn/paindar/academymonster/core/AcademyMonster.java +++ b/src/main/java/cn/paindar/academymonster/core/AcademyMonster.java @@ -6,7 +6,6 @@ import cn.paindar.academymonster.core.command.CommandTest; import cn.paindar.academymonster.entity.SkillExtendedEntityProperties; import cn.paindar.academymonster.entity.ai.*; -import com.typesafe.config.Config; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.Mod.Instance; @@ -16,9 +15,9 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityOwnable; import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.entity.boss.IBossDisplayData; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.IMob; -import net.minecraftforge.common.config.Configuration; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -70,13 +69,18 @@ void initSkill() registerSkill(AIBodyIntensify.class, 1,EntityAIBodyIntensify.class,5); registerSkill(AIDirectedShock.class, 2,EntityAIDirectedShock.class,5); registerSkill(AIElectronBomb.class, 1,EntityAIElectronBomb.class,5); + registerSkill(AIElectronMissile.class,0.1f,EntityAIElectronMissile.class,5); + registerSkill(AIFlashing.class,0.2f,EntityAIFlashing.class,5); registerSkill(AIFleshRipping.class, 1,EntityAIFleshRipping.class,5); - registerSkill(AILightShield.class,70f,EntityAILightShield.class,5); + registerSkill(AILightShield.class,1f,EntityAILightShield.class,5); registerSkill(AIMineRay.class,0.7f,EntityAIMineRay.class,5); - registerSkill(AIPenetrateTeleport.class, 2,EntityAIPenetrateTeleport.class,4); + registerSkill(AIPenetrateTeleport.class, 1,EntityAIPenetrateTeleport.class,4); registerSkill(AIRailgun.class, 0.3f,EntityAIRailgun.class,5); + registerSkill(AIThunderBolt.class,0.7f,EntityAIThunderBlot.class,5); registerSkill(AIThunderClap.class,0.4f,EntityAIThunderClap.class,5); - + registerSkill(AIVecReflect.class, 0.3f,null,5); + registerSkill(AIScatterBomb.class,0.5f,EntityAIScatterBomb.class,5); + registerSkill(AIMeltdowner.class,0.1f,EntityAIMeltdowner.class,5); } @EventHandler @@ -111,7 +115,7 @@ public void serverStopping(FMLServerStoppingEvent event) public void addSkill(EntityLiving entity) { - if(entity.worldObj.isRemote ||!isClassAllowed(entity)) + if(entity.worldObj.isRemote) return; List> tempList= new ArrayList<>(skillList); List tempProbList=new ArrayList<>(probList); @@ -151,18 +155,20 @@ public void addSkill(EntityLiving entity) BaseSkill skill; Class aClass; Constructor[] tempConstructor; - Class[] parameterTypes; + Class[] parameterTypes=new Class[2]; float randExp=RandUtils.rangef(0, 1); try { constructor = elem.getConstructor(EntityLivingBase.class, float.class); - skill = (BaseSkill) constructor.newInstance(entity, randExp * randExp); + skill = (BaseSkill) constructor.newInstance(entity, 1- randExp * randExp); aClass = aiList.get(id); - - tempConstructor = aClass.getDeclaredConstructors(); - parameterTypes = tempConstructor[0].getParameterTypes(); - constructor = aClass.getConstructor(parameterTypes[0], parameterTypes[1]); + if(aClass!=null) + { + tempConstructor = aClass.getDeclaredConstructors(); + parameterTypes = tempConstructor[0].getParameterTypes(); + constructor = aClass.getConstructor(parameterTypes[0], parameterTypes[1]); + } } catch(Exception e) @@ -172,15 +178,20 @@ public void addSkill(EntityLiving entity) throw new RuntimeException(); } EntityAIBase baseAI; - try{baseAI=(EntityAIBase)constructor.newInstance(entity,skill);} - catch (Exception e) + if(aClass!=null) { - AcademyMonster.log.error("param1: " + parameterTypes[0] + " , param2:" + parameterTypes[1]); - AcademyMonster.log.error("Argument: " + entity + " , " + skill); - e.printStackTrace(); - throw new RuntimeException(); + try + { + baseAI = (EntityAIBase) constructor.newInstance(entity, skill); + } catch (Exception e) + { + AcademyMonster.log.error("param1: " + parameterTypes[0] + " , param2:" + parameterTypes[1]); + AcademyMonster.log.error("Argument: " + entity + " , " + skill); + e.printStackTrace(); + throw new RuntimeException(); + } + entity.tasks.addTask(aiLevelList.get(id), baseAI); } - entity.tasks.addTask(aiLevelList.get(id),baseAI); string+= skill.getUnlocalizedSkillName()+"~"+randExp+"-"; prob*=factor; } @@ -233,8 +244,17 @@ public void refreshSkills(EntityLiving entity,String skillStr) BaseSkill skill; Class aClass; Constructor[] tempConstructor; - Class[] parameterTypes; - float randExp=Float.parseFloat(skillInfo[1]); + Class[] parameterTypes=new Class[2]; + float randExp=0; + try + { + randExp=Float.parseFloat(skillInfo[1]); + } + catch(NumberFormatException e) + { + //log.warn("Failed to translate "+entity + " in "+skillStr); + randExp=0; + } int id=skillList.indexOf(skillClass); try { @@ -242,10 +262,12 @@ public void refreshSkills(EntityLiving entity,String skillStr) skill = (BaseSkill) constructor.newInstance(entity, randExp); aClass = aiList.get(id); - - tempConstructor = aClass.getDeclaredConstructors(); - parameterTypes = tempConstructor[0].getParameterTypes(); - constructor = aClass.getConstructor(parameterTypes[0], parameterTypes[1]); + if(aClass!=null) + { + tempConstructor = aClass.getDeclaredConstructors(); + parameterTypes = tempConstructor[0].getParameterTypes(); + constructor = aClass.getConstructor(parameterTypes[0], parameterTypes[1]); + } } catch(Exception e) @@ -255,15 +277,20 @@ public void refreshSkills(EntityLiving entity,String skillStr) throw new RuntimeException(); } EntityAIBase baseAI; - try{baseAI=(EntityAIBase)constructor.newInstance(entity,skill);} - catch (Exception e) + if(aClass!=null) { - AcademyMonster.log.error("param1: " + parameterTypes[0] + " , param2:" + parameterTypes[1]); - AcademyMonster.log.error("Argument: " + entity + " , " + skill); - e.printStackTrace(); - throw new RuntimeException(); + try + { + baseAI = (EntityAIBase) constructor.newInstance(entity, skill); + } catch (Exception e) + { + AcademyMonster.log.error("param1: " + parameterTypes[0] + " , param2:" + parameterTypes[1]); + AcademyMonster.log.error("Argument: " + entity + " , " + skill); + e.printStackTrace(); + throw new RuntimeException(); + } + entity.tasks.addTask(aiLevelList.get(id), baseAI); } - entity.tasks.addTask(aiLevelList.get(id),baseAI); } } } @@ -276,7 +303,7 @@ public void refreshSkills(EntityLiving entity,String skillStr) } - private boolean isClassAllowed(EntityLiving entity) + static boolean isClassAllowed(EntityLiving entity) { if (entity instanceof EntityMob || (entity instanceof IMob)) { @@ -284,7 +311,7 @@ private boolean isClassAllowed(EntityLiving entity) { return false; } - if (checkEntityClassAllowed(entity)) + if (!checkEntityClassAllowed(entity)) { return true; } @@ -292,9 +319,9 @@ private boolean isClassAllowed(EntityLiving entity) return false; } - private boolean checkEntityClassAllowed(EntityLiving entity) + private static boolean checkEntityClassAllowed(EntityLiving entity) { - return entity instanceof EntityMob; + return entity instanceof IBossDisplayData; } diff --git a/src/main/java/cn/paindar/academymonster/core/ClientProxy.java b/src/main/java/cn/paindar/academymonster/core/ClientProxy.java index 509d21c..f576948 100644 --- a/src/main/java/cn/paindar/academymonster/core/ClientProxy.java +++ b/src/main/java/cn/paindar/academymonster/core/ClientProxy.java @@ -1,6 +1,7 @@ package cn.paindar.academymonster.core; import cn.paindar.academymonster.core.support.terminal.ui.AIMScannerUI; +import cn.paindar.academymonster.core.support.terminal.ui.BossHealthBar; import cn.paindar.academymonster.entity.EntityLoader; import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -17,6 +18,7 @@ public class ClientProxy extends CommonProxy public void preInit(FMLPreInitializationEvent event) { super.preInit(event); + BossHealthBar.preInit(); EntityLoader.registerRenders(); } diff --git a/src/main/java/cn/paindar/academymonster/core/GlobalEventHandle.java b/src/main/java/cn/paindar/academymonster/core/GlobalEventHandle.java index a01f723..0e4744f 100644 --- a/src/main/java/cn/paindar/academymonster/core/GlobalEventHandle.java +++ b/src/main/java/cn/paindar/academymonster/core/GlobalEventHandle.java @@ -1,13 +1,20 @@ package cn.paindar.academymonster.core; +import cn.paindar.academymonster.ability.BaseSkill; +import cn.paindar.academymonster.core.support.terminal.ui.BossHealthBar; import cn.paindar.academymonster.entity.SkillExtendedEntityProperties; +import cn.paindar.academymonster.entity.boss.EntityFakeRaingun; import cn.paindar.academymonster.network.NetworkManager; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityTracker; +import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.WorldServer; +import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.player.PlayerEvent; @@ -31,12 +38,23 @@ public void onEntityConstruct(EntityEvent.EntityConstructing event) @SubscribeEvent public void onEntityJoinedWorld(EntityJoinWorldEvent event) { - if(!event.world.isRemote && event.entity instanceof EntityLiving) + if(!event.world.isRemote && event.entity instanceof EntityLiving && event.entity instanceof EntityMob) { SkillExtendedEntityProperties data = SkillExtendedEntityProperties.get(event.entity); String savedSkills=data.getSkillData(); - //AcademyMonster.log.info("entity "+event.entity+" have skills:"+savedSkills); - if(savedSkills.equals("")) + if(event.entity instanceof EntityFakeRaingun) + { + String string=""; + if(data.getSkillData().equals("")) + { + for (BaseSkill skill : ((EntityFakeRaingun) event.entity).skillList) + { + string += skill.getUnlocalizedSkillName() + "~" + skill.getSkillExp() + "-"; + } + data.setSkillData(string); + } + } + else if(savedSkills.equals("")) { AcademyMonster.instance.addSkill((EntityLiving)event.entity); } @@ -66,4 +84,11 @@ public void playerStartedTracking(PlayerEvent.StartTracking e) { } } + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void onPreRenderGameOverlay(RenderGameOverlayEvent.Pre event) + { + BossHealthBar.flushHealthBar(event); + } + } diff --git a/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/AIMScannerUI.java b/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/AIMScannerUI.java index f98dc4f..0b8e033 100644 --- a/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/AIMScannerUI.java +++ b/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/AIMScannerUI.java @@ -168,6 +168,12 @@ private void initGui() public void tick() { EntityClientPlayerMP player=Minecraft.getMinecraft().thePlayer; + if(Minecraft.getMinecraft().theWorld==null) + { + current.dispose(); + current=null; + return ; + } if(player == null) return ; MovingObjectPosition trace=Raytrace.traceLiving(player,20, EntitySelectors.living().and(EntitySelectors.exclude(player))); diff --git a/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/BossHealthBar.java b/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/BossHealthBar.java new file mode 100644 index 0000000..2e30a58 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/BossHealthBar.java @@ -0,0 +1,195 @@ +package cn.paindar.academymonster.core.support.terminal.ui; + +import cn.lambdalib.cgui.gui.CGui; +import cn.lambdalib.cgui.gui.Widget; +import cn.lambdalib.cgui.gui.WidgetContainer; +import cn.lambdalib.cgui.gui.component.DrawTexture; +import cn.lambdalib.cgui.gui.component.TextBox; +import cn.lambdalib.util.client.auxgui.AuxGui; +import cn.lambdalib.util.client.auxgui.AuxGuiHandler; +import cn.lambdalib.util.client.font.IFont; +import cn.lambdalib.util.helper.Color; +import cn.lambdalib.util.helper.GameTimer; +import cn.lambdalib.util.mc.WorldUtils; +import cn.paindar.academymonster.core.AcademyMonster; +import cn.paindar.academymonster.entity.boss.EntityFakeRaingun; +import cpw.mods.fml.client.FMLClientHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.entity.Entity; +import net.minecraft.entity.boss.IBossDisplayData; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.glu.GLU; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +/** + * Created by Paindar on 2017/3/8. + */ +@SideOnly(Side.CLIENT) +public class BossHealthBar extends AuxGui +{ + private static int ticks=0; + private static float flushRange=20f; + private static Minecraft mc; + private static WidgetContainer loaded ; + private static List existedList=new ArrayList<>(); + private static AuxGui current = null; + private static List list=new ArrayList<>(); + private static Widget healWidget; + + public static void preInit() + { + mc = FMLClientHandler.instance().getClient(); + loaded=new WidgetContainer(); + Widget board=new Widget().size(1200,400); + loaded.addWidget("backBroad",board,true); + Widget skillList=new Widget(350,-480,1000,125); + healWidget=new Widget(900,133) .addComponent(new TextBox( + new IFont.FontOption(50, IFont.FontAlign.CENTER,new Color(1,0,0,0.8))).setContent("A Test Skill")); + + Widget healBar= new Widget(900,100).pos(30,60).addComponent(new TextBox(new IFont.FontOption(40, IFont.FontAlign.CENTER,new Color(1,1,1,0.6))).setContent("A Test Health")); + Widget barTextures=new Widget(900,53).pos(30,22).addComponent(new DrawHealBar(new ResourceLocation("academymonster:textures/gui/hp_bar.png")).setColor(new Color(1,1,1,0.6))); + healBar.addWidget("textures",barTextures); + healWidget.addWidget("heal_bar",healBar); + skillList.addWidget("skillItem",healWidget); + board.addWidget("skill",skillList); + } + + CGui gui; + Widget root; + + BossHealthBar() + { + gui = new CGui(); + gui.addWidget(root = loaded.getWidget("backBroad").copy()); + requireTicking=true; + + initGui(); + } + + private void initGui() + { + Widget skillPart=root.getWidget("skill"); + skillPart.removeWidget("skillItem"); + } + + @Override + public void tick() + { + EntityClientPlayerMP player=mc.thePlayer; + if(player == null || list == null) + return ; + for(Widget widget:existedList) + { + widget.dispose(); + } + + existedList.clear(); + Widget widget = root.getWidget("skill"); + int i=0; + for(IBossDisplayData entity:list) + { + Widget w=healWidget.copy().pos(30,30+130*i); + w.getComponent(TextBox.class).setContent(((Entity)entity).getCommandSenderName()); + float per=entity.getHealth()/entity.getMaxHealth(); + Widget healBar=w.getWidget("heal_bar"); + healBar.getComponent(TextBox.class).setContent(String.format("%.2f/%.2f",entity.getHealth(),entity.getMaxHealth())); + healBar.getWidget("textures").getComponent(DrawHealBar.class).setDrawLen(per); + i++; + existedList.add(w); + widget.addWidget(w); + } + + } + + private static void createNewHealthBar(List list) + { + for(Widget widget:existedList) + widget.dispose(); + for(Entity e:list) + { + AcademyMonster.log.info("Boss: "+list); + } + } + + public static void flushHealthBar(RenderGameOverlayEvent.Pre event) + { + List tmpList=WorldUtils.getEntities(mc.thePlayer, flushRange, (Entity entity) -> (!entity.isDead && entity instanceof IBossDisplayData)); + list.clear(); + for(Entity entity:tmpList) + { + if(entity instanceof IBossDisplayData) + { + list.add((IBossDisplayData)entity); + } + } + if (current == null && list.size() != 0) + { + current = new BossHealthBar(); + AuxGuiHandler.register(current); + } + else if (current != null && list.size() == 0) + { + current.dispose(); + current=null; + } + + } + + @Override + public boolean isForeground() + { + return false; + } + + @Override + public void draw(ScaledResolution scaledResolution) + { + float aspect = (float)mc.displayWidth / mc.displayHeight; + + GL11.glMatrixMode(GL11.GL_PROJECTION); + GL11.glPushMatrix(); + GL11.glLoadIdentity(); + + GLU.gluPerspective(50, + aspect, + 1f, 100); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + GL11.glPushMatrix(); + GL11.glLoadIdentity(); + + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glDisable(GL11.GL_ALPHA_TEST); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glColor4d(1, 1, 1, 1); + + double scale = 1.0 / 310; + + GL11.glTranslated(-3, .5, -4); + + //GL11.glTranslated(1, -1.8, 0); + + GL11.glScaled(scale, -scale, scale); + gui.draw(); + + GL11.glPopMatrix(); + + GL11.glMatrixMode(GL11.GL_PROJECTION); + GL11.glPopMatrix(); + + GL11.glMatrixMode(GL11.GL_MODELVIEW); + + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glEnable(GL11.GL_ALPHA_TEST); + GL11.glCullFace(GL11.GL_BACK); + } +} diff --git a/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/DrawHealBar.java b/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/DrawHealBar.java new file mode 100644 index 0000000..a41164e --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/core/support/terminal/ui/DrawHealBar.java @@ -0,0 +1,103 @@ +package cn.paindar.academymonster.core.support.terminal.ui; + +import cn.lambdalib.cgui.gui.Widget; +import cn.lambdalib.cgui.gui.component.Component; +import cn.lambdalib.cgui.gui.event.FrameEvent; +import cn.lambdalib.util.client.HudUtils; +import cn.lambdalib.util.client.RenderUtils; +import cn.lambdalib.util.helper.Color; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; + +/** + * Created by Paindar on 2017/3/10. + */ +public class DrawHealBar extends Component +{ + + public static final ResourceLocation MISSING = new ResourceLocation("lambdalib:textures/cgui/missing.png"); + public ResourceLocation texture; + public Color color; + public double zLevel; + public boolean writeDepth; + private float drawLen=1; + private int shaderId; + + public DrawHealBar() { + this(MISSING); + } + + public DrawHealBar(ResourceLocation texture) { + this(texture, Color.white()); + } + + public DrawHealBar(String name, ResourceLocation _texture, Color _color) { + super(name); + this.zLevel = 0.0D; + this.writeDepth = true; + this.shaderId = 0; + this.texture = _texture; + this.color = _color; + this.listen(FrameEvent.class, (w, e) -> { + GL11.glPushMatrix(); + GL11.glBlendFunc(770, 771); + GL11.glDisable(3008); + GL11.glDepthMask(this.writeDepth); + GL20.glUseProgram(this.shaderId); + this.color.bind(); + double preLevel = HudUtils.zLevel; + HudUtils.zLevel = this.zLevel; + if(this.texture != null && !this.texture.getResourcePath().equals("")) { + RenderUtils.loadTexture(this.texture); + HudUtils.rawRect(0, 0,0,0, w.transform.width*drawLen, w.transform.height,drawLen,1); + + } else { + HudUtils.colorRect(0.0D, 0.0D, w.transform.width, w.transform.height); + } + + HudUtils.zLevel = preLevel; + GL20.glUseProgram(0); + GL11.glDepthMask(true); + GL11.glPopMatrix(); + }); + } + + + public DrawHealBar(ResourceLocation _texture, Color _color) { + this("DrawHealBar", _texture, _color); + } + + public void setShaderId(int id) { + this.shaderId = id; + } + + public void setDrawLen(float len){drawLen=len;} + + public DrawHealBar setTex(ResourceLocation t) { + this.texture = t; + return this; + } + + public DrawHealBar setColor(Color c) { + this.color.from(c); + return this; + } + + public DrawHealBar setColor4i(int r, int g, int b, int a) { + this.color.setColor4d((double)r / 255.0D, (double)g / 255.0D, (double)b / 255.0D, (double)a / 255.0D); + return this; + } + + public DrawHealBar setColor4d(double _r, double _g, double _b, double _a) { + this.color.setColor4d(_r, _g, _b, _a); + return this; + } + + public static DrawHealBar get(Widget w) { + return (DrawHealBar)w.getComponent("DrawHealBar"); + } +} + diff --git a/src/main/java/cn/paindar/academymonster/entity/EntityLightShield.java b/src/main/java/cn/paindar/academymonster/entity/EntityLightShield.java index 834504f..328a5b6 100644 --- a/src/main/java/cn/paindar/academymonster/entity/EntityLightShield.java +++ b/src/main/java/cn/paindar/academymonster/entity/EntityLightShield.java @@ -9,7 +9,6 @@ import cn.lambdalib.util.generic.MathUtils; import cn.lambdalib.util.helper.GameTimer; import cn.lambdalib.util.helper.Motion3D; -import cn.paindar.academymonster.core.AcademyMonster; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData; import io.netty.buffer.ByteBuf; diff --git a/src/main/java/cn/paindar/academymonster/entity/EntityLoader.java b/src/main/java/cn/paindar/academymonster/entity/EntityLoader.java index 32e2a55..2f7efba 100644 --- a/src/main/java/cn/paindar/academymonster/entity/EntityLoader.java +++ b/src/main/java/cn/paindar/academymonster/entity/EntityLoader.java @@ -1,11 +1,9 @@ package cn.paindar.academymonster.entity; -import cn.academy.vanilla.electromaster.client.renderer.RendererCoinThrowing; -import cn.academy.vanilla.meltdowner.client.render.RenderMdShield; import cn.academy.vanilla.meltdowner.entity.EntityMdBall; -import cn.academy.vanilla.meltdowner.entity.EntityMineRayBasic; -import cn.academy.vanilla.meltdowner.entity.EntityMineRayExpert; import cn.paindar.academymonster.core.AcademyMonster; +import cn.paindar.academymonster.entity.boss.EntityFakeRaingun; +import cn.paindar.academymonster.entity.boss.render.RenderFakeRailgun; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.common.registry.EntityRegistry; import cpw.mods.fml.relauncher.Side; @@ -30,12 +28,14 @@ public EntityLoader() @SideOnly(Side.CLIENT) public static void registerRenders() { - registerEntityRender(EntityMdBallNative.class, new EntityMdBall.R()); + registerEntityRender(EntityMdBallNative.class, new EntityMdBallNative.R()); registerEntityRender(EntityCoinThrowingNative.class,new EntityCoinThrowingNative.R()); registerEntityRender(EntityRailgunFXNative.class,new EntityRailgunFXNative.R()); + registerEntityRender(EntityMDRayNative.class,new EntityMDRayNative.R()); registerEntityRender(EntityArcNative.class,new EntityArcNative.Renderer()); registerEntityRender(EntityMineRayNative.class,new EntityMineRayNative.R()); registerEntityRender(EntityLightShield.class,new EntityLightShield.R()); + registerEntityRender(EntityFakeRaingun.class,new RenderFakeRailgun()); } public static void registerEntity() @@ -43,6 +43,13 @@ public static void registerEntity() registerEntity(EntityMineRayNative.class,"am_mine_ray_eff",15,1,true); registerEntity(EntityLightShield.class,"am_light_shield_eff",15,1,true); registerEntity(EntityCoinThrowingNative.class,"am_coin_throwing_eff",15,1,true); + registerEntity(EntityMdBallNative.class,"am_meltdown_ball_eff",15,1,true); + registerEntity(EntityFakeRaingun.class,"am_fake_railgun",40,1,true); + for(BiomeGenBase biome:BiomeGenBase.getBiomeGenArray()) + { + if(biome != null && biome != BiomeGenBase.sky && biome !=BiomeGenBase.hell) + registerEntitySpawn(EntityFakeRaingun.class,100,1,1,EnumCreatureType.monster,biome); + } } @SideOnly(Side.CLIENT) diff --git a/src/main/java/cn/paindar/academymonster/entity/EntityMDRayNative.java b/src/main/java/cn/paindar/academymonster/entity/EntityMDRayNative.java new file mode 100644 index 0000000..1545e05 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/EntityMDRayNative.java @@ -0,0 +1,65 @@ +package cn.paindar.academymonster.entity; + +import cn.academy.core.client.render.ray.RendererRayComposite; +import cn.academy.vanilla.meltdowner.client.render.MdParticleFactory; +import cn.lambdalib.particle.Particle; +import cn.lambdalib.util.generic.RandUtils; +import cn.lambdalib.util.generic.VecUtils; +import cn.lambdalib.util.helper.Motion3D; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.Vec3; + +/** + * Created by Paindar on 2017/3/13. + */ +public class EntityMDRayNative extends EntityRayBaseNative +{ + public EntityMDRayNative(EntityLivingBase _player, double length) { + this(_player, new Motion3D(_player, true), length); + } + + public EntityMDRayNative(EntityLivingBase spawner, Motion3D mo, double length) { + super(spawner); + + Vec3 start = mo.getPosVec(), end = mo.move(length).getPosVec(); + this.setFromTo(start, end); + this.blendInTime = 200; + this.blendOutTime = 700; + this.life = 50; + this.length = length; + } + + @Override + protected void onFirstUpdate() + { + super.onFirstUpdate(); + worldObj.playSound(posX, posY, posZ, "academy:md.meltdowner", 0.5f, 1.0f, false); + } + @Override + public void onUpdate() { + super.onUpdate(); + if(RandUtils.nextDouble() < 0.8) { + Particle p = MdParticleFactory.INSTANCE.next(worldObj, + new Motion3D(this, true).move(RandUtils.ranged(0, 10)).getPosVec(), + VecUtils.vec(RandUtils.ranged(-.03, .03), RandUtils.ranged(-.03, .03), RandUtils.ranged(-.03, .03))); + worldObj.spawnEntityInWorld(p); + } + } + + public static class R extends RendererRayComposite + { + + public R() { + super("mdray"); + this.cylinderIn.width = 0.17; + this.cylinderIn.color.setColor4i(216, 248, 216, 230); + + this.cylinderOut.width = 0.22; + this.cylinderOut.color.setColor4i(106, 242, 106, 50); + + this.glow.width = 1.5; + this.glow.color.a = 0.8; + } + + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/EntityMdBallNative.java b/src/main/java/cn/paindar/academymonster/entity/EntityMdBallNative.java index 9684618..ebe81bf 100644 --- a/src/main/java/cn/paindar/academymonster/entity/EntityMdBallNative.java +++ b/src/main/java/cn/paindar/academymonster/entity/EntityMdBallNative.java @@ -1,5 +1,10 @@ package cn.paindar.academymonster.entity; +import cn.academy.core.Resources; +import cn.academy.core.client.ACRenderingHelper; +import cn.lambdalib.template.client.render.entity.RenderIcon; +import cn.lambdalib.util.client.RenderUtils; +import cn.lambdalib.util.client.shader.ShaderSimple; import cn.lambdalib.util.entityx.EntityAdvanced; import cn.lambdalib.util.entityx.EntityCallback; import cn.lambdalib.util.generic.MathUtils; @@ -7,11 +12,16 @@ import cn.lambdalib.util.helper.GameTimer; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL20; /** * Created by Paindar on 2017/2/10. @@ -232,5 +242,66 @@ private void updatePosition() { posZ = spawner.posZ + subZ; } + @SideOnly(Side.CLIENT) + public static class R extends RenderIcon + { + + ResourceLocation[] textures; + ResourceLocation glowTexture; + + public R() { + super(null); + textures = Resources.getEffectSeq("mdball", MAX_TETXURES); + glowTexture = Resources.getTexture("effects/mdball/glow"); + //this.minTolerateAlpha = 0.05f; + this.shadowOpaque = 0; + } + + @Override + public void doRender(Entity par1Entity, double x, double y, + double z, float par8, float par9) { + if(RenderUtils.isInShadowPass()) { + return; + } + + EntityMdBallNative ent = (EntityMdBallNative) par1Entity; + if(!ent.updateRenderTick()) + return; + + EntityPlayer clientPlayer = Minecraft.getMinecraft().thePlayer; + + //HACK: Force set the render pos to prevent glitches + { + x = ent.posX - clientPlayer.posX; + y = ent.posY - clientPlayer.posY; + z = ent.posZ - clientPlayer.posZ; + y += 1.6; + } + + GL11.glPushMatrix(); + { + ShaderSimple.instance().useProgram(); + GL11.glTranslated(ent.offsetX, ent.offsetY, ent.offsetZ); + + double alpha = ent.getAlpha(); + float size = ent.getSize(); + + //Glow texture + this.color.a = alpha * (0.3 + ent.alphaWiggle * 0.7); + this.icon = glowTexture; + this.setSize(0.7f * size); + super.doRender(par1Entity, x, y, z, par8, par9); + + //Core + this.color.a = alpha * (0.8 + 0.2 * ent.alphaWiggle); + this.icon = textures[ent.texID]; + this.setSize(0.5f * size); + super.doRender(par1Entity, x, y, z, par8, par9); + GL20.glUseProgram(0); + } + GL11.glPopMatrix(); + } + + } } diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIElectronMissile.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIElectronMissile.java new file mode 100644 index 0000000..124ad8d --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIElectronMissile.java @@ -0,0 +1,38 @@ +package cn.paindar.academymonster.entity.ai; + +import cn.paindar.academymonster.ability.AIElectronMissile; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; + +/** + * Created by Paindar on 2017/3/12. + */ +public class EntityAIElectronMissile extends EntityAIBase +{ + private final EntityLiving speller; + private EntityLivingBase target; + private AIElectronMissile skill; + + public EntityAIElectronMissile(EntityLiving speller,AIElectronMissile skill) + { + this.speller=speller; + this.skill=skill; + } + + @Override + public boolean shouldExecute() + { + EntityLivingBase target=speller.getAttackTarget(); + if (target==null|| !skill.available()) + return false; + double dist=speller.getDistanceSqToEntity(target); + return this.speller.getAttackTarget().isEntityAlive() && skill.available() && dist >= 2.25 && dist <= skill.getMaxDistance() * skill.getMaxDistance(); + } + + public void startExecuting() + { + skill.spell(); + } + +} diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIFakeRailgunAttack.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIFakeRailgunAttack.java new file mode 100644 index 0000000..32932e4 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIFakeRailgunAttack.java @@ -0,0 +1,122 @@ +package cn.paindar.academymonster.entity.ai; + +import cn.lambdalib.util.generic.MathUtils; +import cn.lambdalib.util.mc.BlockSelectors; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.Raytrace; +import cn.paindar.academymonster.ability.*; +import cn.paindar.academymonster.entity.boss.EntityFakeRaingun; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +import java.util.List; + +/** + * Created by Paindar on 2017/3/8. + */ +public class EntityAIFakeRailgunAttack extends EntityAIBase +{ + private final EntityFakeRaingun speller; + private EntityLivingBase target; + private int tick=0; + + public EntityAIFakeRailgunAttack(EntityFakeRaingun speller) + { + this.speller=speller; + } + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() + { + if(speller.getAttackTarget()!=null) + { + target=speller.getAttackTarget(); + return true; + } + return false; + } + + @Override + public void updateTask() + { + List list=speller.skillList; + tick=(tick++)%10; + if(tick>=3) + return; + boolean success=false; + for(BaseSkill skill:list) + { + if(skill.available()) + { + MovingObjectPosition result= Raytrace.rayTraceBlocks(speller.worldObj, + Vec3.createVectorHelper(speller.posX, speller.posY, speller.posZ), + Vec3.createVectorHelper(target.posX, target.posY, target.posZ), BlockSelectors.filNormal); + if(skill instanceof AIThunderClap) + { + if(result==null) + { + ((AIThunderClap) skill).spell(target.posX, target.posY, target.posZ); + success=true; + } + } + else if(skill instanceof AIRailgun) + { + MovingObjectPosition trace = Raytrace.traceLiving(speller,((AIRailgun)skill).getMaxDistance(), EntitySelectors.living(), BlockSelectors.filNothing); + if (trace != null && trace.typeOfHit== MovingObjectPosition.MovingObjectType.ENTITY) + { + if(trace.entityHit==target) + { + skill.spell(); + success=true; + } + } + } + else if(skill instanceof AIThunderBolt) + { + MovingObjectPosition trace = Raytrace.traceLiving(speller,((AIThunderBolt)skill).getMaxDistance(), EntitySelectors.living(), BlockSelectors.filNothing); + if (trace != null && trace.typeOfHit== MovingObjectPosition.MovingObjectType.ENTITY) + { + if(trace.entityHit==target) + { + skill.spell(); + success=true; + } + } + } + else if(skill instanceof AIBodyIntensify) + { + skill.spell(); + success=true; + } + else if (skill instanceof AIArcGen) + { + if (result != null && result.typeOfHit== MovingObjectPosition.MovingObjectType.ENTITY) + { + if(result.entityHit==target) + { + skill.spell(); + success=true; + } + } + else if (result != null && result.typeOfHit== MovingObjectPosition.MovingObjectType.BLOCK) + { + Block block=speller.worldObj.getBlock(result.blockX,result.blockY,result.blockZ); + if(block.getMaterial()== Material.wood) + { + skill.spell(); + success=true; + } + } + } + if(success) + break; + } + } + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIFlashing.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIFlashing.java new file mode 100644 index 0000000..a6a278c --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIFlashing.java @@ -0,0 +1,89 @@ +package cn.paindar.academymonster.entity.ai; + +import cn.lambdalib.util.generic.RandUtils; +import cn.paindar.academymonster.ability.AIFlashing; +import cn.paindar.academymonster.ability.AIPenetrateTeleport; +import net.minecraft.block.Block; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.world.World; + +import static java.lang.Math.sqrt; + +/** + * Created by voidcl on 2017/3/10. + */ +public class EntityAIFlashing extends EntityAIBase{ + + EntityLiving speller; + AIFlashing skill; + EntityLivingBase target; + + public EntityAIFlashing(EntityLiving zombie,AIFlashing skill) + { + speller=zombie; + this.skill=skill; + } + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() { + + //&& this.speller.getDistanceSqToEntity(this.speller.getAttackTarget())<=skill.getMaxDistance() + return this.speller.getAttackTarget() != null && !skill.isSkillInCooldown() && this.speller.getAttackTarget().isEntityAlive(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.target =this.speller.getAttackTarget(); + } + + /** + * Resets the task + */ + public void resetTask() + { + this.target = null; + } + + private boolean hasPlace(World world , double x, double y, double z) + { + int ix=(int)x,iy=(int)y,iz=(int)z; + Block b1 = world.getBlock(ix, iy, iz); + Block b2 = world.getBlock(ix, iy + 1, iz); + return !b1.canCollideCheck(world.getBlockMetadata(ix, iy, iz), false) && !b2.canCollideCheck(world.getBlockMetadata(ix, iy + 1, iz), false); + } + + public void updateTask() + { + double dist=sqrt(this.speller.getDistanceSqToEntity(target)); + double distBtwEntities=dist; + dist=skill.getMaxDistance(); + if(target!=null && skill.available()&&distBtwEntities>=3) + { + + double dx= (target.posX-speller.posX)/distBtwEntities, + dy=(target.posY-speller.posY)/distBtwEntities, + dz=(target.posZ-speller.posZ)/distBtwEntities; + World world=speller.worldObj; + double x = speller.posX + dx * dist; + double y = speller.posY + dy * dist; + double z = speller.posZ + dz * dist; + + if(hasPlace(world,x+1+RandUtils.nextInt(1),y+1,z+1+RandUtils.nextInt(1))) + { + this.skill.spell(x,y,z); + speller.getNavigator().clearPathEntity(); + + } + + + } + + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAILightShield.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAILightShield.java index 66a04f4..fa4af67 100644 --- a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAILightShield.java +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAILightShield.java @@ -1,7 +1,6 @@ package cn.paindar.academymonster.entity.ai; import cn.paindar.academymonster.ability.AILightShield; -import cn.paindar.academymonster.core.AcademyMonster; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAIBase; diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIMeltdowner.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIMeltdowner.java new file mode 100644 index 0000000..257fa41 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIMeltdowner.java @@ -0,0 +1,62 @@ +package cn.paindar.academymonster.entity.ai; + +import cn.paindar.academymonster.ability.AIMeltdowner; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; + +/** + * Created by Paindar on 2017/3/13. + */ +public class EntityAIMeltdowner extends EntityAIBase +{ + private final EntityLiving speller; + private EntityLivingBase target; + private AIMeltdowner skill; + + public EntityAIMeltdowner(EntityLiving speller, AIMeltdowner skill) + { + this.speller = speller; + this.skill = skill; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() + { + EntityLivingBase target=speller.getAttackTarget(); + if (target==null) + return false; + double dist=speller.getDistanceSqToEntity(target); + return this.speller.getAttackTarget().isEntityAlive() && !skill.isSkillInCooldown() && dist >= 2.25 && dist <= skill.getMaxDistance() * skill.getMaxDistance(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.target = this.speller.getAttackTarget(); + } + + /** + * Resets the task + */ + public void resetTask() + { + this.target = null; + } + + /** + * Update the task. + */ + public void updateTask() + { + if(!skill.isSkillInCooldown()) + { + skill.spell(); + } + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIScatterBomb.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIScatterBomb.java new file mode 100644 index 0000000..42df0c8 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIScatterBomb.java @@ -0,0 +1,60 @@ +package cn.paindar.academymonster.entity.ai; + +import cn.paindar.academymonster.ability.AIScatterBomb; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; + +/** + * Created by Paindar on 2017/3/12. + */ +public class EntityAIScatterBomb extends EntityAIBase +{ + private final EntityLiving speller; + private EntityLivingBase target; + private AIScatterBomb skill; + + public EntityAIScatterBomb(EntityLiving speller,AIScatterBomb skill) + { + this.speller=speller; + this.skill=skill; + } + + @Override + public boolean shouldExecute() + { + EntityLivingBase target=speller.getAttackTarget(); + if (target==null|| skill.isSkillInCooldown()) + return false; + double dist=speller.getDistanceSqToEntity(target); + return this.speller.getAttackTarget().isEntityAlive() && !skill.isSkillInCooldown() && dist >= 2.25 && dist <= skill.getMaxDistance() * skill.getMaxDistance(); + } + + public void startExecuting() + { + this.target =this.speller.getAttackTarget(); + } + + @Override + public void updateTask() + { + if(target!=null) + { + if(!skill.isChanting()) + { + skill.spell(); + } + else + { + double range = speller.getDistanceSqToEntity(target); + if (range <= skill.getMaxDistance() * skill.getMaxDistance()) + { + if(skill.getBallSize()>=7) + { + skill.spell(); + } + } + } + } + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIThunderBlot.java b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIThunderBlot.java new file mode 100644 index 0000000..0a09b18 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/ai/EntityAIThunderBlot.java @@ -0,0 +1,72 @@ +package cn.paindar.academymonster.entity.ai; + +import cn.lambdalib.util.mc.BlockSelectors; +import cn.lambdalib.util.mc.EntitySelectors; +import cn.lambdalib.util.mc.Raytrace; +import cn.paindar.academymonster.ability.AIThunderBolt; +import net.minecraft.block.Block; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.util.MovingObjectPosition; + +/** + * Created by Paindar on 2017/3/7. + */ +public class EntityAIThunderBlot extends EntityAIBase +{ + private final EntityLiving speller; + private EntityLivingBase target; + private AIThunderBolt skill; + + public EntityAIThunderBlot(EntityLiving speller,AIThunderBolt skill) + { + this.speller=speller; + this.skill=skill; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() { + EntityLivingBase target=speller.getAttackTarget(); + if (target==null||skill.isSkillInCooldown()) + return false; + double dist=speller.getDistanceSqToEntity(target); + return !skill.isSkillInCooldown() && dist >= 2.25 && dist <= skill.getMaxDistance() * skill.getMaxDistance(); + } + + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.target =this.speller.getAttackTarget(); + } + + /** + * Resets the task + */ + public void resetTask() + { + this.target = null; + } + + /** + * Update the task. + */ + public void updateTask(){ + if (target!=null ) { + MovingObjectPosition trace = Raytrace.traceLiving(speller,skill.getMaxDistance(), EntitySelectors.living(), BlockSelectors.filNothing); + if (trace != null && trace.typeOfHit== MovingObjectPosition.MovingObjectType.ENTITY) + { + if(trace.entityHit==target) + { + skill.spell(); + } + } + } + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/boss/EntityFakeRaingun.java b/src/main/java/cn/paindar/academymonster/entity/boss/EntityFakeRaingun.java new file mode 100644 index 0000000..c3e4fb8 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/boss/EntityFakeRaingun.java @@ -0,0 +1,109 @@ +package cn.paindar.academymonster.entity.boss; + +import cn.academy.ability.ModuleAbility; +import cn.academy.vanilla.ModuleVanilla; +import cn.lambdalib.util.generic.RandUtils; +import cn.paindar.academymonster.ability.*; +import cn.paindar.academymonster.entity.ai.EntityAIFakeRailgunAttack; +import net.minecraft.entity.Entity; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.*; +import net.minecraft.entity.boss.IBossDisplayData; +import net.minecraft.entity.monster.EntityMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Paindar on 2017/3/7. + */ +public class EntityFakeRaingun extends EntityMob implements IBossDisplayData +{ + public List skillList=new ArrayList<>(); + public EntityFakeRaingun(World p_i1738_1_) + { + super(p_i1738_1_); + this.setHealth(this.getMaxHealth()); + this.getNavigator().setCanSwim(true); + this.tasks.addTask(0, new EntityAISwimming(this)); + this.tasks.addTask(2, new EntityAIAttackOnCollide(this, EntityPlayer.class, 8.0D, false)); + this.tasks.addTask(4, new EntityAIFakeRailgunAttack(this)); + this.tasks.addTask(5, new EntityAIWander(this, 1.0D)); + this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(7, new EntityAILookIdle(this)); + this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 8, true)); + this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false)); + this.experienceValue = 50; + + skillList.add(new AIArcGen(this,0.5f+ RandUtils.rangef(0,0.5f))); + skillList.add(new AIBodyIntensify(this,0.5f+ RandUtils.rangef(0,0.5f))); + skillList.add(new AIRailgun(this,0.5f+ RandUtils.rangef(0,0.5f))); + skillList.add(new AIThunderBolt(this,0.5f+ RandUtils.rangef(0,0.5f))); + skillList.add(new AIThunderClap(this,0.5f+ RandUtils.rangef(0,0.5f))); + } + + public void writeEntityToNBT(NBTTagCompound nbt) + { + super.writeEntityToNBT(nbt); + nbt.setFloat("ArcGen",skillList.get(0).getSkillExp()); + nbt.setFloat("BodyIntensify",skillList.get(1).getSkillExp()); + nbt.setFloat("Railgun",skillList.get(2).getSkillExp()); + nbt.setFloat("ThunderBolt",skillList.get(3).getSkillExp()); + nbt.setFloat("ThunderClap",skillList.get(4).getSkillExp()); + } + + + public void readEntityFromNBT(NBTTagCompound nbt) + { + super.readEntityFromNBT(nbt); + skillList.clear(); + skillList.add(new AIArcGen(this,nbt.getFloat("ArcGen"))); + skillList.add(new AIBodyIntensify(this,nbt.getFloat("BodyIntensify"))); + skillList.add(new AIThunderBolt(this,nbt.getFloat("ThunderBolt"))); + skillList.add(new AIRailgun(this,nbt.getFloat("Railgun"))); + skillList.add(new AIThunderClap(this,nbt.getFloat("ThunderClap"))); + } + + public int getTotalArmorValue() + { + return 4; + } + + /** + * Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param + * par2 - Level of Looting used to kill this mob. + */ + protected void dropFewItems(boolean p_70628_1_, int p_70628_2_) + { + this.dropItem(Items.iron_ingot, RandUtils.nextInt(5)); + this.dropItem(Item.getItemFromBlock(Blocks.iron_block), RandUtils.nextInt(2)); + this.dropItem(ModuleVanilla.coin,RandUtils.nextInt(5)+3); + if(RandUtils.nextFloat()<=1) + this.dropItem(ModuleAbility.inductionFactor.create(ModuleVanilla.electromaster).getItem(),1); + + } + + protected boolean isAIEnabled() + { + return true; + } + + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(40.0D); + this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.20D); + this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(60); + } + + public void mountEntity(Entity p_70078_1_) + { + this.ridingEntity = null; + } +} diff --git a/src/main/java/cn/paindar/academymonster/entity/boss/render/RenderFakeRailgun.java b/src/main/java/cn/paindar/academymonster/entity/boss/render/RenderFakeRailgun.java new file mode 100644 index 0000000..9c5b9e3 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/entity/boss/render/RenderFakeRailgun.java @@ -0,0 +1,78 @@ +package cn.paindar.academymonster.entity.boss.render; + +import cn.paindar.academymonster.entity.boss.EntityFakeRaingun; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.renderer.entity.RendererLivingEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +/** + * Created by Paindar on 2017/3/7. + */ +@SideOnly(Side.CLIENT) +public class RenderFakeRailgun extends RendererLivingEntity +{ + private static final ResourceLocation textures = new ResourceLocation("textures/entity/steve.png"); + public ModelBiped modelBipedMain; + public ModelBiped modelArmorChestplate; + public ModelBiped modelArmor; + + public RenderFakeRailgun() + { + super(new ModelBiped(0.0F), 0.5F); + this.modelBipedMain = (ModelBiped)this.mainModel; + this.modelArmorChestplate = new ModelBiped(1.0F); + this.modelArmor = new ModelBiped(0.5F); + } + + + public void doRender(EntityFakeRaingun entity, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_) + { + GL11.glColor3f(1.0F, 1.0F, 1.0F); + + double d3 = p_76986_4_ - (double)entity.yOffset; + + super.doRender((EntityLivingBase)entity, p_76986_2_, d3, p_76986_6_, p_76986_8_, p_76986_9_); + this.modelArmorChestplate.aimedBow = this.modelArmor.aimedBow = this.modelBipedMain.aimedBow = false; + this.modelArmorChestplate.isSneak = this.modelArmor.isSneak = this.modelBipedMain.isSneak = false; + this.modelArmorChestplate.heldItemRight = this.modelArmor.heldItemRight = this.modelBipedMain.heldItemRight = 0; + } + + protected void preRenderCallback(EntityFakeRaingun entity, float partialTickTime) + { + float f1 = 0.9375F; + GL11.glScalef(f1, f1, f1); + } + + + protected void preRenderCallback(EntityLivingBase p_77041_1_, float p_77041_2_) + { + this.preRenderCallback((EntityFakeRaingun)p_77041_1_, p_77041_2_); + } + + public void doRender(EntityLivingBase p_76986_1_, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_) + { + this.doRender((EntityFakeRaingun)p_76986_1_, p_76986_2_, p_76986_4_, p_76986_6_, p_76986_8_, p_76986_9_); + } + + public void doRender(Entity p_76986_1_, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_) + { + this.doRender((EntityFakeRaingun)p_76986_1_, p_76986_2_, p_76986_4_, p_76986_6_, p_76986_8_, p_76986_9_); + } + + /** + * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture. + * + * @param p_110775_1_ + */ + @Override + protected ResourceLocation getEntityTexture(Entity p_110775_1_) + { + return textures; + } +} diff --git a/src/main/java/cn/paindar/academymonster/network/MessageMeltdownerEffect.java b/src/main/java/cn/paindar/academymonster/network/MessageMeltdownerEffect.java new file mode 100644 index 0000000..22c18dd --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/network/MessageMeltdownerEffect.java @@ -0,0 +1,68 @@ +package cn.paindar.academymonster.network; + +import cn.paindar.academymonster.entity.EntityMDRayNative; +import cn.paindar.academymonster.entity.EntityRailgunFXNative; +import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.nbt.NBTTagCompound; + +/** + * Created by Paindar on 2017/3/13. + */ +public class MessageMeltdownerEffect implements IMessage +{ + public static class Handler implements IMessageHandler + { + @Override + @SideOnly(Side.CLIENT) + public IMessage onMessage(MessageMeltdownerEffect message, MessageContext ctx) + { + if (ctx.side == Side.CLIENT) + { + EntityLivingBase player= (EntityLivingBase) Minecraft.getMinecraft().theWorld.getEntityByID(message.nbt.getInteger("i")); + int dist=message.nbt.getInteger("dst"); + player.worldObj.spawnEntityInWorld(new EntityMDRayNative(player, dist)); + } + return null; + } + } + + NBTTagCompound nbt; + public MessageMeltdownerEffect(){} + + public MessageMeltdownerEffect(EntityLivingBase speller,int dist) + { + nbt=new NBTTagCompound(); + nbt.setInteger("i",speller.getEntityId()); + nbt.setInteger("dst",dist); + } + + /** + * Convert from the supplied buffer into your specific message type + * + * @param buf + */ + @Override + public void fromBytes(ByteBuf buf) + { + nbt= ByteBufUtils.readTag(buf); + } + + /** + * Deconstruct your message into the supplied byte buffer + * + * @param buf + */ + @Override + public void toBytes(ByteBuf buf) + { + ByteBufUtils.writeTag(buf, nbt); + } +} diff --git a/src/main/java/cn/paindar/academymonster/network/MessageThunderBolt.java b/src/main/java/cn/paindar/academymonster/network/MessageThunderBolt.java new file mode 100644 index 0000000..38c6522 --- /dev/null +++ b/src/main/java/cn/paindar/academymonster/network/MessageThunderBolt.java @@ -0,0 +1,71 @@ +package cn.paindar.academymonster.network; + +import cn.paindar.academymonster.ability.AIThunderBolt; +import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Paindar on 2017/3/7. + */ +public class MessageThunderBolt implements IMessage +{ + public static class Handler implements IMessageHandler + { + @Override + @SideOnly(Side.CLIENT) + public IMessage onMessage(MessageThunderBolt msg, MessageContext ctx) + { + EntityLivingBase ori=(EntityLivingBase) Minecraft.getMinecraft().theWorld.getEntityByID(msg.nbt.getInteger("origin")); + EntityLivingBase target=(EntityLivingBase) Minecraft.getMinecraft().theWorld.getEntityByID(msg.nbt.getInteger("target")); + List aoes=new ArrayList<>(); + int list[]=msg.nbt.getIntArray("list"); + for(int i:list) + { + aoes.add( Minecraft.getMinecraft().theWorld.getEntityByID(i)); + } + AIThunderBolt.spawnEffect(ori,target,aoes); + return null; + } + } + + NBTTagCompound nbt=new NBTTagCompound(); + + public MessageThunderBolt(){} + + public MessageThunderBolt(EntityLivingBase ori, EntityLivingBase target, List aoes) + { + int[] list=new int[aoes.size()]; + for(int i=0;i list, EntityPlayerMP player) + { + if(!player.getEntityWorld().isRemote) + { + MessageThunderBolt msg = new MessageThunderBolt(ori,target,list); + instance.sendTo(msg, player); + } + else + throw new IllegalStateException("Wrong context side!"); + } } diff --git a/src/main/resources/assets/academymonster/config/default.cfg b/src/main/resources/assets/academymonster/config/default.cfg index 6359707..b170c2a 100644 --- a/src/main/resources/assets/academymonster/config/default.cfg +++ b/src/main/resources/assets/academymonster/config/default.cfg @@ -25,6 +25,14 @@ am { prob: 1 } + ElectronMissile + { + prob:0.1 + } + Flashing + { + prob:0.2 + } FleshRipping { prob:1 @@ -33,6 +41,11 @@ am { prob:0.5 } + Meltdowner + { + prob:0.2 + destroyBlock=true; + } MineRay { prob:0.7 @@ -54,10 +67,22 @@ am { prob:0.7 } + ThunderBolt + { + prob:0.7 + } ThunderClap { prob:0.4 } + VecReflect + { + prob:0.3 + } + ScatterBomb + { + prob:0.5f + } } monster { diff --git a/src/main/resources/assets/academymonster/lang/en_US.lang b/src/main/resources/assets/academymonster/lang/en_US.lang index 923fed6..c27152c 100644 --- a/src/main/resources/assets/academymonster/lang/en_US.lang +++ b/src/main/resources/assets/academymonster/lang/en_US.lang @@ -3,4 +3,6 @@ am.app.aim_scanner_skill_list.name=Skill List: ac.settings.prop.open_aim_scanner=Open AIM Scanner am.aim_scanner_skill_list.notinstalled=You have not yet installed the AIM Scanner app. ac.app.aim_scanner.name=AIM Scanner -ac.ability.MineRay.name=Mine Ray \ No newline at end of file +ac.ability.MineRay.name=Mine Ray + +entity.academymonster.am_fake_railgun.name=Fake Railgun \ No newline at end of file diff --git a/src/main/resources/assets/academymonster/lang/zh_CN.lang b/src/main/resources/assets/academymonster/lang/zh_CN.lang index 987feb1..c822637 100644 --- a/src/main/resources/assets/academymonster/lang/zh_CN.lang +++ b/src/main/resources/assets/academymonster/lang/zh_CN.lang @@ -3,4 +3,6 @@ am.app.aim_scanner_skill_list.name=技能列表: ac.settings.prop.open_aim_scanner=开启AIM扫描仪 am.aim_scanner_skill_list.notinstalled=你还没有安装AIM扫描仪 ac.app.aim_scanner.name=AIM扫描仪 -ac.ability.MineRay.name=采矿光束 \ No newline at end of file +ac.ability.MineRay.name=采矿光束 + +entity.academy-monster.am_fake_railgun.name=自称的超电磁炮者 \ No newline at end of file diff --git a/src/main/resources/assets/academymonster/textures/gui/hp_bar.png b/src/main/resources/assets/academymonster/textures/gui/hp_bar.png new file mode 100644 index 0000000..00831e6 Binary files /dev/null and b/src/main/resources/assets/academymonster/textures/gui/hp_bar.png differ