Mass-deletion of enemy code
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package io.anuke.mindustry.entities;
|
||||
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.BaseUnit;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.entities.BulletEntity;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
@@ -37,7 +37,7 @@ public class Bullet extends BulletEntity{
|
||||
}
|
||||
|
||||
public boolean collidesTiles(){
|
||||
return owner instanceof Enemy;
|
||||
return owner instanceof BaseUnit;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.anuke.mindustry.entities;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import io.anuke.mindustry.entities.effect.DamageArea;
|
||||
import io.anuke.mindustry.entities.effect.EMP;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.BaseUnit;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
@@ -122,7 +122,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
|
||||
Effects.effect(Fx.shellsmoke, b);
|
||||
Effects.effect(Fx.shellexplosion, b);
|
||||
|
||||
DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 25f, (int)(damage * 2f/3f));
|
||||
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 25f, (int)(damage * 2f/3f));
|
||||
}
|
||||
},
|
||||
flak = new BulletType(2.9f, 8) {
|
||||
@@ -202,7 +202,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
|
||||
Effects.effect(Fx.shellsmoke, b);
|
||||
Effects.effect(Fx.shockwaveSmall, b);
|
||||
|
||||
DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 50f, (int)(damage * 2f/3f));
|
||||
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 50f, (int)(damage * 2f/3f));
|
||||
}
|
||||
},
|
||||
yellowshell = new BulletType(1.2f, 20){
|
||||
@@ -233,7 +233,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
|
||||
Effects.effect(Fx.shellsmoke, b);
|
||||
Effects.effect(Fx.shockwaveSmall, b);
|
||||
|
||||
DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 25f, (int)(damage * 2f/3f));
|
||||
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 25f, (int)(damage * 2f/3f));
|
||||
}
|
||||
},
|
||||
blast = new BulletType(1.1f, 90){
|
||||
@@ -371,7 +371,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
|
||||
|
||||
Effects.effect(Fx.clusterbomb, b);
|
||||
|
||||
DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 35f, damage);
|
||||
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 35f, damage);
|
||||
}
|
||||
},
|
||||
vulcan = new BulletType(4.5f, 12) {
|
||||
|
||||
@@ -23,17 +23,14 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Player extends SyncEntity{
|
||||
public class Player extends Unit{
|
||||
static final float speed = 1.1f;
|
||||
static final float dashSpeed = 1.8f;
|
||||
|
||||
static final int timerDash = 0;
|
||||
static final int timerShootLeft = 1;
|
||||
static final int timerShootRight = 2;
|
||||
static final int timerRegen = 3;
|
||||
|
||||
public String name = "name";
|
||||
public boolean isAndroid;
|
||||
public boolean isAdmin;
|
||||
public Color color = new Color();
|
||||
|
||||
@@ -60,9 +57,14 @@ public class Player extends SyncEntity{
|
||||
heal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMass(){
|
||||
return mech.mass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(int amount){
|
||||
if(debug || isAndroid) return;
|
||||
if(debug || mech.flying) return;
|
||||
|
||||
health -= amount;
|
||||
if(health <= 0 && !dead && isLocal){ //remote players don't die normally
|
||||
@@ -79,7 +81,7 @@ public class Player extends SyncEntity{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !isDead() && super.collides(other) && !isAndroid;
|
||||
return !isDead() && super.collides(other) && !mech.flying;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,34 +115,33 @@ public class Player extends SyncEntity{
|
||||
|
||||
@Override
|
||||
public void drawSmooth(){
|
||||
if((debug && (!showPlayer || !showUI)) || (isAndroid && isLocal) || dead) return;
|
||||
if((debug && (!showPlayer || !showUI)) || dead) return;
|
||||
boolean snap = snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate") && isLocal;
|
||||
|
||||
String part = isAndroid ? "ship" : "mech";
|
||||
String mname = "mech-" + mech.name;
|
||||
|
||||
Shaders.outline.color.set(getColor());
|
||||
Shaders.outline.lighten = 0f;
|
||||
Shaders.outline.region = Draw.region(part + "-" + mech.name);
|
||||
Shaders.outline.region = Draw.region(mname);
|
||||
|
||||
Shaders.outline.apply();
|
||||
|
||||
if(!isAndroid) {
|
||||
for (int i : Mathf.signs) {
|
||||
Weapon weapon = i < 0 ? weaponLeft : weaponRight;
|
||||
tr.trns(angle - 90, 3*i, 2);
|
||||
float w = i > 0 ? -8 : 8;
|
||||
if(snap){
|
||||
Draw.rect(weapon.name + "-equip", (int)x + tr.x, (int)y + tr.y, w, 8, angle - 90);
|
||||
}else{
|
||||
Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, angle - 90);
|
||||
}
|
||||
for (int i : Mathf.signs) {
|
||||
Weapon weapon = i < 0 ? weaponLeft : weaponRight;
|
||||
tr.trns(rotation - 90, 3*i, 2);
|
||||
float w = i > 0 ? -8 : 8;
|
||||
if(snap){
|
||||
Draw.rect(weapon.name + "-equip", (int)x + tr.x, (int)y + tr.y, w, 8, rotation - 90);
|
||||
}else{
|
||||
Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, rotation - 90);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(snap){
|
||||
Draw.rect(part + "-" + mech.name, (int)x, (int)y, angle-90);
|
||||
Draw.rect(mname, (int)x, (int)y, rotation -90);
|
||||
}else{
|
||||
Draw.rect(part + "-" + mech.name, x, y, angle-90);
|
||||
Draw.rect(mname, x, y, rotation -90);
|
||||
}
|
||||
|
||||
Graphics.flush();
|
||||
@@ -148,16 +149,25 @@ public class Player extends SyncEntity{
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(!isLocal || isAndroid){
|
||||
if(isAndroid && isLocal){
|
||||
angle = Mathf.slerpDelta(angle, targetAngle, 0.2f);
|
||||
}
|
||||
if(!isLocal) interpolate();
|
||||
if(!isLocal){
|
||||
interpolate();
|
||||
return;
|
||||
}
|
||||
|
||||
if(isDead()) return;
|
||||
|
||||
if(mech.flying){
|
||||
updateFlying();
|
||||
}else{
|
||||
updateMech();
|
||||
}
|
||||
|
||||
x = Mathf.clamp(x, 0, world.width() * tilesize);
|
||||
y = Mathf.clamp(y, 0, world.height() * tilesize);
|
||||
}
|
||||
|
||||
protected void updateMech(){
|
||||
|
||||
Tile tile = world.tileWorld(x, y);
|
||||
|
||||
//if player is in solid block
|
||||
@@ -175,14 +185,14 @@ public class Player extends SyncEntity{
|
||||
if(ui.chatfrag.chatOpen()) return;
|
||||
|
||||
dashing = Inputs.keyDown("dash");
|
||||
|
||||
|
||||
float speed = dashing ? (debug ? Player.dashSpeed * 5f : Player.dashSpeed) : Player.speed;
|
||||
|
||||
|
||||
if(health < maxhealth && timer.get(timerRegen, 20))
|
||||
health ++;
|
||||
|
||||
health = Mathf.clamp(health, -1, maxhealth);
|
||||
|
||||
|
||||
movement.set(0, 0);
|
||||
|
||||
float xa = Inputs.getAxis("move_x");
|
||||
@@ -192,7 +202,7 @@ public class Player extends SyncEntity{
|
||||
|
||||
movement.y += ya*speed;
|
||||
movement.x += xa*speed;
|
||||
|
||||
|
||||
boolean shooting = !Inputs.keyDown("dash") && Inputs.keyDown("shoot") && control.input().recipe == null
|
||||
&& !ui.hasMouse() && !control.input().onConfigurable();
|
||||
|
||||
@@ -200,30 +210,31 @@ public class Player extends SyncEntity{
|
||||
weaponLeft.update(player, true);
|
||||
weaponRight.update(player, false);
|
||||
}
|
||||
|
||||
|
||||
if(dashing && timer.get(timerDash, 3) && movement.len() > 0){
|
||||
Effects.effect(Fx.dashsmoke, x + Angles.trnsx(angle + 180f, 3f), y + Angles.trnsy(angle + 180f, 3f));
|
||||
Effects.effect(Fx.dashsmoke, x + Angles.trnsx(rotation + 180f, 3f), y + Angles.trnsy(rotation + 180f, 3f));
|
||||
}
|
||||
|
||||
|
||||
movement.limit(speed);
|
||||
|
||||
|
||||
if(!noclip){
|
||||
move(movement.x*Timers.delta(), movement.y*Timers.delta());
|
||||
}else{
|
||||
x += movement.x*Timers.delta();
|
||||
y += movement.y*Timers.delta();
|
||||
}
|
||||
|
||||
|
||||
if(!shooting){
|
||||
if(!movement.isZero())
|
||||
angle = Mathf.slerpDelta(angle, movement.angle(), 0.13f);
|
||||
rotation = Mathf.slerpDelta(rotation, movement.angle(), 0.13f);
|
||||
}else{
|
||||
float angle = Angles.mouseAngle(x, y);
|
||||
this.angle = Mathf.slerpDelta(this.angle, angle, 0.1f);
|
||||
this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
x = Mathf.clamp(x, 0, world.width() * tilesize);
|
||||
y = Mathf.clamp(y, 0, world.height() * tilesize);
|
||||
protected void updateFlying(){
|
||||
rotation = Mathf.slerpDelta(rotation, targetAngle, 0.2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,7 +244,7 @@ public class Player extends SyncEntity{
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Player{" + id + ", android=" + isAndroid + ", local=" + isLocal + ", " + x + ", " + y + "}\n";
|
||||
return "Player{" + id + ", mech=" + mech.name + ", local=" + isLocal + ", " + x + ", " + y + "}\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -242,7 +253,7 @@ public class Player extends SyncEntity{
|
||||
buffer.put(name.getBytes());
|
||||
buffer.put(weaponLeft.id);
|
||||
buffer.put(weaponRight.id);
|
||||
buffer.put(isAndroid ? 1 : (byte)0);
|
||||
buffer.put(mech.id);
|
||||
buffer.put(isAdmin ? 1 : (byte)0);
|
||||
buffer.putInt(Color.rgba8888(color));
|
||||
buffer.putFloat(x);
|
||||
@@ -255,9 +266,9 @@ public class Player extends SyncEntity{
|
||||
byte[] n = new byte[nlength];
|
||||
buffer.get(n);
|
||||
name = new String(n);
|
||||
weaponLeft = (Weapon) Upgrade.getByID(buffer.get());
|
||||
weaponRight = (Weapon) Upgrade.getByID(buffer.get());
|
||||
isAndroid = buffer.get() == 1;
|
||||
weaponLeft = Upgrade.getByID(buffer.get());
|
||||
weaponRight = Upgrade.getByID(buffer.get());
|
||||
mech = Upgrade.getByID(buffer.get());
|
||||
isAdmin = buffer.get() == 1;
|
||||
color.set(buffer.getInt());
|
||||
x = buffer.getFloat();
|
||||
@@ -274,7 +285,7 @@ public class Player extends SyncEntity{
|
||||
data.putFloat(interpolator.target.x);
|
||||
data.putFloat(interpolator.target.y);
|
||||
}
|
||||
data.putFloat(angle);
|
||||
data.putFloat(rotation);
|
||||
data.putShort((short)health);
|
||||
data.put((byte)(dashing ? 1 : 0));
|
||||
}
|
||||
@@ -299,10 +310,10 @@ public class Player extends SyncEntity{
|
||||
|
||||
Interpolator i = interpolator;
|
||||
|
||||
float tx = x + Angles.trnsx(angle + 180f, 4f);
|
||||
float ty = y + Angles.trnsy(angle + 180f, 4f);
|
||||
float tx = x + Angles.trnsx(rotation + 180f, 4f);
|
||||
float ty = y + Angles.trnsy(rotation + 180f, 4f);
|
||||
|
||||
if(isAndroid && i.target.dst(i.last) > 2f && timer.get(timerDash, 1)){
|
||||
if(mech.flying && i.target.dst(i.last) > 2f && timer.get(timerDash, 1)){
|
||||
Effects.effect(Fx.dashsmoke, tx, ty);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@ package io.anuke.mindustry.entities;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.utils.ObjectIntMap;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
@@ -14,24 +12,13 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import static io.anuke.mindustry.Vars.threads;
|
||||
|
||||
/**Base class for any entity that needs to be synced across clients.*/
|
||||
public abstract class SyncEntity extends DestructibleEntity{
|
||||
private static ObjectIntMap<Class<? extends SyncEntity>> writeSizes = new ObjectIntMap<>();
|
||||
|
||||
protected transient Interpolator interpolator = new Interpolator();
|
||||
|
||||
//smoothed position/angle
|
||||
/**smoothed position and rotation*/
|
||||
private Vector3 spos = new Vector3();
|
||||
|
||||
public float angle;
|
||||
|
||||
static{
|
||||
setWriteSize(Enemy.class, 4 + 4 + 2 + 2);
|
||||
setWriteSize(Player.class, 4 + 4 + 4 + 2 + 1);
|
||||
}
|
||||
|
||||
public static boolean isSmoothing(){
|
||||
return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f;
|
||||
}
|
||||
/**the general rotation.*/
|
||||
public float rotation;
|
||||
|
||||
public abstract void writeSpawn(ByteBuffer data);
|
||||
public abstract void readSpawn(ByteBuffer data);
|
||||
@@ -39,56 +26,47 @@ public abstract class SyncEntity extends DestructibleEntity{
|
||||
public abstract void write(ByteBuffer data);
|
||||
public abstract void read(ByteBuffer data, long time);
|
||||
|
||||
/**Interpolate everything needed. Should be called in update() for non-local entities.*/
|
||||
public void interpolate(){
|
||||
interpolator.update();
|
||||
|
||||
x = interpolator.pos.x;
|
||||
y = interpolator.pos.y;
|
||||
angle = interpolator.angle;
|
||||
rotation = interpolator.rotation;
|
||||
}
|
||||
|
||||
/**Same as draw, but for interpolated drawing at low tick speeds.*/
|
||||
public abstract void drawSmooth();
|
||||
|
||||
/**Do not override, use drawSmooth instead.*/
|
||||
@Override
|
||||
public final void draw(){
|
||||
final float x = this.x, y = this.y, angle = this.angle;
|
||||
final float x = this.x, y = this.y, rotation = this.rotation;
|
||||
|
||||
//interpolates data at low tick speeds.
|
||||
if(isSmoothing()){
|
||||
if(Vector2.dst(spos.x, spos.y, x, y) > 128){
|
||||
spos.set(x, y, angle);
|
||||
spos.set(x, y, rotation);
|
||||
}
|
||||
|
||||
this.x = spos.x = Mathf.lerpDelta(spos.x, x, 0.2f);
|
||||
this.y = spos.y = Mathf.lerpDelta(spos.y, y, 0.2f);
|
||||
this.angle = spos.z = Mathf.slerpDelta(spos.z, angle, 0.3f);
|
||||
this.rotation = spos.z = Mathf.slerpDelta(spos.z, rotation, 0.3f);
|
||||
}
|
||||
|
||||
drawSmooth();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.angle = angle;
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
/**Returns smoothed position. x = x, y = y, z = rotation.*/
|
||||
public Vector3 getDrawPosition(){
|
||||
return isSmoothing() ? spos : spos.set(x, y, angle);
|
||||
}
|
||||
|
||||
public void drawSmooth(){}
|
||||
|
||||
public int getWriteSize(){
|
||||
return getWriteSize(getClass());
|
||||
}
|
||||
|
||||
public static int getWriteSize(Class<? extends SyncEntity> type){
|
||||
int i = writeSizes.get(type, -1);
|
||||
if(i == -1) throw new RuntimeException("Write size for class \"" + type + "\" is not defined!");
|
||||
return i;
|
||||
}
|
||||
|
||||
protected static void setWriteSize(Class<? extends SyncEntity> type, int size){
|
||||
writeSizes.put(type, size);
|
||||
return isSmoothing() ? spos : spos.set(x, y, rotation);
|
||||
}
|
||||
|
||||
/**Set position and interpolator position.*/
|
||||
public <T extends SyncEntity> T setNet(float x, float y){
|
||||
set(x, y);
|
||||
interpolator.target.set(x, y);
|
||||
@@ -98,6 +76,10 @@ public abstract class SyncEntity extends DestructibleEntity{
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
private static boolean isSmoothing(){
|
||||
return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f;
|
||||
}
|
||||
|
||||
public static class Interpolator {
|
||||
//used for movement
|
||||
public Vector2 target = new Vector2();
|
||||
@@ -108,7 +90,7 @@ public abstract class SyncEntity extends DestructibleEntity{
|
||||
|
||||
//current state
|
||||
public Vector2 pos = new Vector2();
|
||||
public float angle;
|
||||
public float rotation;
|
||||
|
||||
public void read(float cx, float cy, float x, float y, float angle, long sent){
|
||||
targetrot = angle;
|
||||
@@ -124,7 +106,7 @@ public abstract class SyncEntity extends DestructibleEntity{
|
||||
|
||||
Mathf.lerp2(pos.set(last), target, time);
|
||||
|
||||
angle = Mathf.slerpDelta(angle, targetrot, 0.6f);
|
||||
rotation = Mathf.slerpDelta(rotation, targetrot, 0.6f);
|
||||
|
||||
if(target.dst(pos) > 128){
|
||||
pos.set(target);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.anuke.mindustry.entities;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
|
||||
public abstract class Unit extends SyncEntity {
|
||||
//total duration of hit effect
|
||||
public static final float hitDuration = 5f;
|
||||
|
||||
public Team team = Team.blue;
|
||||
public Vector2 velocity = new Vector2();
|
||||
public float hitTime;
|
||||
|
||||
public abstract float getMass();
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class DamageArea{
|
||||
rect.height += expand*2;
|
||||
|
||||
Consumer<SolidEntity> cons = e -> {
|
||||
if(e == owner || (e instanceof Player && ((Player)e).isAndroid)) return;
|
||||
if(e == owner) return;
|
||||
DestructibleEntity enemy = (DestructibleEntity) e;
|
||||
Rectangle other = enemy.hitbox.getRect(enemy.x, enemy.y);
|
||||
other.y -= expand;
|
||||
@@ -69,7 +69,7 @@ public class DamageArea{
|
||||
damage(true, x, y, radius, damage);
|
||||
|
||||
for(Player player : playerGroup.all()){
|
||||
if(player.isAndroid) continue;
|
||||
//if(player.isAndroid) continue;
|
||||
int amount = calculateDamage(x, y, player.x, player.y, radius, damage);
|
||||
player.damage(amount);
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class DamageArea{
|
||||
public static void damage(boolean enemies, float x, float y, float radius, int damage){
|
||||
Consumer<SolidEntity> cons = entity -> {
|
||||
DestructibleEntity enemy = (DestructibleEntity)entity;
|
||||
if(enemy.distanceTo(x, y) > radius || (entity instanceof Player && ((Player)entity).isAndroid)){
|
||||
if(enemy.distanceTo(x, y) > radius){
|
||||
return;
|
||||
}
|
||||
int amount = calculateDamage(x, y, enemy.x, enemy.y, radius, damage);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.anuke.mindustry.entities.effect;
|
||||
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.BaseUnit;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.types.defense.ShieldBlock;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
@@ -55,7 +55,7 @@ public class Shield extends Entity{
|
||||
|
||||
Entities.getNearby(bulletGroup, x, y, block.shieldRadius * 2*uptime + 10, entity->{
|
||||
BulletEntity bullet = (BulletEntity)entity;
|
||||
if((bullet.owner instanceof Enemy || hitPlayers)){
|
||||
if((bullet.owner instanceof BaseUnit || hitPlayers)){
|
||||
|
||||
float dst = entity.distanceTo(this);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.BaseUnit;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
@@ -19,7 +19,7 @@ import static io.anuke.mindustry.Vars.enemyGroup;
|
||||
|
||||
public class TeslaOrb extends Entity{
|
||||
private Array<Vector2> points = new Array<>();
|
||||
private ObjectSet<Enemy> hit = new ObjectSet<>();
|
||||
private ObjectSet<BaseUnit> hit = new ObjectSet<>();
|
||||
private int damage = 0;
|
||||
private float range = 0;
|
||||
private float lifetime = 30f;
|
||||
@@ -47,10 +47,10 @@ public class TeslaOrb extends Entity{
|
||||
Array<SolidEntity> enemies = Entities.getNearby(enemyGroup, curx, cury, range*2f);
|
||||
|
||||
for(SolidEntity entity : enemies){
|
||||
if(entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((Enemy)entity)){
|
||||
hit.add((Enemy)entity);
|
||||
if(entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){
|
||||
hit.add((BaseUnit)entity);
|
||||
points.add(new Vector2(entity.x + Mathf.range(shake), entity.y + Mathf.range(shake)));
|
||||
damageEnemy((Enemy)entity);
|
||||
damageEnemy((BaseUnit)entity);
|
||||
curx = entity.x;
|
||||
cury = entity.y;
|
||||
break;
|
||||
@@ -63,7 +63,7 @@ public class TeslaOrb extends Entity{
|
||||
}
|
||||
}
|
||||
|
||||
void damageEnemy(Enemy enemy){
|
||||
void damageEnemy(BaseUnit enemy){
|
||||
enemy.damage(damage);
|
||||
Effects.effect(Fx.laserhit, enemy.x + Mathf.range(2f), enemy.y + Mathf.range(2f));
|
||||
}
|
||||
|
||||
+15
-62
@@ -1,50 +1,31 @@
|
||||
package io.anuke.mindustry.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetEvents;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.SolidEntity;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static io.anuke.mindustry.Vars.enemyGroup;
|
||||
|
||||
public class Enemy extends SyncEntity {
|
||||
public EnemyType type;
|
||||
|
||||
public class BaseUnit extends Unit {
|
||||
public UnitType type;
|
||||
public Timer timer = new Timer(5);
|
||||
public float idletime = 0f;
|
||||
public int lane;
|
||||
public int node = -1;
|
||||
|
||||
public Enemy spawner;
|
||||
public int spawned;
|
||||
|
||||
public Vector2 velocity = new Vector2();
|
||||
public Vector2 totalMove = new Vector2();
|
||||
public Vector2 tpos = new Vector2(-999, -999);
|
||||
public Entity target;
|
||||
public float hitTime;
|
||||
public int tier = 1;
|
||||
|
||||
public TextureRegion region;
|
||||
public Translator tr = new Translator();
|
||||
|
||||
public Enemy(EnemyType type){
|
||||
public BaseUnit(UnitType type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**internal constructor used for deserialization, DO NOT USE*/
|
||||
public Enemy(){}
|
||||
public BaseUnit(){}
|
||||
|
||||
@Override
|
||||
public float getMass() {
|
||||
return type.mass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
@@ -68,13 +49,13 @@ public class Enemy extends SyncEntity {
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidEntity other){
|
||||
return (other instanceof Bullet) && !(((Bullet) other).owner instanceof Enemy);
|
||||
return (other instanceof Bullet) && !(((Bullet) other).owner instanceof BaseUnit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(int amount){
|
||||
super.damage(amount);
|
||||
hitTime = EnemyType.hitDuration;
|
||||
hitTime = hitDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,22 +72,16 @@ public class Enemy extends SyncEntity {
|
||||
public void added(){
|
||||
hitbox.setSize(type.hitsize);
|
||||
hitboxTile.setSize(type.hitsizeTile);
|
||||
maxhealth = type.health * tier;
|
||||
region = Draw.region(type.name + "-t" + Mathf.clamp(tier, 1, 3));
|
||||
|
||||
heal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enemy add(){
|
||||
public BaseUnit add(){
|
||||
return add(enemyGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSpawn(ByteBuffer buffer) {
|
||||
buffer.put(type.id);
|
||||
buffer.put((byte)lane);
|
||||
buffer.put((byte)tier);
|
||||
buffer.putFloat(x);
|
||||
buffer.putFloat(y);
|
||||
buffer.putShort((short)health);
|
||||
@@ -114,9 +89,7 @@ public class Enemy extends SyncEntity {
|
||||
|
||||
@Override
|
||||
public void readSpawn(ByteBuffer buffer) {
|
||||
type = EnemyType.getByID(buffer.get());
|
||||
lane = buffer.get();
|
||||
tier = buffer.get();
|
||||
type = UnitType.getByID(buffer.get());
|
||||
x = buffer.getFloat();
|
||||
y = buffer.getFloat();
|
||||
health = buffer.getShort();
|
||||
@@ -127,38 +100,18 @@ public class Enemy extends SyncEntity {
|
||||
public void write(ByteBuffer data) {
|
||||
data.putFloat(x);
|
||||
data.putFloat(y);
|
||||
data.putShort((short)(angle*2));
|
||||
data.putShort((short)(rotation *2));
|
||||
data.putShort((short)health);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuffer data, long time) {
|
||||
|
||||
float x = data.getFloat();
|
||||
float y = data.getFloat();
|
||||
short angle = data.getShort();
|
||||
short health = data.getShort();
|
||||
|
||||
this.health = health;
|
||||
|
||||
interpolator.read(this.x, this.y, x, y, angle/2f, time);
|
||||
}
|
||||
|
||||
public void shoot(BulletType bullet){
|
||||
shoot(bullet, 0);
|
||||
}
|
||||
|
||||
public void shoot(BulletType bullet, float rotation){
|
||||
|
||||
if(!(Net.client())) {
|
||||
tr.trns(angle + rotation, type.length);
|
||||
Bullet out = new Bullet(bullet, this, x + tr.x, y + tr.y, this.angle + rotation).add();
|
||||
out.damage = (int) ((bullet.damage * (1 + (tier - 1) * 1f)));
|
||||
type.onShoot(this, bullet, rotation);
|
||||
|
||||
if(Net.server()){
|
||||
NetEvents.handleBullet(bullet, this, x + tr.x, y + tr.y, this.angle + rotation, (short)out.damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetEvents;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Strings;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class EnemyType {
|
||||
|
||||
//TODO documentation, comments
|
||||
private static byte lastid = 0;
|
||||
private static Array<EnemyType> types = new Array<>();
|
||||
|
||||
public final static Color[] tierColors = {
|
||||
Color.valueOf("ffe451"), Color.valueOf("f48e20"), Color.valueOf("ff6757"),
|
||||
Color.valueOf("ff2d86"), Color.valueOf("cb2dff"), Color.valueOf("362020") };
|
||||
public final static int maxtier = tierColors.length;
|
||||
public final static float maxIdleLife = 60f*2f; //2 seconds idle = death
|
||||
public final static float hitDuration = 5f;
|
||||
|
||||
public final String name;
|
||||
public final byte id;
|
||||
|
||||
protected int timeid;
|
||||
protected int health = 60;
|
||||
protected float hitsize = 5f;
|
||||
protected float hitsizeTile = 4f;
|
||||
protected float speed = 0.4f;
|
||||
protected float reload = 32;
|
||||
protected float range = 60;
|
||||
protected float length = 4;
|
||||
protected float rotatespeed = 0.1f;
|
||||
protected float turretrotatespeed = 0.2f;
|
||||
protected boolean alwaysRotate = false;
|
||||
protected BulletType bullet = BulletType.small;
|
||||
protected String shootsound = "enemyshoot";
|
||||
protected boolean targetCore = false;
|
||||
protected boolean stopNearCore = true;
|
||||
protected boolean targetClient = false;
|
||||
protected float mass = 1f;
|
||||
|
||||
protected final int timerTarget = timeid ++;
|
||||
protected final int timerReload = timeid ++;
|
||||
protected final int timerReset = timeid ++;
|
||||
|
||||
protected final Vector2 shift = new Vector2();
|
||||
protected final Vector2 move = new Vector2();
|
||||
protected final Vector2 calc = new Vector2();
|
||||
|
||||
public EnemyType(String name){
|
||||
this.id = lastid++;
|
||||
this.name = name;
|
||||
types.add(this);
|
||||
}
|
||||
|
||||
public void draw(Enemy enemy){
|
||||
Shaders.outline.color.set(tierColors[enemy.tier - 1]);
|
||||
Shaders.outline.lighten = Mathf.clamp(enemy.hitTime/hitDuration);
|
||||
Shaders.outline.region = enemy.region;
|
||||
|
||||
Shaders.outline.apply();
|
||||
|
||||
Draw.rect(enemy.region, enemy.x, enemy.y, enemy.angle - 90);
|
||||
Draw.color();
|
||||
|
||||
Graphics.flush();
|
||||
|
||||
if(isCalculating(enemy)){
|
||||
Draw.color(Color.SKY);
|
||||
Lines.polySeg(20, 0, 4, enemy.x, enemy.y, 11f, Timers.time() * 2f + enemy.id*52f);
|
||||
Lines.polySeg(20, 0, 4, enemy.x, enemy.y, 11f, Timers.time() * 2f + enemy.id*52f + 180f);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
if(showPaths){
|
||||
Draw.tscl(0.25f);
|
||||
Draw.text((int)enemy.idletime + " " + enemy.node + " " + enemy.id + "\n" + Strings.toFixed(enemy.totalMove.x, 2) + ", "
|
||||
+ Strings.toFixed(enemy.totalMove.x, 2), enemy.x, enemy.y);
|
||||
Draw.tscl(fontscale);
|
||||
}
|
||||
|
||||
Shaders.outline.lighten = 0f;
|
||||
}
|
||||
|
||||
public void drawOver(Enemy enemy){ }
|
||||
|
||||
public void update(Enemy enemy){
|
||||
float lastx = enemy.x, lasty = enemy.y;
|
||||
if(enemy.hitTime > 0){
|
||||
enemy.hitTime -= Timers.delta();
|
||||
}
|
||||
|
||||
if(enemy.lane >= world.getSpawns().size || enemy.lane < 0) enemy.lane = 0;
|
||||
|
||||
boolean waiting = enemy.lane >= world.getSpawns().size || enemy.lane < 0
|
||||
|| world.getSpawns().get(enemy.lane).pathTiles == null || enemy.node <= 0;
|
||||
|
||||
move(enemy);
|
||||
|
||||
enemy.velocity.set(enemy.x - lastx, enemy.y - lasty).scl(1f / Timers.delta());
|
||||
enemy.totalMove.add(enemy.velocity);
|
||||
|
||||
float minv = 0.07f;
|
||||
|
||||
if(enemy.timer.get(timerReset, 80)){
|
||||
enemy.totalMove.setZero();
|
||||
}
|
||||
|
||||
if(enemy.velocity.len() < minv && !waiting && enemy.target == null){
|
||||
enemy.idletime += Timers.delta();
|
||||
}else{
|
||||
enemy.idletime = 0;
|
||||
}
|
||||
|
||||
if(enemy.timer.getTime(timerReset) > 50 && enemy.totalMove.len() < 0.2f && !waiting && enemy.target == null){
|
||||
enemy.idletime = 999999f;
|
||||
}
|
||||
|
||||
Tile tile = world.tileWorld(enemy.x, enemy.y);
|
||||
if(tile != null && tile.floor().liquid && tile.block() == Blocks.air){
|
||||
enemy.damage(enemy.health+1); //drown
|
||||
}
|
||||
|
||||
if(Float.isNaN(enemy.angle)){
|
||||
enemy.angle = 0;
|
||||
}
|
||||
|
||||
if(enemy.target == null || alwaysRotate){
|
||||
enemy.angle = Mathf.slerpDelta(enemy.angle, enemy.velocity.angle(), rotatespeed);
|
||||
}else{
|
||||
enemy.angle = Mathf.slerpDelta(enemy.angle, enemy.angleTo(enemy.target), turretrotatespeed);
|
||||
}
|
||||
|
||||
enemy.x = Mathf.clamp(enemy.x, 0, world.width() * tilesize);
|
||||
enemy.y = Mathf.clamp(enemy.y, 0, world.height() * tilesize);
|
||||
}
|
||||
|
||||
public void move(Enemy enemy){
|
||||
if(Net.client()){
|
||||
enemy.interpolate();
|
||||
if(targetClient) updateTargeting(enemy, false);
|
||||
return;
|
||||
}
|
||||
|
||||
float speed = this.speed + 0.04f * enemy.tier;
|
||||
float range = this.range + enemy.tier * 5;
|
||||
|
||||
Tile core = world.getCore();
|
||||
|
||||
if(core == null) return;
|
||||
|
||||
if(enemy.idletime > maxIdleLife && enemy.node > 0){
|
||||
enemy.onDeath();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean nearCore = enemy.distanceTo(core.worldx(), core.worldy()) <= range - 18f && stopNearCore;
|
||||
Vector2 vec;
|
||||
|
||||
if(nearCore){
|
||||
vec = move.setZero();
|
||||
if(targetCore) enemy.target = core.entity;
|
||||
}else{
|
||||
vec = world.pathfinder().find(enemy);
|
||||
vec.sub(enemy.x, enemy.y).limit(speed);
|
||||
}
|
||||
|
||||
shift.setZero();
|
||||
float shiftRange = enemy.hitbox.width + 2f;
|
||||
float avoidRange = shiftRange + 4f;
|
||||
float attractRange = avoidRange + 7f;
|
||||
float avoidSpeed = this.speed/2.7f;
|
||||
|
||||
Entities.getNearby(enemyGroup, enemy.x, enemy.y, range, en -> {
|
||||
Enemy other = (Enemy)en;
|
||||
if(other == enemy) return;
|
||||
float dst = other.distanceTo(enemy);
|
||||
|
||||
if(dst < shiftRange){
|
||||
float scl = Mathf.clamp(1.4f - dst / shiftRange) * mass * 1f/mass;
|
||||
shift.add((enemy.x - other.x) * scl, (enemy.y - other.y) * scl);
|
||||
}else if(dst < avoidRange){
|
||||
calc.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed);
|
||||
shift.add(calc.scl(1.1f));
|
||||
}else if(dst < attractRange && !nearCore && !isCalculating(enemy)){
|
||||
calc.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed);
|
||||
shift.add(calc.scl(-1));
|
||||
}
|
||||
});
|
||||
|
||||
shift.limit(1f);
|
||||
vec.add(shift.scl(0.5f));
|
||||
|
||||
enemy.move(vec.x * Timers.delta(), vec.y * Timers.delta());
|
||||
|
||||
updateTargeting(enemy, nearCore);
|
||||
|
||||
behavior(enemy);
|
||||
}
|
||||
|
||||
public void behavior(Enemy enemy){}
|
||||
|
||||
public void updateTargeting(Enemy enemy, boolean nearCore){
|
||||
if(enemy.target != null && enemy.target instanceof TileEntity && ((TileEntity)enemy.target).dead){
|
||||
enemy.target = null;
|
||||
}
|
||||
|
||||
if(enemy.timer.get(timerTarget, 15) && !nearCore){
|
||||
enemy.target = world.findTileTarget(enemy.x, enemy.y, null, range, false);
|
||||
|
||||
//no tile found
|
||||
if(enemy.target == null){
|
||||
enemy.target = Entities.getClosest(playerGroup, enemy.x, enemy.y, range, e -> !((Player)e).isAndroid &&
|
||||
!((Player)e).isDead());
|
||||
}
|
||||
}else if(nearCore){
|
||||
enemy.target = world.getCore().entity;
|
||||
}
|
||||
|
||||
if(enemy.target != null && bullet != null){
|
||||
updateShooting(enemy);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateShooting(Enemy enemy){
|
||||
float reload = this.reload / Math.max(enemy.tier / 1.5f, 1f);
|
||||
|
||||
if(enemy.timer.get(timerReload, reload)){
|
||||
shoot(enemy);
|
||||
}
|
||||
}
|
||||
|
||||
public void shoot(Enemy enemy){
|
||||
enemy.shoot(bullet);
|
||||
if(shootsound != null) Effects.sound(shootsound, enemy);
|
||||
}
|
||||
|
||||
public void onShoot(Enemy enemy, BulletType type, float rotation){}
|
||||
|
||||
public void onDeath(Enemy enemy, boolean force){
|
||||
if(Net.server()){
|
||||
NetEvents.handleEnemyDeath(enemy);
|
||||
}
|
||||
|
||||
if(!Net.client() || force) {
|
||||
Effects.effect(Fx.explosion, enemy);
|
||||
Effects.shake(3f, 4f, enemy);
|
||||
Effects.sound("bang2", enemy);
|
||||
enemy.remove();
|
||||
enemy.dead = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void removed(Enemy enemy){
|
||||
if(!enemy.dead){
|
||||
if(enemy.spawner != null){
|
||||
enemy.spawner.spawned --;
|
||||
}else{
|
||||
state.enemies --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCalculating(Enemy enemy){
|
||||
return enemy.node < 0 && !Net.client();
|
||||
}
|
||||
|
||||
public static EnemyType getByID(byte id){
|
||||
return types.get(id);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies;
|
||||
|
||||
import io.anuke.mindustry.entities.enemies.types.BlastType;
|
||||
import io.anuke.mindustry.entities.enemies.types.EmpType;
|
||||
import io.anuke.mindustry.entities.enemies.types.FastType;
|
||||
import io.anuke.mindustry.entities.enemies.types.FlamerType;
|
||||
import io.anuke.mindustry.entities.enemies.types.FortressType;
|
||||
import io.anuke.mindustry.entities.enemies.types.HealerType;
|
||||
import io.anuke.mindustry.entities.enemies.types.MortarType;
|
||||
import io.anuke.mindustry.entities.enemies.types.RapidType;
|
||||
import io.anuke.mindustry.entities.enemies.types.*;
|
||||
import io.anuke.mindustry.entities.enemies.types.TankType;
|
||||
import io.anuke.mindustry.entities.enemies.types.TargetType;
|
||||
import io.anuke.mindustry.entities.enemies.types.TitanType;
|
||||
|
||||
public class EnemyTypes {
|
||||
public static final EnemyType
|
||||
|
||||
standard = new StandardType(),
|
||||
fast = new FastType(),
|
||||
rapid = new RapidType(),
|
||||
flamer = new FlamerType(),
|
||||
tank = new TankType(),
|
||||
blast = new BlastType(),
|
||||
mortar = new MortarType(),
|
||||
healer = new HealerType(),
|
||||
titan = new TitanType(),
|
||||
emp = new EmpType(),
|
||||
fortress = new FortressType(),
|
||||
target = new TargetType();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package io.anuke.mindustry.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class UnitType {
|
||||
private static byte lastid = 0;
|
||||
private static Array<UnitType> types = new Array<>();
|
||||
|
||||
public final String name;
|
||||
public final byte id;
|
||||
|
||||
protected int health = 60;
|
||||
protected float hitsize = 5f;
|
||||
protected float hitsizeTile = 4f;
|
||||
protected float speed = 0.4f;
|
||||
protected float range = 60;
|
||||
protected float rotatespeed = 0.1f;
|
||||
protected float mass = 1f;
|
||||
protected boolean isFlying;
|
||||
|
||||
public UnitType(String name){
|
||||
this.id = lastid++;
|
||||
this.name = name;
|
||||
types.add(this);
|
||||
}
|
||||
|
||||
public void draw(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void drawOver(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void update(BaseUnit enemy){
|
||||
//TODO
|
||||
enemy.x = Mathf.clamp(enemy.x, 0, world.width() * tilesize);
|
||||
enemy.y = Mathf.clamp(enemy.y, 0, world.height() * tilesize);
|
||||
}
|
||||
|
||||
public void move(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void behavior(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void updateTargeting(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void updateShooting(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void shoot(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void onShoot(BaseUnit enemy, BulletType type, float rotation){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void onDeath(BaseUnit enemy, boolean force){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void removed(BaseUnit enemy){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public static UnitType getByID(byte id){
|
||||
return types.get(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package io.anuke.mindustry.entities.enemies;
|
||||
|
||||
public class UnitTypes {
|
||||
//TODO list types here.
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
|
||||
public class BlastType extends EnemyType {
|
||||
|
||||
public BlastType() {
|
||||
super("blastenemy");
|
||||
health = 30;
|
||||
speed = 0.8f;
|
||||
bullet = null;
|
||||
turretrotatespeed = 0f;
|
||||
mass = 0.8f;
|
||||
stopNearCore = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void behavior(Enemy enemy){
|
||||
|
||||
float range = 10f;
|
||||
float ox = 0, oy = 0;
|
||||
|
||||
if(enemy.target instanceof TileEntity){
|
||||
TileEntity e = (TileEntity)enemy.target;
|
||||
range = (e.tile.block().size * tilesize) /2f + 8f;
|
||||
ox = e.tile.block().getPlaceOffset().x;
|
||||
oy = e.tile.block().getPlaceOffset().y;
|
||||
}
|
||||
|
||||
if(enemy.target != null && enemy.target.distanceTo(enemy.x - ox, enemy.y - oy) < range){
|
||||
explode(enemy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(Enemy enemy, boolean force){
|
||||
if(force) explode(enemy);
|
||||
super.onDeath(enemy, force);
|
||||
}
|
||||
|
||||
void explode(Enemy enemy){
|
||||
Bullet b = new Bullet(BulletType.blast, enemy, enemy.x, enemy.y, 0).add();
|
||||
b.damage = BulletType.blast.damage + (enemy.tier-1) * 40;
|
||||
enemy.damage(999);
|
||||
enemy.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
public class EmpType extends EnemyType {
|
||||
|
||||
public EmpType() {
|
||||
super("empenemy");
|
||||
|
||||
speed = 0.3f;
|
||||
reload = 70;
|
||||
health = 210;
|
||||
range = 80f;
|
||||
bullet = BulletType.emp;
|
||||
turretrotatespeed = 0.1f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
public class FastType extends EnemyType {
|
||||
|
||||
public FastType() {
|
||||
super("fastenemy");
|
||||
|
||||
speed = 0.73f;
|
||||
reload = 20;
|
||||
mass = 0.2f;
|
||||
|
||||
health = 50;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
public class FlamerType extends EnemyType {
|
||||
|
||||
public FlamerType() {
|
||||
super("flamerenemy");
|
||||
|
||||
speed = 0.35f;
|
||||
health = 150;
|
||||
reload = 6;
|
||||
bullet = BulletType.flameshot;
|
||||
shootsound = "flame";
|
||||
mass = 1.5f;
|
||||
range = 40;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyTypes;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class FortressType extends EnemyType {
|
||||
final int maxSpawn = 6;
|
||||
final float spawnTime = 190;
|
||||
|
||||
public FortressType() {
|
||||
super("fortressenemy");
|
||||
|
||||
speed = 0.25f;
|
||||
reload = 90;
|
||||
health = 700;
|
||||
range = 70f;
|
||||
bullet = BulletType.yellowshell;
|
||||
hitsize = 10f;
|
||||
turretrotatespeed = rotatespeed = 0.08f;
|
||||
length = 7f;
|
||||
mass = 7f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void behavior(Enemy enemy){
|
||||
if(enemy.distanceTo(world.getCore().worldx(),
|
||||
world.getCore().worldy()) <= 90f){
|
||||
|
||||
if(Timers.get(this, "spawn", spawnTime) && enemy.spawned < maxSpawn){
|
||||
enemy.tr.trns(enemy.angle, 20f);
|
||||
|
||||
Enemy s = new Enemy(EnemyTypes.fast);
|
||||
s.lane = enemy.lane;
|
||||
s.tier = enemy.tier;
|
||||
s.spawner = enemy;
|
||||
s.set(enemy.x + enemy.tr.x, enemy.y + enemy.tr.y);
|
||||
s.add();
|
||||
|
||||
Effects.effect(Fx.spawn, enemy);
|
||||
enemy.spawned ++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onShoot(Enemy enemy, BulletType type, float rotation){
|
||||
Effects.effect(Fx.largeCannonShot, enemy.x + enemy.tr.x, enemy.y + enemy.tr.y, enemy.angle);
|
||||
Effects.shake(3f, 3f, enemy);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.graphics.Shapes;
|
||||
|
||||
import static io.anuke.mindustry.Vars.enemyGroup;
|
||||
|
||||
public class HealerType extends EnemyType {
|
||||
|
||||
public HealerType() {
|
||||
super("healerenemy");
|
||||
speed = 0.25f;
|
||||
reload = 10;
|
||||
health = 200;
|
||||
bullet = BulletType.shot;
|
||||
range = 40f;
|
||||
alwaysRotate = false;
|
||||
targetCore = false;
|
||||
stopNearCore = true;
|
||||
targetClient = true;
|
||||
mass = 1.1f;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void behavior(Enemy enemy){
|
||||
|
||||
if(enemy.idletime > 60f*3){ //explode after 3 seconds of stillness
|
||||
explode(enemy);
|
||||
Effects.effect(Fx.shellexplosion, enemy);
|
||||
Effects.effect(Fx.shellsmoke, enemy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTargeting(Enemy enemy, boolean nearCore){
|
||||
if(enemy.timer.get(timerTarget, 15)){
|
||||
enemy.target = Entities.getClosest(enemyGroup,
|
||||
enemy.x, enemy.y, range, e -> e instanceof Enemy && e != enemy && ((Enemy)e).healthfrac() < 1f);
|
||||
}
|
||||
|
||||
if(enemy.target != null){
|
||||
updateShooting(enemy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateShooting(Enemy enemy){
|
||||
Enemy target = (Enemy)enemy.target;
|
||||
|
||||
if(target.health < target.maxhealth && enemy.timer.get(timerReload, reload)){
|
||||
target.health ++;
|
||||
enemy.idletime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOver(Enemy enemy){
|
||||
Enemy target = (Enemy)enemy.target;
|
||||
|
||||
if(target == null) return;
|
||||
|
||||
enemy.tr.trns(enemy.angleTo(target), 5f);
|
||||
|
||||
Shaders.outline.color.set(Color.CLEAR);
|
||||
Shaders.outline.apply();
|
||||
|
||||
if(target.health < target.maxhealth){
|
||||
Draw.color(Hue.rgb(138, 244, 138, (MathUtils.sin(Timers.time()) + 1f) / 13f));
|
||||
Draw.alpha(0.9f);
|
||||
Shapes.laser("laser", "laserend", enemy.x + enemy.tr.x, enemy.y + enemy.tr.y, target.x - enemy.tr.x/1.5f, target.y - enemy.tr.y/1.5f);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
Graphics.flush();
|
||||
}
|
||||
|
||||
void explode(Enemy enemy){
|
||||
Bullet b = new Bullet(BulletType.blast, enemy, enemy.x, enemy.y, 0).add();
|
||||
b.damage = BulletType.blast.damage + (enemy.tier-1) * 30;
|
||||
enemy.damage(999);
|
||||
enemy.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
public class MortarType extends EnemyType {
|
||||
|
||||
public MortarType() {
|
||||
super("mortarenemy");
|
||||
|
||||
health = 200;
|
||||
speed = 0.25f;
|
||||
reload = 100f;
|
||||
bullet = BulletType.shell;
|
||||
turretrotatespeed = 0.15f;
|
||||
rotatespeed = 0.05f;
|
||||
range = 120f;
|
||||
mass = 1.2f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
public class RapidType extends EnemyType {
|
||||
|
||||
public RapidType() {
|
||||
super("rapidenemy");
|
||||
|
||||
reload = 8;
|
||||
bullet = BulletType.purple;
|
||||
rotatespeed = 0.08f;
|
||||
health = 260;
|
||||
speed = 0.33f;
|
||||
hitsize = 8f;
|
||||
mass = 3f;
|
||||
range = 70;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
|
||||
public class StandardType extends EnemyType {
|
||||
|
||||
public StandardType(){
|
||||
super("standardenemy");
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
|
||||
public class TankType extends EnemyType {
|
||||
|
||||
public TankType() {
|
||||
super("tankenemy");
|
||||
|
||||
health = 350;
|
||||
speed = 0.24f;
|
||||
reload = 90f;
|
||||
rotatespeed = 0.06f;
|
||||
bullet = BulletType.small;
|
||||
length = 3f;
|
||||
mass = 1.4f;
|
||||
length = 8f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shoot(Enemy enemy){
|
||||
super.shoot(enemy);
|
||||
|
||||
Angles.shotgun(3, 8f, enemy.angle, f -> enemy.shoot(bullet, f));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyTypes;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.control;
|
||||
|
||||
public class TargetType extends EnemyType {
|
||||
|
||||
public TargetType(){
|
||||
super("targetenemy");
|
||||
|
||||
speed = 0f;
|
||||
health = 40;
|
||||
shootsound = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(Enemy enemy){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shoot(Enemy enemy){
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(Enemy enemy){
|
||||
//don't call enemy death since this is only a target
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Enemy enemy){
|
||||
super.draw(enemy);
|
||||
|
||||
Draw.color(Color.YELLOW);
|
||||
|
||||
if(control.tutorial().showTarget()){
|
||||
Lines.spikes(enemy.x, enemy.y, 11f + Mathf.sin(Timers.time(), 7f, 1f), 4f, 8, Timers.time());
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(Enemy enemy, boolean force){
|
||||
super.onDeath(enemy, force);
|
||||
Timers.run(100f, ()->{
|
||||
new Enemy(EnemyTypes.target).set(enemy.x, enemy.y).add();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCalculating(Enemy enemy){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package io.anuke.mindustry.entities.enemies.types;
|
||||
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class TitanType extends EnemyType {
|
||||
|
||||
public TitanType() {
|
||||
super("titanenemy");
|
||||
|
||||
speed = 0.26f;
|
||||
reload = 30;
|
||||
health = 430;
|
||||
range = 60f;
|
||||
bullet = BulletType.small;
|
||||
hitsize = 7f;
|
||||
mass = 4f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateShooting(Enemy enemy){
|
||||
Timers.get(enemy, "salvo", 240);
|
||||
|
||||
if(Timers.getTime(enemy, "salvo") < 60){
|
||||
if(Timers.get(enemy, "salvoShoot", 6)){
|
||||
enemy.shoot(BulletType.flameshot, Mathf.range(20f));
|
||||
}
|
||||
}
|
||||
|
||||
if(Timers.get(enemy, "shotgun", 80)){
|
||||
Angles.shotgun(5, 10f, 0f, f->{
|
||||
enemy.shoot(BulletType.smallSlow, f);
|
||||
});
|
||||
}
|
||||
|
||||
if(Timers.get(enemy, "circle", 200)){
|
||||
Angles.circle(8, f->{
|
||||
enemy.shoot(BulletType.smallSlow, f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user