Mass-deletion of enemy code

This commit is contained in:
Anuken
2018-03-14 18:02:35 -04:00
parent a023c4fbac
commit 1cd30e9057
56 changed files with 313 additions and 1271 deletions

View File

@@ -4,7 +4,7 @@
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Tile" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.Maps" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.Player" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.enemies.Enemy" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.enemies.BaseUnit" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Map" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.EnemySpawn" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.core.GameState" />

View File

@@ -9,7 +9,7 @@ import io.anuke.mindustry.entities.Bullet;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.effect.Shield;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.net.ClientDebug;
import io.anuke.mindustry.net.ServerDebug;
@@ -136,7 +136,7 @@ public class Vars{
public static Player player;
public static final EntityGroup<Player> playerGroup = Entities.addGroup(Player.class).enableMapping();
public static final EntityGroup<Enemy> enemyGroup = Entities.addGroup(Enemy.class).enableMapping();
public static final EntityGroup<BaseUnit> enemyGroup = Entities.addGroup(BaseUnit.class).enableMapping();
public static final EntityGroup<TileEntity> tileGroup = Entities.addGroup(TileEntity.class, false);
public static final EntityGroup<Bullet> bulletGroup = Entities.addGroup(Bullet.class);
public static final EntityGroup<Shield> shieldGroup = Entities.addGroup(Shield.class, false);

View File

@@ -4,15 +4,14 @@ import com.badlogic.gdx.ai.pfa.PathFinderRequest;
import com.badlogic.gdx.ai.pfa.PathSmoother;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.state;
import static io.anuke.mindustry.Vars.world;
public class Pathfind{
/**Maximum time taken per frame on pathfinding for a single path.*/
@@ -33,91 +32,9 @@ public class Pathfind{
* If the path is not yet calculated, this returns the enemy's position (i. e. "don't move")
* @param enemy The enemy to find a path for
* @return The position the enemy should move to.*/
public Vector2 find(Enemy enemy){
//TODO fix -1/-2 node usage
if(enemy.node == -1 || enemy.node == -2){
findNode(enemy);
}
if(enemy.node == -2){
enemy.node = -1;
}
if(enemy.node < 0 || world.getSpawns().get(enemy.lane).pathTiles == null){
return vector.set(enemy.x, enemy.y);
}
Tile[] path = world.getSpawns().get(enemy.lane).pathTiles;
if(enemy.node >= path.length){
enemy.node = -1;
return vector.set(enemy.x, enemy.y);
}
if(enemy.node <= -1){
return vector.set(enemy.x, enemy.y);
}
//TODO documentation on what this does
Tile prev = path[enemy.node - 1];
Tile target = path[enemy.node];
//a bridge has been broken, re-path
if(!world.passable(target.x, target.y)){
remakePath();
return vector.set(enemy.x, enemy.y);
}
float projectLen = Vector2.dst(prev.worldx(), prev.worldy(), target.worldx(), target.worldy()) / 6f;
Vector2 projection = projectPoint(prev.worldx(), prev.worldy(),
target.worldx(), target.worldy(), enemy.x, enemy.y);
boolean canProject = true;
if(projectLen < 8 || !onLine(projection, prev.worldx(), prev.worldy(), target.worldx(), target.worldy())){
canProject = false;
}else{
projection.add(v1.set(projectLen, 0).rotate(Angles.angle(prev.worldx(), prev.worldy(),
target.worldx(), target.worldy())));
}
float dst = Vector2.dst(enemy.x, enemy.y, target.worldx(), target.worldy());
float nlinedist = enemy.node >= path.length - 1 ? 9999 :
pointLineDist(path[enemy.node].worldx(), path[enemy.node].worldy(),
path[enemy.node + 1].worldx(), path[enemy.node + 1].worldy(), enemy.x, enemy.y);
if(dst < 8 || nlinedist < 8){
if(enemy.node <= path.length-2)
enemy.node ++;
target = path[enemy.node];
}
if(canProject && projection.dst(enemy.x, enemy.y) < Vector2.dst(target.x, target.y, enemy.x, enemy.y)){
vector.set(projection);
}else{
vector.set(target.worldx(), target.worldy());
}
//near the core, stop
if(enemy.node == path.length - 1){
vector.set(target.worldx(), target.worldy());
}
return vector;
}
/**Re-calculate paths for all enemies. Runs when a path changes while moving.*/
private void remakePath(){
for(int i = 0; i < enemyGroup.size(); i ++){
Enemy enemy = enemyGroup.all().get(i);
enemy.node = -1;
}
resetPaths();
public Vector2 find(BaseUnit enemy){
//TODO!
return v1.set(enemy.x, enemy.y);
}
/**Update the pathfinders and continue calculating the path if it hasn't been calculated yet.
@@ -185,28 +102,6 @@ public class Pathfind{
point.request.statusChanged = true; //IMPORTANT!
}
/**For an enemy that was just loaded from a save, find the node in the path it should be following.*/
void findNode(Enemy enemy){
if(enemy.lane >= world.getSpawns().size || enemy.lane < 0){
enemy.lane = 0;
}
if(world.getSpawns().get(enemy.lane).pathTiles == null){
return;
}
Tile[] path = world.getSpawns().get(enemy.lane).pathTiles;
int closest = findClosest(path, enemy.x, enemy.y);
closest = Mathf.clamp(closest, 1, path.length-1);
if(closest == -1){
return;
}
enemy.node = closest;
}
/**Finds the closest tile to a position, in an array of tiles.*/
private int findClosest(Tile[] tiles, float x, float y){
int cindex = -2;

View File

@@ -17,6 +17,7 @@ import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.io.Saves;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.Mech;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.UCore;
@@ -132,7 +133,7 @@ public class Control extends Module{
player = new Player();
player.name = Settings.getString("name");
player.isAndroid = android;
player.mech = android ? Mech.standardShip : Mech.standard;
player.color.set(Settings.getInt("color"));
player.isLocal = true;

View File

@@ -2,25 +2,19 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.game.EnemySpawn;
import io.anuke.mindustry.game.EventType.GameOverEvent;
import io.anuke.mindustry.game.EventType.PlayEvent;
import io.anuke.mindustry.game.EventType.ResetEvent;
import io.anuke.mindustry.game.EventType.WaveEvent;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.game.WaveCreator;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
@@ -73,30 +67,7 @@ public class Logic extends Module {
}
for(EnemySpawn spawn : spawns){
Array<SpawnPoint> spawns = world.getSpawns();
for(int lane = 0; lane < spawns.size; lane ++){
int fl = lane;
Tile tile = spawns.get(lane).start;
int spawnamount = spawn.evaluate(state.wave, lane);
for(int i = 0; i < spawnamount; i ++){
float range = 12f;
Timers.runTask(i*5f, () -> {
Enemy enemy = new Enemy(spawn.type);
enemy.set(tile.worldx() + Mathf.range(range), tile.worldy() + Mathf.range(range));
enemy.lane = fl;
enemy.tier = spawn.tier(state.wave, fl);
enemy.add();
Effects.effect(Fx.spawn, enemy);
state.enemies ++;
});
}
}
//TODO spawn enemies for that spawnpoint
}
state.wave ++;

View File

@@ -9,7 +9,7 @@ import io.anuke.mindustry.entities.Bullet;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode;
@@ -139,7 +139,7 @@ public class NetClient extends Module {
SyncEntity entity = (SyncEntity) group.getByID(id);
if(entity instanceof Player) players ++;
if(entity instanceof Enemy) enemies ++;
if(entity instanceof BaseUnit) enemies ++;
if (entity == null || id == player.id) {
if (id != player.id) {
@@ -199,7 +199,7 @@ public class NetClient extends Module {
});
Net.handleClient(EnemyDeathPacket.class, packet -> {
Enemy enemy = enemyGroup.getByID(packet.id);
BaseUnit enemy = enemyGroup.getByID(packet.id);
if (enemy != null){
enemy.type.onDeath(enemy, true);
}else if(recent.get(packet.id) != null){

View File

@@ -85,7 +85,7 @@ public class NetServer extends Module{
player.isAdmin = admins.isAdmin(Net.getConnection(id).address);
player.clientid = id;
player.name = packet.name;
player.isAndroid = packet.android;
player.mech = packet.android ? Mech.standardShip : Mech.standard;
player.set(world.getSpawnX(), world.getSpawnY());
player.setNet(player.x, player.y);
player.setNet(player.x, player.y);
@@ -219,7 +219,7 @@ public class NetServer extends Module{
Net.handleServer(UpgradePacket.class, (id, packet) -> {
Player player = connections.get(id);
Weapon weapon = (Weapon) Upgrade.getByID(packet.id);
Weapon weapon = Upgrade.getByID(packet.id);
if (!weapons.containsKey(player.name)) weapons.put(player.name, new ByteArray());
if (!weapons.get(player.name).contains(weapon.id)) weapons.get(player.name).add(weapon.id);

View File

@@ -15,7 +15,7 @@ import com.badlogic.gdx.utils.Pools;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.graphics.BlockRenderer;
import io.anuke.mindustry.graphics.Shaders;
@@ -282,7 +282,7 @@ public class Renderer extends RendererModule{
Graphics.surface(indicatorSurface);
Draw.color(Color.RED);
for(Enemy enemy : enemyGroup.all()) {
for(BaseUnit enemy : enemyGroup.all()) {
if (rect.setSize(camera.viewportWidth, camera.viewportHeight).setCenter(camera.position.x, camera.position.y)
.overlaps(enemy.hitbox.getRect(enemy.x, enemy.y))) {
@@ -503,7 +503,7 @@ public class Renderer extends RendererModule{
if((!debug || showUI) && Settings.getBool("healthbars")){
//draw entity health bars
for(Enemy entity : enemyGroup.all()){
for(BaseUnit entity : enemyGroup.all()){
drawHealth(entity);
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,5 @@
package io.anuke.mindustry.entities.enemies;
public class UnitTypes {
//TODO list types here.
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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");
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
});
}
}
}

View File

@@ -1,13 +1,13 @@
package io.anuke.mindustry.game;
import io.anuke.mindustry.entities.enemies.EnemyType;
import io.anuke.mindustry.entities.enemies.UnitType;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.state;
public class EnemySpawn{
/**The enemy type spawned*/
public final EnemyType type;
public final UnitType type;
/**When this spawns should end*/
protected int before = Integer.MAX_VALUE;
/**When this spawns should start*/
@@ -27,7 +27,7 @@ public class EnemySpawn{
/**Amount of enemies spawned initially, with no scaling*/
protected int amount = 1;
public EnemySpawn(EnemyType type){
public EnemySpawn(UnitType type){
this.type = type;
}
@@ -41,6 +41,6 @@ public class EnemySpawn{
}
public int tier(int wave, int lane){
return Mathf.clamp(tier + (wave-after)/tierscale, 1, EnemyType.maxtier);
return Mathf.clamp(tier + (wave-after)/tierscale, 1, UnitType.maxtier);
}
}

View File

@@ -3,7 +3,7 @@ package io.anuke.mindustry.game;
import io.anuke.mindustry.core.GameState.State;
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.BaseUnit;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
@@ -41,7 +41,7 @@ public class EventType {
}
public interface EnemyDeathEvent extends Event{
void handle(Enemy enemy);
void handle(BaseUnit enemy);
}
public interface BlockDestroyEvent extends Event{

View File

@@ -0,0 +1,15 @@
package io.anuke.mindustry.game;
import com.badlogic.gdx.graphics.Color;
public enum Team {
none(Color.GRAY),
blue(Color.BLUE),
red(Color.RED);
public final Color color;
Team(Color color){
this.color = color;
}
}

View File

@@ -1,130 +1,12 @@
package io.anuke.mindustry.game;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.entities.enemies.EnemyTypes;
public class WaveCreator{
public static Array<EnemySpawn> getSpawns(){
return Array.with(
new EnemySpawn(EnemyTypes.standard){{
scaling = 1;
before = 3;
}},
new EnemySpawn(EnemyTypes.fast){{
scaling = 1;
after = 3;
spacing = 5;
amount = 3;
tierscaleback = 0;
}},
new EnemySpawn(EnemyTypes.blast){{
after = 4;
amount = 2;
spacing = 5;
scaling = 2;
tierscaleback = 1;
}},
new EnemySpawn(EnemyTypes.tank){{
after = 5;
spacing = 5;
scaling = 2;
amount = 2;
}},
new EnemySpawn(EnemyTypes.rapid){{
after = 7;
spacing = 5;
scaling = 2;
amount = 3;
}},
new EnemySpawn(EnemyTypes.healer){{
after = 5;
spacing = 5;
scaling = 1;
amount = 1;
}},
new EnemySpawn(EnemyTypes.standard){{
scaling = 3;
after = 8;
spacing = 4;
tier = 2;
}},
new EnemySpawn(EnemyTypes.titan){{
after = 6;
amount = 2;
spacing = 5;
scaling = 3;
}},
new EnemySpawn(EnemyTypes.flamer){{
after = 12;
amount = 2;
spacing = 5;
scaling = 3;
}},
new EnemySpawn(EnemyTypes.emp){{
after = 15;
amount = 1;
spacing = 5;
scaling = 2;
}},
new EnemySpawn(EnemyTypes.blast){{
after = 4 + 5 + 5;
amount = 3;
spacing = 5;
scaling = 2;
tierscaleback = 0;
}},
//boss wave
new EnemySpawn(EnemyTypes.fortress){{
after = 16;
amount = 1;
spacing = 5;
scaling = 1;
}},
new EnemySpawn(EnemyTypes.titan){{
after = 16;
amount = 1;
spacing = 5;
scaling = 3;
tierscaleback = 0;
}},
new EnemySpawn(EnemyTypes.healer){{
after = 16;
spacing = 5;
scaling = 2;
amount = 2;
}},
//end boss wave
//enchanced boss wave
new EnemySpawn(EnemyTypes.mortar){{
after = 16 + 5;
amount = 1;
spacing = 5;
scaling = 3;
}},
new EnemySpawn(EnemyTypes.emp){{
after = 16 + 5;
amount = 1;
spacing = 5;
scaling = 3;
}}
//end enchanced boss wave
);
//TODO
return null;
}
public static void testWaves(int from, int to){

View File

@@ -5,7 +5,6 @@ import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Layer;
@@ -86,10 +85,7 @@ public class BlockRenderer{
}
if(!(block instanceof StaticBlock)){
if(block == Blocks.air){
if(!state.is(State.paused)) tile.floor().update(tile);
}else{
if(block != Blocks.air){
if(!expanded){
addRequest(tile, Layer.block);
}

View File

@@ -3,8 +3,8 @@ package io.anuke.mindustry.io.versions;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.EnemyType;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.entities.enemies.UnitType;
import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.io.SaveFileVersion;
@@ -120,7 +120,7 @@ public class Save16 extends SaveFileVersion {
int enemies = stream.readInt();
Array<Enemy> enemiesToUpdate = new Array<>();
Array<BaseUnit> enemiesToUpdate = new Array<>();
for(int i = 0; i < enemies; i ++){
byte type = stream.readByte();
@@ -131,7 +131,7 @@ public class Save16 extends SaveFileVersion {
int health = stream.readShort();
try{
Enemy enemy = new Enemy(EnemyType.getByID(type));
BaseUnit enemy = new BaseUnit(UnitType.getByID(type));
enemy.lane = lane;
enemy.health = health;
enemy.x = x;
@@ -158,7 +158,7 @@ public class Save16 extends SaveFileVersion {
world.loadMap(world.maps().getMap(mapid), seed);
if(!headless) renderer.clearTiles();
for(Enemy enemy : enemiesToUpdate){
for(BaseUnit enemy : enemiesToUpdate){
enemy.node = -2;
}
@@ -278,12 +278,12 @@ public class Save16 extends SaveFileVersion {
//--ENEMIES--
EntityContainer<Enemy> enemies = enemyGroup.all();
EntityContainer<BaseUnit> enemies = enemyGroup.all();
stream.writeInt(enemies.size()); //enemy amount
for(int i = 0; i < enemies.size(); i ++){
Enemy enemy = enemies.get(i);
BaseUnit enemy = enemies.get(i);
stream.writeByte(enemy.type.id); //type
stream.writeByte(enemy.lane); //lane
stream.writeFloat(enemy.x); //x

View File

@@ -4,7 +4,7 @@ import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.resource.Weapon;
@@ -40,7 +40,7 @@ public class NetEvents {
Net.send(packet, SendMode.udp);
}
public static void handleEnemyDeath(Enemy enemy){
public static void handleEnemyDeath(BaseUnit enemy){
EnemyDeathPacket packet = new EnemyDeathPacket();
packet.id = enemy.id;
Net.send(packet, SendMode.tcp);

View File

@@ -34,8 +34,8 @@ public class ServerDebug {
build.append(player.clientid);
build.append(" / player '");
build.append(player.name);
build.append(" android: ");
build.append(player.isAndroid);
build.append(" mech: ");
build.append(player.mech);
build.append("'\n");
for(Class<?> type : map.orderedKeys()){

View File

@@ -3,9 +3,14 @@ package io.anuke.mindustry.resource;
public class Mech extends Upgrade{
public static final Mech
standard = new Mech("standard");
standard = new Mech("standard", false),
standardShip = new Mech("standard-ship", true);
public Mech(String name){
public boolean flying;
public float mass = 1f;
public Mech(String name, boolean flying){
super(name);
this.flying = flying;
}
}

View File

@@ -23,8 +23,8 @@ public abstract class Upgrade {
return Bundles.get("upgrade." + name + ".name");
}
public static Upgrade getByID(byte id){
return upgrades.get(id);
public static <T extends Upgrade> T getByID(byte id){
return (T)upgrades.get(id);
}
public static Array<Upgrade> getAllUpgrades() {

View File

@@ -3,8 +3,8 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.EnemyTypes;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.entities.enemies.UnitTypes;
import io.anuke.mindustry.net.Net;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.builders.button;
@@ -67,7 +67,7 @@ public class DebugFragment implements Fragment {
});
row();
new button("spawn", () -> {
new Enemy(EnemyTypes.healer).set(player.x, player.y).add();
new BaseUnit(UnitTypes.healer).set(player.x, player.y).add();
});
row();
}}.end();
@@ -163,8 +163,8 @@ public class DebugFragment implements Fragment {
result.append(", ");
result.append(player.y);
result.append("\n");
result.append(" android: ");
result.append(player.isAndroid);
result.append(" mech: ");
result.append(player.mech);
result.append("\n");
result.append(" local: ");
result.append(player.isLocal);

View File

@@ -5,6 +5,7 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.modules.InventoryModule;
import io.anuke.mindustry.world.blocks.types.modules.LiquidModule;
@@ -25,6 +26,7 @@ public class Tile{
private byte rotation;
private byte dump;
private byte extra;
private byte team;
/**The coordinates of the core tile this is linked to, in the form of two bytes packed into one.
* This is relative to the block it is linked to; negate coords to find the link.*/
public byte link = 0;
@@ -125,6 +127,15 @@ public class Tile{
public Block block(){
return Block.getByID(getWallID());
}
//TODO save team
public Team getTeam(){
return Team.values()[team];
}
public void setTeam(Team team){
this.team = (byte)team.ordinal();
}
/**Returns the breaktime of the block, <i>or</i> the breaktime of the linked block, if this tile is linked.*/
public float getBreakTime(){

View File

@@ -5,8 +5,8 @@ import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.EnemyTypes;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.entities.enemies.UnitTypes;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.world.blocks.Blocks;
@@ -77,7 +77,7 @@ public class WorldGenerator {
}
if(color == Hue.rgb(Color.PURPLE)){
if(!Vars.android) new Enemy(EnemyTypes.target).set(x * tilesize, y * tilesize).add();
if(!Vars.android) new BaseUnit(UnitTypes.target).set(x * tilesize, y * tilesize).add();
floor = Blocks.stone;
}

View File

@@ -180,7 +180,7 @@ public class ProductionBlocks{
{
resource = Blocks.uranium;
result = Item.uranium;
drillTime = 540;
drillTime = 600;
}
},

View File

@@ -3,7 +3,7 @@ package io.anuke.mindustry.world.blocks.types.defense;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.entities.enemies.BaseUnit;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.world.Layer;
import io.anuke.mindustry.world.Tile;
@@ -32,7 +32,7 @@ public class LaserTurret extends PowerTurret{
@Override
public void shoot(Tile tile){
TurretEntity entity = tile.entity();
Enemy enemy = entity.target;
BaseUnit enemy = entity.target;
if(Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) < cone){
enemy.damage(damage);
@@ -43,7 +43,7 @@ public class LaserTurret extends PowerTurret{
@Override
public void drawLayer2(Tile tile){
TurretEntity entity = tile.entity();
Enemy enemy = entity.target;
BaseUnit enemy = entity.target;
if(enemy != null &&
Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) <= cone){

View File

@@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color;
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.BaseUnit;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.*;
@@ -131,8 +131,8 @@ public class Turret extends Block{
if(hasAmmo(tile) || (debug && infiniteAmmo)){
if(entity.timer.get(timerTarget, targetInterval)){
entity.target = (Enemy)Entities.getClosest(enemyGroup,
tile.worldx(), tile.worldy(), range, e-> e instanceof Enemy && !((Enemy)e).isDead());
entity.target = (BaseUnit)Entities.getClosest(enemyGroup,
tile.worldx(), tile.worldy(), range, e-> e instanceof BaseUnit && !((BaseUnit)e).isDead());
}
if(entity.target != null){
@@ -240,7 +240,7 @@ public class Turret extends Block{
public TileEntity blockTarget;
public int ammo;
public float rotation = 90;
public Enemy target;
public BaseUnit target;
@Override
public void write(DataOutputStream stream) throws IOException{

View File

@@ -3,6 +3,8 @@ package io.anuke.mindustry.world.blocks.types.production;
import io.anuke.mindustry.world.Tile;
public class Centrifuge extends LiquidCrafter {
protected float powerUsed = 0.1f;
protected float timeUsed = 360f;
public Centrifuge(String name) {
super(name);