Weapon refactor / New units with edgy names / Spritesheet cleanup

This commit is contained in:
Anuken
2019-02-03 21:11:26 -05:00
parent 62d8cb0b25
commit a8c645f00d
50 changed files with 1969 additions and 2504 deletions
@@ -165,7 +165,7 @@ public class Damage{
entity.damage(amount);
//TODO better velocity displacement
float dst = tr.set(entity.x - x, entity.y - y).len();
entity.velocity().add(tr.setLength((1f - dst / radius) * 2f));
entity.velocity().add(tr.setLength((1f - dst / radius) * 2f / entity.mass()));
};
rect.setSize(radius * 2).setCenter(x, y);
@@ -48,7 +48,7 @@ public class Units{
/**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/
public static boolean invalidateTarget(TargetTrait target, Unit targeter){
return invalidateTarget(target, targeter.getTeam(), targeter.x, targeter.y, targeter.getWeapon().getAmmo().range());
return invalidateTarget(target, targeter.getTeam(), targeter.x, targeter.y, targeter.getWeapon().bullet.range());
}
/**Returns whether there are any entities on this tile.*/
@@ -1,14 +1,13 @@
package io.anuke.mindustry.entities.bullet;
import io.anuke.arc.Core;
import io.anuke.mindustry.entities.Effects;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.effect.Lightning;
import io.anuke.mindustry.entities.traits.TargetTrait;
@@ -72,7 +71,7 @@ public class BasicBulletType extends BulletType{
if(homingPower > 0.0001f){
TargetTrait target = Units.getClosestTarget(b.getTeam(), b.x, b.y, homingRange);
if(target != null){
b.velocity().setAngle(Angles.moveToward(b.velocity().angle(), b.angleTo(target), homingPower * Time.delta()));
b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f));
}
}
}
@@ -131,7 +131,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
}
public void targetClosest(){
target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().getAmmo().range(), type.range), u -> type.targetAir || !u.isFlying());
target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().bullet.range(), type.range), u -> type.targetAir || !u.isFlying());
}
public TileEntity getClosestEnemyCore(){
@@ -284,7 +284,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
@Override
public float drawSize(){
return 14;
return type.hitsize * 10;
}
@Override
@@ -1,15 +1,19 @@
package io.anuke.mindustry.entities.type;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Fill;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.entities.Predict;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Shaders;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.world.Tile;
@@ -18,7 +22,7 @@ import io.anuke.mindustry.world.meta.BlockFlag;
import static io.anuke.mindustry.Vars.world;
public abstract class FlyingUnit extends BaseUnit{
protected static Vector2 vec = new Vector2();
protected float[] weaponAngles = {0, 0};
protected final UnitState
@@ -52,6 +56,7 @@ public abstract class FlyingUnit extends BaseUnit{
}
if(target == null){
retarget(() -> {
targetClosest();
@@ -69,15 +74,27 @@ public abstract class FlyingUnit extends BaseUnit{
}
});
}else{
attack(150f);
attack(type.attackLength);
if((Angles.near(angleTo(target), rotation, 15f) || !getWeapon().getAmmo().keepVelocity) //bombers don't care about rotation
&& dst(target) < Math.max(getWeapon().getAmmo().range(), type.range)){
BulletType ammo = getWeapon().getAmmo();
if((Angles.near(angleTo(target), rotation, type.shootCone) || getWeapon().ignoreRotation) //bombers and such don't care about rotation
&& dst(target) < Math.max(getWeapon().bullet.range(), type.range)){
BulletType ammo = getWeapon().bullet;
Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.speed);
if(type.rotateWeapon){
for(boolean left : Mathf.booleans){
int wi = Mathf.num(left);
float wx = x + Angles.trnsx(rotation - 90, getWeapon().width * Mathf.sign(left));
float wy = y + Angles.trnsy(rotation - 90, getWeapon().width * Mathf.sign(left));
getWeapon().update(FlyingUnit.this, to.x, to.y);
weaponAngles[wi] = Mathf.slerpDelta(weaponAngles[wi], Angles.angle(wx, wy, target.getX(), target.getY()), 0.1f);
Tmp.v2.trns(weaponAngles[wi], getWeapon().length);
getWeapon().update(FlyingUnit.this, wx + Tmp.v2.x, wy + Tmp.v2.y, weaponAngles[wi], left);
}
}else{
Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.speed);
getWeapon().update(FlyingUnit.this, to.x, to.y);
}
}
}
}
@@ -133,19 +150,46 @@ public abstract class FlyingUnit extends BaseUnit{
}
}
@Override
public void drawUnder(){
drawEngine();
}
@Override
public void draw(){
Draw.alpha(Draw.getShader() != Shaders.mix ? 1f : hitTime / hitDuration);
Draw.rect(type.region, x, y, rotation - 90);
Draw.rect(type.name, x, y, rotation - 90);
drawWeapons();
drawItems();
Draw.alpha(1f);
}
public void drawWeapons(){
}
public void drawEngine(){
Draw.color(Palette.engine);
Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset), y + Angles.trnsy(rotation + 180, type.engineOffset),
type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize/4f));
Draw.color(Color.WHITE);
Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset-1f), y + Angles.trnsy(rotation + 180, type.engineOffset-1f),
(type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize/4f)) / 2f);
Draw.color();
}
@Override
public void behavior(){
if(Units.invalidateTarget(target, this)){
for(boolean left : Mathf.booleans){
int wi = Mathf.num(left);
weaponAngles[wi] = Mathf.slerpDelta(weaponAngles[wi],rotation, 0.1f);
}
}
if(health <= health * type.retreatPercent &&
Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)) != null){
setState(retreat);
@@ -157,19 +201,14 @@ public abstract class FlyingUnit extends BaseUnit{
return attack;
}
@Override
public float drawSize(){
return 60;
}
protected void wobble(){
if(Net.client()) return;
x += Mathf.sin(Time.time() + id * 999, 25f, 0.08f)*Time.delta();
y += Mathf.cos(Time.time() + id * 999, 25f, 0.08f)*Time.delta();
x += Mathf.sin(Time.time() + id * 999, 25f, 0.05f)*Time.delta();
y += Mathf.cos(Time.time() + id * 999, 25f, 0.05f)*Time.delta();
if(velocity.len() <= 0.05f){
rotation += Mathf.sin(Time.time() + id * 99, 10f, 2.5f)*Time.delta();
//rotation += Mathf.sin(Time.time() + id * 99, 10f, 2f * type.speed)*Time.delta();
}
}
@@ -184,44 +223,48 @@ public abstract class FlyingUnit extends BaseUnit{
protected void circle(float circleLength, float speed){
if(target == null) return;
vec.set(target.getX() - x, target.getY() - y);
Tmp.v1.set(target.getX() - x, target.getY() - y);
if(vec.len() < circleLength){
vec.rotate((circleLength - vec.len()) / circleLength * 180f);
if(Tmp.v1.len() < circleLength){
Tmp.v1.rotate((circleLength - Tmp.v1.len()) / circleLength * 180f);
}
vec.setLength(speed * Time.delta());
Tmp.v1.setLength(speed * Time.delta());
velocity.add(vec);
velocity.add(Tmp.v1);
}
protected void moveTo(float circleLength){
if(target == null) return;
vec.set(target.getX() - x, target.getY() - y);
Tmp.v1.set(target.getX() - x, target.getY() - y);
float length = circleLength <= 0.001f ? 1f : Mathf.clamp((dst(target) - circleLength) / 100f, -1f, 1f);
vec.setLength(type.speed * Time.delta() * length);
if(length < 0) vec.rotate(180f);
Tmp.v1.setLength(type.speed * Time.delta() * length);
if(length < -0.5f){
Tmp.v1.rotate(180f);
}else if(length < 0){
Tmp.v1.setZero();
}
velocity.add(vec);
velocity.add(Tmp.v1);
}
protected void attack(float circleLength){
vec.set(target.getX() - x, target.getY() - y);
Tmp.v1.set(target.getX() - x, target.getY() - y);
float ang = angleTo(target);
float diff = Angles.angleDist(ang, rotation);
if(diff > 100f && vec.len() < circleLength){
vec.setAngle(velocity.angle());
if(diff > 100f && Tmp.v1.len() < circleLength){
Tmp.v1.setAngle(velocity.angle());
}else{
vec.setAngle(Mathf.slerpDelta(velocity.angle(), vec.angle(), 0.44f));
Tmp.v1.setAngle(Mathf.slerpDelta(velocity.angle(), Tmp.v1.angle(), 0.44f));
}
vec.setLength(type.speed * Time.delta());
Tmp.v1.setLength(type.speed * Time.delta());
velocity.add(vec);
velocity.add(Tmp.v1);
}
}
@@ -11,19 +11,12 @@ import io.anuke.mindustry.entities.Predict;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.type.UnitType;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.Shaders;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.Weapon;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.world;
public abstract class GroundUnit extends BaseUnit{
@@ -32,7 +25,6 @@ public abstract class GroundUnit extends BaseUnit{
protected float walkTime;
protected float stuckTime;
protected float baseRotation;
protected Weapon weapon;
public final UnitState
@@ -45,11 +37,11 @@ public abstract class GroundUnit extends BaseUnit{
TileEntity core = getClosestEnemyCore();
float dst = core == null ? 0 : dst(core);
if(core != null && dst < getWeapon().getAmmo().range() / 1.1f){
if(core != null && dst < getWeapon().bullet.range() / 1.1f){
target = core;
}
if(dst > getWeapon().getAmmo().range() * 0.5f){
if(dst > getWeapon().bullet.range() * 0.5f){
moveToCore();
}
}
@@ -80,12 +72,6 @@ public abstract class GroundUnit extends BaseUnit{
}
};
@Override
public void init(UnitType type, Team team){
super.init(type, team);
this.weapon = type.weapon;
}
@Override
public void interpolate(){
super.interpolate();
@@ -125,11 +111,7 @@ public abstract class GroundUnit extends BaseUnit{
@Override
public Weapon getWeapon(){
return weapon;
}
public void setWeapon(Weapon weapon){
this.weapon = weapon;
return type.weapon;
}
@Override
@@ -162,11 +144,11 @@ public abstract class GroundUnit extends BaseUnit{
Draw.rect(type.region, x, y, rotation - 90);
for(int i : Mathf.signs){
float tra = rotation - 90, trY = -weapon.getRecoil(this, i > 0) + type.weaponOffsetY;
float tra = rotation - 90, trY = -type.weapon.getRecoil(this, i > 0) + type.weaponOffsetY;
float w = i > 0 ? -12 : 12;
Draw.rect(weapon.equipRegion,
x + Angles.trnsx(tra, type.weaponOffsetX * i, trY),
y + Angles.trnsy(tra, type.weaponOffsetX * i, trY), w, 12, rotation - 90);
Draw.rect(type.weapon.equipRegion,
x + Angles.trnsx(tra, getWeapon().width * i, trY),
y + Angles.trnsy(tra, getWeapon().width * i, trY), w, 12, rotation - 90);
}
drawItems();
@@ -181,11 +163,11 @@ public abstract class GroundUnit extends BaseUnit{
}
if(!Units.invalidateTarget(target, this)){
if(dst(target) < getWeapon().getAmmo().range()){
if(dst(target) < getWeapon().bullet.range()){
rotate(angleTo(target));
if(Angles.near(angleTo(target), rotation, 13f)){
BulletType ammo = getWeapon().getAmmo();
BulletType ammo = getWeapon().bullet;
Vector2 to = Predict.intercept(GroundUnit.this, target, ammo.speed);
@@ -206,30 +188,6 @@ public abstract class GroundUnit extends BaseUnit{
retarget(this::targetClosest);
}
@Override
public void write(DataOutput data) throws IOException{
super.write(data);
data.writeByte(weapon.id);
}
@Override
public void read(DataInput data) throws IOException{
super.read(data);
weapon = content.getByID(ContentType.weapon, data.readByte());
}
@Override
public void writeSave(DataOutput stream) throws IOException{
stream.writeByte(weapon.id);
super.writeSave(stream);
}
@Override
public void readSave(DataInput stream) throws IOException{
weapon = content.getByID(ContentType.weapon, stream.readByte());
super.readSave(stream);
}
protected void patrol(){
vec.trns(baseRotation, type.speed * Time.delta());
velocity.add(vec.x, vec.y);
@@ -370,6 +370,20 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
drawBuilding();
}
@Override
public void drawUnder(){
float size = mech.engineSize * (mech.flying ? 1f : boostHeat);
Draw.color(mech.trailColorTo);
Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset), y + Angles.trnsy(rotation + 180, mech.engineOffset),
size + Mathf.absin(Time.time(), 2f, size/4f));
Draw.color(Color.WHITE);
Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset-1f), y + Angles.trnsy(rotation + 180, mech.engineOffset-1f),
(size + Mathf.absin(Time.time(), 2f, size/4f)) / 2f);
Draw.color();
}
public void drawName(){
BitmapFont font = Core.scene.skin.getFont("default-font");
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
@@ -603,7 +617,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
protected void updateFlying(){
if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
mech.canHeal && dst(target) < getWeapon().getAmmo().range())){
mech.canHeal && dst(target) < getWeapon().bullet.range())){
target = null;
}
@@ -675,11 +689,11 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
if(target == null){
isShooting = false;
if(Core.settings.getBool("autotarget")){
target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().range());
target = Units.getClosestTarget(team, x, y, getWeapon().bullet.range());
if(mech.canHeal && target == null){
target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.blue));
if(target != null && dst(target) > getWeapon().getAmmo().range()){
if(target != null && dst(target) > getWeapon().bullet.range()){
target = null;
}else if(target != null){
target = ((Tile) target).entity;
@@ -691,14 +705,14 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
}
}
}else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
mech.canHeal && dst(target) < getWeapon().getAmmo().range())){
mech.canHeal && dst(target) < getWeapon().bullet.range())){
//rotate toward and shoot the target
if(mech.turnCursor){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
}
Vector2 intercept =
Predict.intercept(x, y, target.getX(), target.getY(), target.velocity().x - velocity.x, target.velocity().y - velocity.y, getWeapon().getAmmo().speed);
Predict.intercept(x, y, target.getX(), target.getY(), target.velocity().x - velocity.x, target.velocity().y - velocity.y, getWeapon().bullet.speed);
pointerX = intercept.x;
pointerY = intercept.y;
@@ -1,7 +1,35 @@
package io.anuke.mindustry.entities.type.base;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.type.FlyingUnit;
public class Revenant extends FlyingUnit{
@Override
public void drawWeapons(){
for(int i : Mathf.signs){
float tra = rotation - 90, trY = -getWeapon().getRecoil(this, i > 0) + type.weaponOffsetY;
float w = i > 0 ? -12 : 12;
float wx = x + Angles.trnsx(tra, getWeapon().width * i, trY), wy = y + Angles.trnsy(tra, getWeapon().width * i, trY);
int wi = (i + 1)/2;
Draw.rect(getWeapon().equipRegion, wx, wy, w, 12, weaponAngles[wi] - 90);
}
}
@Override
protected void attack(float circleLength){
moveTo(circleLength);
}
@Override
protected void updateRotation(){
if(!Units.invalidateTarget(target, this)){
rotation = Mathf.slerpDelta(rotation, angleTo(target), type.rotatespeed);
}else{
rotation = Mathf.slerpDelta(rotation, velocity.angle(), type.baseRotateSpeed);
}
}
}