Gradual component conversion
This commit is contained in:
@@ -4,7 +4,6 @@ import arc.struct.Array;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.entities.traits.Entity;
|
||||
import mindustry.entities.traits.SolidTrait;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -11,6 +11,8 @@ import mindustry.world.blocks.*;
|
||||
|
||||
public class HealBulletType extends BulletType{
|
||||
protected float healPercent = 3f;
|
||||
protected float bulletHeight = 7f, bulletWidth = 2f;
|
||||
protected Color backColor = Pal.heal, frontColor = Color.white;
|
||||
|
||||
public HealBulletType(float speed, float damage){
|
||||
super(speed, damage);
|
||||
@@ -33,11 +35,11 @@ public class HealBulletType extends BulletType{
|
||||
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
Draw.color(Pal.heal);
|
||||
Lines.stroke(2f);
|
||||
Lines.lineAngleCenter(b.x, b.y, b.rot(), 7f);
|
||||
Draw.color(Color.white);
|
||||
Lines.lineAngleCenter(b.x, b.y, b.rot(), 3f);
|
||||
Draw.color(backColor);
|
||||
Lines.stroke(bulletWidth);
|
||||
Lines.lineAngleCenter(b.x, b.y, b.rot(), bulletHeight);
|
||||
Draw.color(frontColor);
|
||||
Lines.lineAngleCenter(b.x, b.y, b.rot(), bulletHeight / 2f);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
|
||||
73
core/src/mindustry/entities/bullet/LaserBulletType.java
Normal file
73
core/src/mindustry/entities/bullet/LaserBulletType.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package mindustry.entities.bullet;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class LaserBulletType extends BulletType{
|
||||
protected Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white};
|
||||
protected float length = 160f;
|
||||
protected float width = 15f;
|
||||
protected float lengthFalloff = 0.5f;
|
||||
protected float sideLength = 29f, sideWidth = 0.7f;
|
||||
protected float sideAngle = 90f;
|
||||
|
||||
public LaserBulletType(float damage){
|
||||
super(0.01f, damage);
|
||||
|
||||
keepVelocity = false;
|
||||
hitEffect = Fx.hitLancer;
|
||||
despawnEffect = Fx.none;
|
||||
shootEffect = Fx.hitLancer;
|
||||
smokeEffect = Fx.lancerLaserShootSmoke;
|
||||
hitSize = 4;
|
||||
lifetime = 16f;
|
||||
pierce = true;
|
||||
}
|
||||
|
||||
public LaserBulletType(){
|
||||
this(1f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float range(){
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Bullet b){
|
||||
Damage.collideLine(b, b.getTeam(), hitEffect, b.x, b.y, b.rot(), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
float f = Mathf.curve(b.fin(), 0f, 0.2f);
|
||||
float baseLen = length * f;
|
||||
float cwidth = width;
|
||||
float compound = 1f;
|
||||
|
||||
Lines.lineAngle(b.x, b.y, b.rot(), baseLen);
|
||||
Lines.precise(true);
|
||||
for(Color color : colors){
|
||||
Draw.color(color);
|
||||
Lines.stroke((cwidth *= lengthFalloff) * b.fout());
|
||||
Lines.lineAngle(b.x, b.y, b.rot(), baseLen, CapStyle.none);
|
||||
Tmp.v1.trns(b.rot(), baseLen);
|
||||
Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, Lines.getStroke() * 1.22f, cwidth * 2f + width / 2f, b.rot());
|
||||
|
||||
Fill.circle(b.x, b.y, 1f * cwidth * b.fout());
|
||||
for(int i : Mathf.signs){
|
||||
Drawf.tri(b.x, b.y, sideWidth * b.fout() * cwidth, sideLength * compound, b.rot() + sideAngle * i);
|
||||
}
|
||||
|
||||
compound *= lengthFalloff;
|
||||
}
|
||||
Lines.precise(false);
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
30
core/src/mindustry/entities/bullet/LightningBulletType.java
Normal file
30
core/src/mindustry/entities/bullet/LightningBulletType.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package mindustry.entities.bullet;
|
||||
|
||||
import arc.graphics.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class LightningBulletType extends BulletType{
|
||||
protected Color lightningColor = Pal.lancerLaser;
|
||||
protected int lightningLength = 25;
|
||||
|
||||
public LightningBulletType(){
|
||||
super(0.0001f, 1f);
|
||||
|
||||
lifetime = 1;
|
||||
despawnEffect = Fx.none;
|
||||
hitEffect = Fx.hitLancer;
|
||||
keepVelocity = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Bullet b){
|
||||
Lightning.create(b.getTeam(), lightningColor, damage, b.x, b.y, b.rot(), lightningLength);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,22 @@
|
||||
package mindustry.entities.def;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.Bits;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -23,19 +29,23 @@ import static mindustry.Vars.content;
|
||||
|
||||
public class EntityComps{
|
||||
|
||||
@Depends({HealthComp.class, VelComp.class, StatusComp.class, TeamComp.class, ItemsComp.class})
|
||||
@Component({HealthComp.class, VelComp.class, StatusComp.class, TeamComp.class, ItemsComp.class})
|
||||
class UnitComp{
|
||||
//UnitDef type;
|
||||
UnitDef type;
|
||||
}
|
||||
|
||||
class OwnerComp{
|
||||
Entityc owner;
|
||||
}
|
||||
|
||||
@Depends({TimedComp.class})
|
||||
@Component({TimedComp.class, DamageComp.class, Hitboxc.class})
|
||||
class BulletComp{
|
||||
BulletType bullet;
|
||||
|
||||
float getDamage(){
|
||||
return bullet.damage;
|
||||
}
|
||||
|
||||
void init(){
|
||||
//TODO
|
||||
bullet.init(null);
|
||||
@@ -47,6 +57,12 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DamageComp{
|
||||
abstract float getDamage();
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class TimedComp extends EntityComp implements Scaled{
|
||||
float time, lifetime;
|
||||
|
||||
@@ -64,79 +80,339 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class HealthComp{
|
||||
float health, maxHealth;
|
||||
float health, maxHealth, hitTime;
|
||||
boolean dead;
|
||||
|
||||
float healthf(){
|
||||
return health / maxHealth;
|
||||
}
|
||||
|
||||
void update(){
|
||||
hitTime -= Time.delta() / 9f;
|
||||
}
|
||||
|
||||
void killed(){
|
||||
//implement by other components
|
||||
}
|
||||
|
||||
void kill(){
|
||||
health = 0;
|
||||
dead = true;
|
||||
}
|
||||
|
||||
void heal(){
|
||||
dead = false;
|
||||
health = maxHealth;
|
||||
}
|
||||
|
||||
boolean damaged(){
|
||||
return health <= maxHealth - 0.0001f;
|
||||
}
|
||||
|
||||
void damage(float amount){
|
||||
health -= amount;
|
||||
if(health <= 0 && !dead){
|
||||
dead = true;
|
||||
killed();
|
||||
}
|
||||
}
|
||||
|
||||
void clampHealth(){
|
||||
health = Mathf.clamp(health, 0, maxHealth);
|
||||
}
|
||||
|
||||
void heal(float amount){
|
||||
health += amount;
|
||||
clampHealth();
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class FlyingComp{
|
||||
boolean flying;
|
||||
}
|
||||
|
||||
@Component
|
||||
class LegsComp{
|
||||
|
||||
float baseRotation;
|
||||
float drownTime;
|
||||
}
|
||||
|
||||
@Component
|
||||
class RotComp{
|
||||
float rotation;
|
||||
}
|
||||
|
||||
@Component
|
||||
class TeamComp{
|
||||
Team team = Team.sharded;
|
||||
}
|
||||
|
||||
@Depends(PosComp.class)
|
||||
class SyncComp{
|
||||
Interpolator interpolator;
|
||||
@Component({RotComp.class, PosComp.class})
|
||||
static class WeaponsComp{
|
||||
transient float x, y, rotation;
|
||||
|
||||
/** 1 */
|
||||
static final int[] one = {1};
|
||||
/** minimum cursor distance from player, fixes 'cross-eyed' shooting */
|
||||
static final float minAimDst = 20f;
|
||||
/** temporary weapon sequence number */
|
||||
static int sequenceNum = 0;
|
||||
|
||||
/** weapon mount array, never null */
|
||||
WeaponMount[] mounts = {};
|
||||
|
||||
public void init(UnitDef def){
|
||||
mounts = new WeaponMount[def.weapons.size];
|
||||
for(int i = 0; i < mounts.length; i++){
|
||||
mounts[i] = new WeaponMount(def.weapons.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/** Aim at something. This will make all mounts point at it. */
|
||||
public void aim(Unit unit, float x, float y){
|
||||
Tmp.v1.set(x, y).sub(unit.x, unit.y);
|
||||
if(Tmp.v1.len() < minAimDst) Tmp.v1.setLength(minAimDst);
|
||||
|
||||
x = Tmp.v1.x + unit.x;
|
||||
y = Tmp.v1.y + unit.y;
|
||||
|
||||
for(WeaponMount mount : mounts){
|
||||
mount.aimX = x;
|
||||
mount.aimY = y;
|
||||
}
|
||||
}
|
||||
|
||||
/** Update shooting and rotation for this unit. */
|
||||
public void update(Unit unit){
|
||||
for(WeaponMount mount : mounts){
|
||||
Weapon weapon = mount.weapon;
|
||||
mount.reload -= Time.delta();
|
||||
|
||||
float rotation = unit.rotation - 90;
|
||||
|
||||
//rotate if applicable
|
||||
if(weapon.rotate){
|
||||
float axisXOffset = weapon.mirror ? 0f : weapon.x;
|
||||
float axisX = unit.x + Angles.trnsx(rotation, axisXOffset, weapon.y),
|
||||
axisY = unit.y + Angles.trnsy(rotation, axisXOffset, weapon.y);
|
||||
|
||||
mount.rotation = Angles.moveToward(mount.rotation, Angles.angle(axisX, axisY, mount.aimX, mount.aimY), weapon.rotateSpeed);
|
||||
}
|
||||
|
||||
//shoot if applicable
|
||||
//TODO only shoot if angle is reached, don't shoot inaccurately
|
||||
if(mount.reload <= 0){
|
||||
for(int i : (weapon.mirror && !weapon.alternate ? Mathf.signs : one)){
|
||||
i *= Mathf.sign(weapon.flipped) * Mathf.sign(mount.side);
|
||||
|
||||
//m a t h
|
||||
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
|
||||
float mountX = unit.x + Angles.trnsx(rotation, weapon.x * i, weapon.y),
|
||||
mountY = unit.y + Angles.trnsy(rotation, weapon.x * i, weapon.y);
|
||||
float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX * i, weapon.shootY),
|
||||
shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX * i, weapon.shootY);
|
||||
float shootAngle = weapon.rotate ? weaponRotation : Angles.angle(shootX, shootY, mount.aimX, mount.aimY);
|
||||
|
||||
shoot(unit, weapon, shootX, shootY, shootAngle);
|
||||
}
|
||||
|
||||
mount.side = !mount.side;
|
||||
mount.reload = weapon.reload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Draw weapon mounts. */
|
||||
void draw(){
|
||||
for(WeaponMount mount : mounts){
|
||||
Weapon weapon = mount.weapon;
|
||||
|
||||
for(int i : (weapon.mirror ? Mathf.signs : one)){
|
||||
i *= Mathf.sign(weapon.flipped);
|
||||
|
||||
float rotation = this.rotation - 90 + (weapon.rotate ? mount.rotation : 0);
|
||||
float trY = weapon.y - (mount.reload / weapon.reload * weapon.recoil) * (weapon.alternate ? Mathf.num(i == Mathf.sign(mount.side)) : 1);
|
||||
float width = i > 0 ? -weapon.region.getWidth() : weapon.region.getWidth();
|
||||
|
||||
Draw.rect(weapon.region,
|
||||
x + Angles.trnsx(rotation, weapon.x * i, trY),
|
||||
y + Angles.trnsy(rotation, weapon.x * i, trY),
|
||||
width * Draw.scl,
|
||||
weapon.region.getHeight() * Draw.scl,
|
||||
rotation - 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void shoot(ShooterTrait shooter, Weapon weapon, float x, float y, float rotation){
|
||||
float baseX = shooter.getX(), baseY = shooter.getY();
|
||||
|
||||
weapon.shootSound.at(x, y, Mathf.random(0.8f, 1.0f));
|
||||
|
||||
sequenceNum = 0;
|
||||
if(weapon.shotDelay > 0.01f){
|
||||
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> {
|
||||
Time.run(sequenceNum * weapon.shotDelay, () -> bullet(shooter, weapon, x + shooter.getX() - baseX, y + shooter.getY() - baseY, f + Mathf.range(weapon.inaccuracy)));
|
||||
sequenceNum++;
|
||||
});
|
||||
}else{
|
||||
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(shooter, weapon, x, y, f + Mathf.range(weapon.inaccuracy)));
|
||||
}
|
||||
|
||||
BulletType ammo = weapon.bullet;
|
||||
|
||||
Tmp.v1.trns(rotation + 180f, ammo.recoil);
|
||||
|
||||
shooter.velocity().add(Tmp.v1);
|
||||
|
||||
Tmp.v1.trns(rotation, 3f);
|
||||
boolean parentize = ammo.keepVelocity;
|
||||
|
||||
Effects.shake(weapon.shake, weapon.shake, x, y);
|
||||
Effects.effect(weapon.ejectEffect, x, y, rotation);
|
||||
Effects.effect(ammo.shootEffect, x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? shooter : null);
|
||||
Effects.effect(ammo.smokeEffect, x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? shooter : null);
|
||||
}
|
||||
|
||||
private void bullet(ShooterTrait owner, Weapon weapon, float x, float y, float angle){
|
||||
Tmp.v1.trns(angle, 3f);
|
||||
Bullet.create(weapon.bullet, owner, owner.getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd));
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PosComp implements Position{
|
||||
@Component
|
||||
abstract class DrawComp{
|
||||
//TODO ponder.
|
||||
|
||||
abstract float drawSize();
|
||||
|
||||
void draw(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Component(PosComp.class)
|
||||
abstract class SyncComp extends PosComp{
|
||||
Interpolator interpolator = new Interpolator();
|
||||
|
||||
void setNet(float x, float y){
|
||||
set(x, y);
|
||||
|
||||
//TODO change interpolator API
|
||||
if(interpolator != null){
|
||||
interpolator.target.set(x, y);
|
||||
interpolator.last.set(x, y);
|
||||
interpolator.pos.set(0, 0);
|
||||
interpolator.updateSpacing = 16;
|
||||
interpolator.lastUpdated = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void update(){
|
||||
if(Vars.net.client() && !isLocal()){
|
||||
interpolate();
|
||||
}
|
||||
}
|
||||
|
||||
void interpolate(){
|
||||
interpolator.update();
|
||||
x = interpolator.pos.x;
|
||||
y = interpolator.pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class PosComp extends EntityComp implements Position{
|
||||
float x, y;
|
||||
|
||||
void set(float x, float y){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
void trns(float x, float y){
|
||||
set(this.x + x, this.y + y);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DamageComp{
|
||||
abstract float getDamage();
|
||||
}
|
||||
|
||||
@Component
|
||||
class MinerComp{
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
class BuilderComp{
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
class ItemsComp{
|
||||
ItemStack item = new ItemStack();
|
||||
}
|
||||
|
||||
@Depends(PosComp.class)
|
||||
class VelComp{
|
||||
transient float x, y;
|
||||
@Component(VelComp.class)
|
||||
class MassComp{
|
||||
float mass;
|
||||
}
|
||||
|
||||
@Component({PosComp.class, DrawComp.class, TimedComp.class})
|
||||
class EffectComp extends EntityComp{
|
||||
Effect effect;
|
||||
Color color = new Color(Color.white);
|
||||
Object data;
|
||||
float rotation = 0f;
|
||||
|
||||
void draw(){
|
||||
|
||||
}
|
||||
|
||||
void update(){
|
||||
//TODO fix effects, make everything poolable
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class VelComp extends PosComp{
|
||||
final Vec2 vel = new Vec2();
|
||||
float drag = 0f;
|
||||
|
||||
void update(){
|
||||
x += vel.x;
|
||||
y += vel.y;
|
||||
vel.scl(0.9f);
|
||||
vel.scl(1f - drag * Time.delta());
|
||||
}
|
||||
}
|
||||
|
||||
@Depends(PosComp.class)
|
||||
@Component(PosComp.class)
|
||||
class HitboxComp{
|
||||
transient float x, y;
|
||||
|
||||
float hitSize;
|
||||
float lastX, lastY;
|
||||
|
||||
void update(){
|
||||
|
||||
}
|
||||
|
||||
void updateLastPosition(){
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
|
||||
void collision(Hitboxc other){
|
||||
|
||||
}
|
||||
|
||||
float getDeltaX(){
|
||||
return x - lastX;
|
||||
}
|
||||
|
||||
float getDeltaY(){
|
||||
return y - lastY;
|
||||
}
|
||||
|
||||
boolean collides(Hitboxc other){
|
||||
return Intersector.overlapsRect(x - hitSize/2f, y - hitSize/2f, hitSize, hitSize,
|
||||
@@ -144,7 +420,7 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Depends(PosComp.class)
|
||||
@Component(PosComp.class)
|
||||
class StatusComp{
|
||||
private Array<StatusEntry> statuses = new Array<>();
|
||||
private Bits applied = new Bits(content.getBy(ContentType.status).size);
|
||||
@@ -258,6 +534,7 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
@BaseComponent
|
||||
class EntityComp{
|
||||
int id;
|
||||
@@ -268,6 +545,11 @@ public class EntityComps{
|
||||
|
||||
void remove(){}
|
||||
|
||||
boolean isLocal(){
|
||||
//TODO fix
|
||||
return this == (Object)Vars.player;
|
||||
}
|
||||
|
||||
<T> T as(Class<T> type){
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import arc.math.Mathf;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.entities.traits.BelowLiquidTrait;
|
||||
import mindustry.entities.traits.DrawTrait;
|
||||
import mindustry.graphics.Pal;
|
||||
|
||||
import static mindustry.Vars.groundEffectGroup;
|
||||
|
||||
@@ -11,7 +11,6 @@ import arc.util.Time;
|
||||
import arc.util.pooling.Pools;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.entities.traits.DrawTrait;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.type.Item;
|
||||
|
||||
@@ -14,8 +14,6 @@ import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.Units;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.entities.traits.DrawTrait;
|
||||
import mindustry.entities.traits.TimeTrait;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.game.Team;
|
||||
import mindustry.gen.Call;
|
||||
|
||||
@@ -67,9 +67,9 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
|
||||
if(!(tile.block() instanceof BuildBlock)){
|
||||
if(!current.initialized && canCreateBlocks() && !current.breaking && Build.validPlace(getTeam(), current.x, current.y, current.block, current.rotation)){
|
||||
Call.beginPlace(getTeam(), current.x, current.y, current.block, current.rotation);
|
||||
Build.beginPlace(getTeam(), current.x, current.y, current.block, current.rotation);
|
||||
}else if(!current.initialized && canCreateBlocks() && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){
|
||||
Call.beginBreak(getTeam(), current.x, current.y);
|
||||
Build.beginBreak(getTeam(), current.x, current.y);
|
||||
}else{
|
||||
buildQueue().removeFirst();
|
||||
return;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
public interface DamageTrait{
|
||||
float damage();
|
||||
|
||||
default void killed(Entity other){
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
public interface DrawTrait extends Entity{
|
||||
|
||||
default float drawSize(){
|
||||
return 20f;
|
||||
}
|
||||
|
||||
void draw();
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.*;
|
||||
import mindustry.entities.*;
|
||||
|
||||
public interface Entity extends MoveTrait{
|
||||
|
||||
@@ -14,6 +15,14 @@ public interface Entity extends MoveTrait{
|
||||
|
||||
default void added(){}
|
||||
|
||||
default int tileX(){
|
||||
return Vars.world.toTile(getX());
|
||||
}
|
||||
|
||||
default int tileY(){
|
||||
return Vars.world.toTile(getY());
|
||||
}
|
||||
|
||||
EntityGroup targetGroup();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.math.Mathf;
|
||||
|
||||
public interface HealthTrait{
|
||||
|
||||
void health(float health);
|
||||
|
||||
float health();
|
||||
|
||||
float maxHealth();
|
||||
|
||||
boolean isDead();
|
||||
|
||||
void setDead(boolean dead);
|
||||
|
||||
default void kill(){
|
||||
health(-1);
|
||||
damage(1);
|
||||
}
|
||||
|
||||
default void onHit(SolidTrait entity){
|
||||
}
|
||||
|
||||
default void onDeath(){
|
||||
}
|
||||
|
||||
default boolean damaged(){
|
||||
return health() < maxHealth() - 0.0001f;
|
||||
}
|
||||
|
||||
default void damage(float amount){
|
||||
health(health() - amount);
|
||||
if(health() <= 0 && !isDead()){
|
||||
onDeath();
|
||||
setDead(true);
|
||||
}
|
||||
}
|
||||
|
||||
default void clampHealth(){
|
||||
health(Mathf.clamp(health(), 0, maxHealth()));
|
||||
}
|
||||
|
||||
default float healthf(){
|
||||
return health() / maxHealth();
|
||||
}
|
||||
|
||||
default void healBy(float amount){
|
||||
health(health() + amount);
|
||||
clampHealth();
|
||||
}
|
||||
|
||||
default void heal(){
|
||||
health(maxHealth());
|
||||
setDead(false);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
public interface KillerTrait{
|
||||
void killed(Entity other);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.math.geom.Position;
|
||||
|
||||
public interface MoveTrait extends Position{
|
||||
|
||||
void setX(float x);
|
||||
|
||||
void setY(float y);
|
||||
|
||||
default void moveBy(float x, float y){
|
||||
setX(getX() + x);
|
||||
setY(getY() + y);
|
||||
}
|
||||
|
||||
default void set(float x, float y){
|
||||
setX(x);
|
||||
setY(y);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.util.Interval;
|
||||
import mindustry.type.Weapon;
|
||||
|
||||
public interface ShooterTrait extends VelocityTrait, TeamTrait{
|
||||
|
||||
Interval getTimer();
|
||||
|
||||
int getShootTimer(boolean left);
|
||||
|
||||
Weapon getWeapon();
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
|
||||
import arc.math.geom.*;
|
||||
import arc.math.geom.QuadTree.QuadTreeObject;
|
||||
import mindustry.Vars;
|
||||
|
||||
public interface SolidTrait extends QuadTreeObject, MoveTrait, VelocityTrait, Entity, Position{
|
||||
|
||||
void hitbox(Rect rect);
|
||||
|
||||
void hitboxTile(Rect rect);
|
||||
|
||||
Vec2 lastPosition();
|
||||
|
||||
default boolean collidesGrid(int x, int y){
|
||||
return true;
|
||||
}
|
||||
|
||||
default float getDeltaX(){
|
||||
return getX() - lastPosition().x;
|
||||
}
|
||||
|
||||
default float getDeltaY(){
|
||||
return getY() - lastPosition().y;
|
||||
}
|
||||
|
||||
default boolean collides(SolidTrait other){
|
||||
return true;
|
||||
}
|
||||
|
||||
default void collision(SolidTrait other, float x, float y){
|
||||
}
|
||||
|
||||
default void move(float x, float y){
|
||||
Vars.collisions.move(this, x, y);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import mindustry.net.Interpolator;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public interface SyncTrait extends Entity, TypeTrait{
|
||||
|
||||
/** Sets the position of this entity and updated the interpolator. */
|
||||
default void setNet(float x, float y){
|
||||
set(x, y);
|
||||
|
||||
if(getInterpolator() != null){
|
||||
getInterpolator().target.set(x, y);
|
||||
getInterpolator().last.set(x, y);
|
||||
getInterpolator().pos.set(0, 0);
|
||||
getInterpolator().updateSpacing = 16;
|
||||
getInterpolator().lastUpdated = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Interpolate entity position only. Override if you need to interpolate rotations or other values. */
|
||||
default void interpolate(){
|
||||
if(getInterpolator() == null){
|
||||
throw new RuntimeException("This entity must have an interpolator to interpolate()!");
|
||||
}
|
||||
|
||||
getInterpolator().update();
|
||||
|
||||
setX(getInterpolator().pos.x);
|
||||
setY(getInterpolator().pos.y);
|
||||
}
|
||||
|
||||
/** Return the interpolator used for smoothing the position. Optional. */
|
||||
default Interpolator getInterpolator(){
|
||||
return null;
|
||||
}
|
||||
|
||||
//Read and write sync data, usually position
|
||||
void write(DataOutput data) throws IOException;
|
||||
|
||||
void read(DataInput data) throws IOException;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.math.geom.Position;
|
||||
import mindustry.game.Team;
|
||||
|
||||
/**
|
||||
* Base interface for targetable entities.
|
||||
*/
|
||||
public interface TargetTrait extends Position, VelocityTrait{
|
||||
|
||||
boolean isDead();
|
||||
|
||||
Team getTeam();
|
||||
|
||||
default float getTargetVelocityX(){
|
||||
if(this instanceof SolidTrait){
|
||||
return ((SolidTrait)this).getDeltaX();
|
||||
}
|
||||
return velocity().x;
|
||||
}
|
||||
|
||||
default float getTargetVelocityY(){
|
||||
if(this instanceof SolidTrait){
|
||||
return ((SolidTrait)this).getDeltaY();
|
||||
}
|
||||
return velocity().y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this entity is a valid target.
|
||||
*/
|
||||
default boolean isValid(){
|
||||
return !isDead();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import mindustry.game.Team;
|
||||
|
||||
public interface TeamTrait extends Entity{
|
||||
Team getTeam();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.util.Time;
|
||||
|
||||
public interface TimeTrait extends Scaled, Entity{
|
||||
|
||||
float lifetime();
|
||||
|
||||
void time(float time);
|
||||
|
||||
float time();
|
||||
|
||||
default void updateTime(){
|
||||
time(Mathf.clamp(time() + Time.delta(), 0, lifetime()));
|
||||
|
||||
if(time() >= lifetime()){
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
//fin() is not implemented due to compiler issues with iOS/RoboVM
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import mindustry.type.TypeID;
|
||||
|
||||
public interface TypeTrait{
|
||||
|
||||
TypeID getTypeID();
|
||||
/*
|
||||
int[] lastRegisteredID = {0};
|
||||
Array<Supplier<? extends TypeTrait>> registeredTypes = new Array<>();
|
||||
ObjectIntMap<Class<? extends TypeTrait>> typeToID = new ObjectIntMap<>();
|
||||
|
||||
/**
|
||||
* Register and return a type ID. The supplier should return a fresh instace of that type.
|
||||
|
||||
static <T extends TypeTrait> void registerType(Class<T> type, Supplier<T> supplier){
|
||||
if(typeToID.get(type, -1) != -1){
|
||||
return; //already registered
|
||||
}
|
||||
|
||||
registeredTypes.add(supplier);
|
||||
int result = lastRegisteredID[0];
|
||||
typeToID.put(type, result);
|
||||
lastRegisteredID[0]++;
|
||||
}
|
||||
|
||||
/**Gets a syncable type by ID.
|
||||
static Supplier<? extends TypeTrait> getTypeByID(int id){
|
||||
if(id == -1){
|
||||
throw new IllegalArgumentException("Attempt to retrieve invalid entity type ID! Did you forget to set it in ContentLoader.registerTypes()?");
|
||||
}
|
||||
return registeredTypes.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type ID of this entity used for intstantiation. Should be < BYTE_MAX.
|
||||
* Do not override!
|
||||
|
||||
default int getTypeID(){
|
||||
int id = typeToID.get(getClass(), -1);
|
||||
if(id == -1)
|
||||
throw new RuntimeException("Class of type '" + getClass() + "' is not registered! Did you forget to register it in ContentLoader#registerTypes()?");
|
||||
return id;
|
||||
}*/
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.math.geom.Vec2;
|
||||
import arc.util.Time;
|
||||
|
||||
public interface VelocityTrait extends MoveTrait{
|
||||
|
||||
Vec2 velocity();
|
||||
|
||||
default void applyImpulse(float x, float y){
|
||||
velocity().x += x / mass();
|
||||
velocity().y += y / mass();
|
||||
}
|
||||
|
||||
default float maxVelocity(){
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
default float mass(){
|
||||
return 1f;
|
||||
}
|
||||
|
||||
default float drag(){
|
||||
return 0f;
|
||||
}
|
||||
|
||||
default void updateVelocity(){
|
||||
velocity().scl(1f - drag() * Time.delta());
|
||||
|
||||
if(this instanceof SolidTrait){
|
||||
((SolidTrait)this).move(velocity().x * Time.delta(), velocity().y * Time.delta());
|
||||
}else{
|
||||
moveBy(velocity().x * Time.delta(), velocity().y * Time.delta());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,6 @@ public abstract class BaseEntity implements Entity{
|
||||
id = lastid++;
|
||||
}
|
||||
|
||||
public int tileX(){
|
||||
return Vars.world.toTile(x);
|
||||
}
|
||||
|
||||
public int tileY(){
|
||||
return Vars.world.toTile(y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID(){
|
||||
return id;
|
||||
|
||||
@@ -36,11 +36,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
protected static final int timerTarget = timerIndex++;
|
||||
protected static final int timerTarget2 = timerIndex++;
|
||||
protected static final int timerShootLeft = timerIndex++;
|
||||
protected static final int timerShootRight = timerIndex++;
|
||||
|
||||
protected boolean loaded;
|
||||
protected UnitType type;
|
||||
protected UnitDef type;
|
||||
protected Interval timer = new Interval(5);
|
||||
protected StateMachine state = new StateMachine();
|
||||
protected TargetTrait target;
|
||||
@@ -76,11 +74,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
Core.app.post(unit::remove);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drag(){
|
||||
return type.drag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeID getTypeID(){
|
||||
return type.typeID;
|
||||
@@ -119,7 +112,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
}
|
||||
|
||||
/** Initialize the type and team of this unit. Only call once! */
|
||||
public void init(UnitType type, Team team){
|
||||
public void init(UnitDef type, Team team){
|
||||
if(this.type != null) throw new RuntimeException("This unit is already initialized!");
|
||||
|
||||
this.type = type;
|
||||
@@ -131,16 +124,12 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
return true;
|
||||
}
|
||||
|
||||
public UnitType getType(){
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setSpawner(Tile tile){
|
||||
this.spawner = tile.pos();
|
||||
}
|
||||
|
||||
public void rotate(float angle){
|
||||
rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed);
|
||||
rotation = Mathf.slerpDelta(rotation, angle, type.rotateSpeed);
|
||||
}
|
||||
|
||||
public boolean targetHasFlag(BlockFlag flag){
|
||||
@@ -179,7 +168,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
}
|
||||
|
||||
public void targetClosest(){
|
||||
TargetTrait newTarget = Units.closestTarget(team, x, y, Math.max(getWeapon().bullet.range(), type.range), u -> type.targetAir || !u.isFlying());
|
||||
TargetTrait newTarget = Units.closestTarget(team, x, y, type.range, u -> type.targetAir || !u.isFlying());
|
||||
if(newTarget != null){
|
||||
target = newTarget;
|
||||
}
|
||||
@@ -210,41 +199,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
return status.getDamageMultiplier() * Vars.state.rules.unitDamageMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmune(StatusEffect effect){
|
||||
return type.immunities.contains(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(){
|
||||
return super.isValid() && isAdded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interval getTimer(){
|
||||
return timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShootTimer(boolean left){
|
||||
return left ? timerShootLeft : timerShootRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weapon getWeapon(){
|
||||
return type.weapon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion getIconRegion(){
|
||||
return type.icon(Cicon.full);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCapacity(){
|
||||
return type.itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate(){
|
||||
super.interpolate();
|
||||
@@ -259,16 +218,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
return type.health * Vars.state.rules.unitHealthMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float mass(){
|
||||
return type.mass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlying(){
|
||||
return type.flying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(isDead()){
|
||||
@@ -312,11 +261,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float maxVelocity(){
|
||||
return type.maxVelocity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
super.removed();
|
||||
@@ -351,16 +295,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitbox(Rect rect){
|
||||
rect.setSize(type.hitsize).setCenter(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitboxTile(Rect rect){
|
||||
rect.setSize(type.hitsizeTile).setCenter(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGroup targetGroup(){
|
||||
return unitGroup;
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
|
||||
import mindustry.entities.traits.*;
|
||||
|
||||
public abstract class DestructibleEntity extends SolidEntity implements HealthTrait{
|
||||
public transient boolean dead;
|
||||
public float health;
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidTrait other){
|
||||
return other instanceof DamageTrait;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(SolidTrait other, float x, float y){
|
||||
if(other instanceof DamageTrait){
|
||||
boolean wasDead = isDead();
|
||||
onHit(other);
|
||||
damage(((DamageTrait)other).damage());
|
||||
if(!wasDead && isDead()){
|
||||
((DamageTrait)other).killed(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void health(float health){
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float health(){
|
||||
return health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead(){
|
||||
return dead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(boolean dead){
|
||||
this.dead = dead;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import arc.graphics.Color;
|
||||
import arc.util.pooling.Pool.Poolable;
|
||||
import arc.util.pooling.Pools;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.Effects.Effect;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.traits.DrawTrait;
|
||||
import mindustry.entities.traits.Entity;
|
||||
import arc.graphics.*;
|
||||
import arc.util.pooling.Pool.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.traits.*;
|
||||
|
||||
import static mindustry.Vars.effectGroup;
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ import static mindustry.Vars.*;
|
||||
public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
public static final int timerSync = 2;
|
||||
public static final int timerAbility = 3;
|
||||
private static final int timerShootLeft = 0;
|
||||
private static final int timerShootRight = 1;
|
||||
private static final float liftoffBoost = 0.2f;
|
||||
|
||||
private static final Rect rect = new Rect();
|
||||
@@ -53,7 +51,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
public float boostHeat, shootHeat, destructTime;
|
||||
public boolean achievedFlight;
|
||||
public Color color = new Color();
|
||||
public Mech mech = Mechs.starter;
|
||||
public UnitDef mech = Mechs.starter;
|
||||
public SpawnerTrait spawner, lastSpawner;
|
||||
public int respawns;
|
||||
|
||||
@@ -90,16 +88,6 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
return status.getDamageMultiplier() * state.rules.playerDamageMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitbox(Rect rect){
|
||||
rect.setSize(mech.hitsize).setCenter(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitboxTile(Rect rect){
|
||||
rect.setSize(mech.hitsize * 2f / 3f).setCenter(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRespawn(Tile tile){
|
||||
velocity.setZero();
|
||||
@@ -127,6 +115,16 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
return TypeIDs.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitDef type(){
|
||||
return mech;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weapons getWeapons(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(float x, float y){
|
||||
if(!mech.flying){
|
||||
@@ -136,29 +134,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drag(){
|
||||
return mech.drag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interval getTimer(){
|
||||
return timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShootTimer(boolean left){
|
||||
return left ? timerShootLeft : timerShootRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weapon getWeapon(){
|
||||
return mech.weapon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinePower(){
|
||||
return mech.mineSpeed;
|
||||
return mech.minePower;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,11 +144,6 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
return mech.icon(Cicon.full);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCapacity(){
|
||||
return mech.itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate(){
|
||||
super.interpolate();
|
||||
@@ -206,7 +179,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
|
||||
@Override
|
||||
public boolean canMine(Item item){
|
||||
return item.hardness <= mech.drillPower;
|
||||
return item.hardness <= mech.drillTier;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -247,11 +220,6 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float maxVelocity(){
|
||||
return mech.maxSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> buildQueue(){
|
||||
return placeQueue;
|
||||
@@ -312,7 +280,10 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
float boostTrnsX = boostHeat * 3f;
|
||||
float boostAng = boostHeat * 40f;
|
||||
|
||||
float light = 0.2f;
|
||||
|
||||
for(int i : Mathf.signs){
|
||||
Draw.colorl(1f-light + Mathf.clamp(ft * i, 0, 1) *light);
|
||||
Draw.rect(mech.legRegion,
|
||||
x + Angles.trnsx(baseRotation, ft * i + boostTrnsY, -boostTrnsX * i),
|
||||
y + Angles.trnsy(baseRotation, ft * i + boostTrnsY, -boostTrnsX * i),
|
||||
@@ -320,6 +291,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
(mech.legRegion.getHeight() - Mathf.clamp(ft * i, 0, 2)) * Draw.scl,
|
||||
baseRotation - 90 + boostAng * i);
|
||||
}
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(mech.baseRegion, x, y, baseRotation - 90);
|
||||
}
|
||||
@@ -333,18 +305,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
Draw.rect(mech.region, x, y, rotation - 90);
|
||||
|
||||
mech.draw(this);
|
||||
|
||||
for(int i : Mathf.signs){
|
||||
float tra = rotation - 90, trY = -mech.weapon.getRecoil(this, i > 0) + mech.weaponOffsetY;
|
||||
float w = i > 0 ? -mech.weapon.region.getWidth() : mech.weapon.region.getWidth();
|
||||
Draw.rect(mech.weapon.region,
|
||||
x + Angles.trnsx(tra, (mech.weaponOffsetX + mech.spreadX(this)) * i, trY),
|
||||
y + Angles.trnsy(tra, (mech.weaponOffsetX + mech.spreadX(this)) * i, trY),
|
||||
w * Draw.scl,
|
||||
mech.weapon.region.getHeight() * Draw.scl,
|
||||
rotation - 90);
|
||||
}
|
||||
|
||||
weapons.draw(this);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@@ -522,7 +483,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
|
||||
boostHeat = Mathf.lerpDelta(boostHeat, (tile != null && tile.solid()) || (isBoosting && ((!movement.isZero() && moved) || !isLocal)) ? 1f : 0f, 0.08f);
|
||||
shootHeat = Mathf.lerpDelta(shootHeat, isShooting() ? 1f : 0f, 0.06f);
|
||||
mech.updateAlt(this); //updated regardless
|
||||
mech.update(this); //updated regardless
|
||||
|
||||
if(boostHeat > liftoffBoost + 0.1f){
|
||||
achievedFlight = true;
|
||||
@@ -530,9 +491,6 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
|
||||
if(boostHeat <= liftoffBoost + 0.05f && achievedFlight && !mech.flying){
|
||||
if(tile != null){
|
||||
if(mech.shake > 1f){
|
||||
Effects.shake(mech.shake, mech.shake, this);
|
||||
}
|
||||
Effects.effect(Fx.unitLand, tile.floor().color, x, y, tile.floor().isLiquid ? 1f : 0.5f);
|
||||
}
|
||||
mech.onLand(this);
|
||||
@@ -620,7 +578,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
|
||||
if(canMove){
|
||||
float baseLerp = mech.getRotationAlpha(this);
|
||||
if(!isShooting() || !mech.turnCursor){
|
||||
if(!isShooting() || !mech.faceTarget){
|
||||
if(!movement.isZero()){
|
||||
rotation = Mathf.slerpDelta(rotation, mech.flying ? velocity.angle() : movement.angle(), 0.13f * baseLerp);
|
||||
}
|
||||
@@ -633,18 +591,19 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
|
||||
protected void updateShooting(){
|
||||
if(!state.isEditor() && isShooting() && mech.canShoot(this)){
|
||||
if(!mech.turnCursor){
|
||||
weapons.update(this);
|
||||
//if(!mech.turnCursor){
|
||||
//shoot forward ignoring cursor
|
||||
mech.weapon.update(this, x + Angles.trnsx(rotation, mech.weapon.targetDistance), y + Angles.trnsy(rotation, mech.weapon.targetDistance));
|
||||
}else{
|
||||
mech.weapon.update(this, pointerX, pointerY);
|
||||
}
|
||||
//mech.weapon.update(this, x + Angles.trnsx(rotation, mech.weapon.targetDistance), y + Angles.trnsy(rotation, mech.weapon.targetDistance));
|
||||
//}else{
|
||||
//mech.weapon.update(this, pointerX, pointerY);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateTouch(){
|
||||
if(Units.invalidateTarget(target, this) &&
|
||||
!(target instanceof TileEntity && ((TileEntity)target).damaged() && target.isValid() && target.getTeam() == team && mech.canHeal && dst(target) < getWeapon().bullet.range() && !(((TileEntity)target).block instanceof BuildBlock))){
|
||||
!(target instanceof TileEntity && ((TileEntity)target).damaged() && target.isValid() && target.getTeam() == team && mech.canHeal && dst(target) < mech.range && !(((TileEntity)target).block instanceof BuildBlock))){
|
||||
target = null;
|
||||
}
|
||||
|
||||
@@ -720,11 +679,11 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
if(target == null){
|
||||
isShooting = false;
|
||||
if(Core.settings.getBool("autotarget")){
|
||||
target = Units.closestTarget(team, x, y, getWeapon().bullet.range(), u -> u.getTeam() != Team.derelict, u -> u.getTeam() != Team.derelict);
|
||||
target = Units.closestTarget(team, x, y, mech.range, u -> u.getTeam() != Team.derelict, u -> u.getTeam() != Team.derelict);
|
||||
|
||||
if(mech.canHeal && target == null){
|
||||
target = Geometry.findClosest(x, y, indexer.getDamaged(Team.sharded));
|
||||
if(target != null && dst(target) > getWeapon().bullet.range()){
|
||||
if(target != null && dst(target) > mech.range){
|
||||
target = null;
|
||||
}else if(target != null){
|
||||
target = ((Tile)target).entity;
|
||||
@@ -735,10 +694,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
setMineTile(null);
|
||||
}
|
||||
}
|
||||
}else if(target.isValid() || (target instanceof TileEntity && ((TileEntity)target).damaged() && target.getTeam() == team &&
|
||||
mech.canHeal && dst(target) < getWeapon().bullet.range())){
|
||||
}else if(target.isValid() || (target instanceof TileEntity && ((TileEntity)target).damaged() && target.getTeam() == team && mech.canHeal && dst(target) < mech.range)){
|
||||
//rotate toward and shoot the target
|
||||
if(mech.turnCursor){
|
||||
if(mech.faceTarget){
|
||||
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import arc.math.geom.Vec2;
|
||||
import mindustry.entities.traits.SolidTrait;
|
||||
|
||||
public abstract class SolidEntity extends BaseEntity implements SolidTrait{
|
||||
protected transient Vec2 velocity = new Vec2(0f, 0.0001f);
|
||||
private transient Vec2 lastPosition = new Vec2();
|
||||
|
||||
@Override
|
||||
public Vec2 lastPosition(){
|
||||
return lastPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec2 velocity(){
|
||||
return velocity;
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,6 @@ import arc.math.geom.Vec2;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.traits.HealthTrait;
|
||||
import mindustry.entities.traits.TargetTrait;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.EventType.BlockDestroyEvent;
|
||||
import mindustry.gen.*;
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait{
|
||||
public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, ShooterTrait{
|
||||
/** Total duration of hit flash effect */
|
||||
public static final float hitDuration = 9f;
|
||||
/** Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks. */
|
||||
@@ -42,11 +42,29 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
public float rotation;
|
||||
|
||||
protected final Interpolator interpolator = new Interpolator();
|
||||
/** status effects */
|
||||
protected final Statuses status = new Statuses();
|
||||
/** current item held */
|
||||
protected final ItemStack item = new ItemStack(content.item(0), 0);
|
||||
/** holds weapon aiming positions and angles */
|
||||
protected final Weapons weapons = new Weapons();
|
||||
|
||||
/** team; can be changed at any time */
|
||||
protected Team team = Team.sharded;
|
||||
/** timers for drowning and getting hit */
|
||||
protected float drownTime, hitTime;
|
||||
/** this unit's type; do not change internally without calling setType(...) */
|
||||
protected UnitDef type;
|
||||
|
||||
public void setType(UnitDef type){
|
||||
this.type = type;
|
||||
clampHealth();
|
||||
weapons.init(this);
|
||||
}
|
||||
|
||||
public UnitDef type(){
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collidesGrid(int x, int y){
|
||||
@@ -58,6 +76,11 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
return team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weapons getWeapons(){
|
||||
return weapons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate(){
|
||||
interpolator.update();
|
||||
@@ -134,6 +157,22 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
return !isDead() && isAdded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitbox(Rect rect){
|
||||
rect.setSize(type.hitsize).setCenter(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitboxTile(Rect rect){
|
||||
rect.setSize(type.hitsizeTile).setCenter(x, y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public float drag(){
|
||||
return type.drag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSave(DataOutput stream) throws IOException{
|
||||
writeSave(stream, false);
|
||||
@@ -186,7 +225,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
}
|
||||
|
||||
public boolean isImmune(StatusEffect effect){
|
||||
return false;
|
||||
return type.immunities.contains(effect);
|
||||
}
|
||||
|
||||
public boolean isOutOfBounds(){
|
||||
@@ -253,7 +292,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
status.update(this);
|
||||
item.amount = Mathf.clamp(this.item.amount, 0, getItemCapacity());
|
||||
|
||||
velocity.limit(maxVelocity()).scl(1f + (status.getSpeedMultiplier() - 1f) * Time.delta());
|
||||
//velocity.limit(maxVelocity()).scl(1f + (status.getSpeedMultiplier() - 1f) * Time.delta());
|
||||
|
||||
if(x < -finalWorldBounds || y < -finalWorldBounds || x >= world.width() * tilesize + finalWorldBounds || y >= world.height() * tilesize + finalWorldBounds){
|
||||
kill();
|
||||
@@ -277,7 +316,6 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
if(x > world.unitWidth()) velocity.x -= (x - world.unitWidth())/warpDst;
|
||||
if(y > world.unitHeight()) velocity.y -= (y - world.unitHeight())/warpDst;
|
||||
|
||||
|
||||
if(isFlying()){
|
||||
drownTime = 0f;
|
||||
move(velocity.x * Time.delta(), velocity.y * Time.delta());
|
||||
@@ -327,7 +365,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
if(Math.abs(py - y) <= 0.0001f) velocity.y = 0f;
|
||||
}
|
||||
|
||||
velocity.scl(Mathf.clamp(1f - drag() * (isFlying() ? 1f : floor.dragMultiplier) * Time.delta()));
|
||||
//velocity.scl(Mathf.clamp(1f - drag() * (isFlying() ? 1f : floor.dragMultiplier) * Time.delta()));
|
||||
}
|
||||
|
||||
public boolean acceptsItem(Item item){
|
||||
@@ -392,7 +430,9 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
}
|
||||
|
||||
public void drawLight(){
|
||||
renderer.lights.add(x, y, 50f, Pal.powerLight, 0.6f);
|
||||
if(type.lightRadius > 0){
|
||||
renderer.lights.add(x, y, type.lightRadius, type.lightColor, 0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawBackItems(float itemtime, boolean number){
|
||||
@@ -449,11 +489,16 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
|
||||
public abstract TextureRegion getIconRegion();
|
||||
|
||||
public abstract Weapon getWeapon();
|
||||
public final int getItemCapacity(){
|
||||
return type.itemCapacity;
|
||||
}
|
||||
|
||||
public abstract int getItemCapacity();
|
||||
@Override
|
||||
public float mass(){
|
||||
return type.mass;
|
||||
}
|
||||
|
||||
public abstract float mass();
|
||||
|
||||
public abstract boolean isFlying();
|
||||
public boolean isFlying(){
|
||||
return type.flying;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public abstract class BaseDrone extends FlyingUnit{
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean countsAsEnemy(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,11 +119,6 @@ public class GroundUnit extends BaseUnit{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weapon getWeapon(){
|
||||
return type.weapon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.mixcol(Color.white, hitTime / hitDuration);
|
||||
|
||||
20
core/src/mindustry/entities/units/WeaponMount.java
Normal file
20
core/src/mindustry/entities/units/WeaponMount.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package mindustry.entities.units;
|
||||
|
||||
import mindustry.type.*;
|
||||
|
||||
public class WeaponMount{
|
||||
/** weapon associated with this mount */
|
||||
public final Weapon weapon;
|
||||
/** reload in frames; 0 means ready to fire */
|
||||
public float reload;
|
||||
/** rotation relative to the unit this mount is on */
|
||||
public float rotation;
|
||||
/** aiming position in world coordinates */
|
||||
public float aimX, aimY;
|
||||
/** side that's being shot - only valid for mirrors */
|
||||
public boolean side;
|
||||
|
||||
public WeaponMount(Weapon weapon){
|
||||
this.weapon = weapon;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user