More components, less entities
This commit is contained in:
@@ -47,21 +47,21 @@ public class Damage{
|
||||
int f = i;
|
||||
Time.run(i * 2f, () -> {
|
||||
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f);
|
||||
Effects.effect(Fx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius));
|
||||
Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius));
|
||||
});
|
||||
}
|
||||
|
||||
if(explosiveness > 15f){
|
||||
Effects.effect(Fx.shockwave, x, y);
|
||||
Fx.shockwave.at(x, y);
|
||||
}
|
||||
|
||||
if(explosiveness > 30f){
|
||||
Effects.effect(Fx.bigShockwave, x, y);
|
||||
Fx.bigShockwave.at(x, y);
|
||||
}
|
||||
|
||||
float shake = Math.min(explosiveness / 4f + 3f, 9f);
|
||||
Effects.shake(shake, shake, x, y);
|
||||
Effects.effect(Fx.dynamicExplosion, x, y, radius / 8f);
|
||||
Fx.dynamicExplosion.at(x, y, radius / 8f);
|
||||
}
|
||||
|
||||
public static void createIncend(float x, float y, float range, int amount){
|
||||
@@ -136,7 +136,7 @@ public class Damage{
|
||||
Vec2 vec = Geometry.raycastRect(x, y, x2, y2, other);
|
||||
|
||||
if(vec != null){
|
||||
Effects.effect(effect, vec.x, vec.y);
|
||||
effect.at(vec.x, vec.y);
|
||||
e.collision(hitter, vec.x, vec.y);
|
||||
hitter.collision(e, vec.x, vec.y);
|
||||
}
|
||||
|
||||
96
core/src/mindustry/entities/Effect.java
Normal file
96
core/src/mindustry/entities/Effect.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package mindustry.entities;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
|
||||
public class Effect{
|
||||
private static final EffectContainer container = new EffectContainer();
|
||||
private static int lastid = 0;
|
||||
|
||||
public final int id;
|
||||
public final Cons<EffectContainer> renderer;
|
||||
public final float lifetime;
|
||||
/** Clip size. */
|
||||
public float size;
|
||||
|
||||
public Effect(float life, float clipsize, Cons<EffectContainer> renderer){
|
||||
this.id = lastid++;
|
||||
this.lifetime = life;
|
||||
this.renderer = renderer;
|
||||
this.size = clipsize;
|
||||
}
|
||||
|
||||
public Effect(float life, Cons<EffectContainer> renderer){
|
||||
this(life, 28f, renderer);
|
||||
}
|
||||
|
||||
public void at(Position pos){
|
||||
Effects.createEffect(this, pos.getX(), pos.getY(), 0, Color.white, null);
|
||||
}
|
||||
|
||||
public void at(Position pos, float rotation){
|
||||
Effects.createEffect(this, pos.getX(), pos.getY(), rotation, Color.white, null);
|
||||
}
|
||||
|
||||
public void at(float x, float y){
|
||||
Effects.createEffect(this, x, y, 0, Color.white, null);
|
||||
}
|
||||
|
||||
public void at(float x, float y, float rotation){
|
||||
Effects.createEffect(this, x, y, rotation, Color.white, null);
|
||||
}
|
||||
|
||||
public void at(float x, float y, float rotation, Color color){
|
||||
Effects.createEffect(this, x, y, rotation, color, null);
|
||||
}
|
||||
|
||||
public void at(float x, float y, float rotation, Color color, Object data){
|
||||
Effects.createEffect(this, x, y, rotation, color, data);
|
||||
}
|
||||
|
||||
public void at(float x, float y, float rotation, Object data){
|
||||
Effects.createEffect(this, x, y, rotation, Color.white, data);
|
||||
}
|
||||
|
||||
public void render(int id, Color color, float life, float rotation, float x, float y, Object data){
|
||||
container.set(id, color, life, lifetime, rotation, x, y, data);
|
||||
renderer.get(container);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public static class EffectContainer implements Scaled{
|
||||
public float x, y, time, lifetime, rotation;
|
||||
public Color color;
|
||||
public int id;
|
||||
public Object data;
|
||||
private EffectContainer innerContainer;
|
||||
|
||||
public void set(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.color = color;
|
||||
this.time = life;
|
||||
this.lifetime = lifetime;
|
||||
this.id = id;
|
||||
this.rotation = rotation;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void scaled(float lifetime, Cons<EffectContainer> cons){
|
||||
if(innerContainer == null) innerContainer = new EffectContainer();
|
||||
if(time <= lifetime){
|
||||
innerContainer.set(id, color, time, lifetime, rotation, x, y, data);
|
||||
cons.get(innerContainer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float fin(){
|
||||
return time / lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +1,23 @@
|
||||
package mindustry.entities;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Effects{
|
||||
private static final EffectContainer container = new EffectContainer();
|
||||
private static Array<Effect> effects = new Array<>();
|
||||
private static ScreenshakeProvider shakeProvider;
|
||||
private static float shakeFalloff = 10000f;
|
||||
private static EffectProvider provider = (effect, color, x, y, rotation, data) -> {
|
||||
EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new);
|
||||
entity.effect = effect;
|
||||
entity.color = color;
|
||||
entity.rotation = rotation;
|
||||
entity.data = data;
|
||||
entity.set(x, y);
|
||||
entity.add();
|
||||
};
|
||||
|
||||
public static void setEffectProvider(EffectProvider prov){
|
||||
provider = prov;
|
||||
}
|
||||
|
||||
public static void setScreenShakeProvider(ScreenshakeProvider provider){
|
||||
shakeProvider = provider;
|
||||
}
|
||||
|
||||
public static void renderEffect(int id, Effect render, Color color, float life, float rotation, float x, float y, Object data){
|
||||
container.set(id, color, life, render.lifetime, rotation, x, y, data);
|
||||
render.draw.render(container);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public static Effect getEffect(int id){
|
||||
if(id >= effects.size || id < 0)
|
||||
throw new IllegalArgumentException("The effect with ID \"" + id + "\" does not exist!");
|
||||
return effects.get(id);
|
||||
}
|
||||
|
||||
public static Array<Effect> all(){
|
||||
return effects;
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, float x, float y, float rotation){
|
||||
provider.createEffect(effect, Color.white, x, y, rotation, null);
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, float x, float y){
|
||||
effect(effect, x, y, 0);
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, Color color, float x, float y){
|
||||
provider.createEffect(effect, color, x, y, 0f, null);
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, Position loc){
|
||||
provider.createEffect(effect, Color.white, loc.getX(), loc.getY(), 0f, null);
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, Color color, float x, float y, float rotation){
|
||||
provider.createEffect(effect, color, x, y, rotation, null);
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, Color color, float x, float y, float rotation, Object data){
|
||||
provider.createEffect(effect, color, x, y, rotation, data);
|
||||
}
|
||||
|
||||
public static void effect(Effect effect, float x, float y, float rotation, Object data){
|
||||
provider.createEffect(effect, Color.white, x, y, rotation, data);
|
||||
}
|
||||
|
||||
/** Default value is 1000. Higher numbers mean more powerful shake (less falloff). */
|
||||
public static void setShakeFalloff(float falloff){
|
||||
shakeFalloff = falloff;
|
||||
}
|
||||
private static final float shakeFalloff = 10000f;
|
||||
|
||||
private static void shake(float intensity, float duration){
|
||||
if(shakeProvider == null) throw new RuntimeException("Screenshake provider is null! Set it first.");
|
||||
shakeProvider.accept(intensity, duration);
|
||||
if(!headless){
|
||||
renderer.shake(intensity, duration);
|
||||
}
|
||||
}
|
||||
|
||||
public static void shake(float intensity, float duration, float x, float y){
|
||||
@@ -100,68 +33,26 @@ public class Effects{
|
||||
shake(intensity, duration, loc.getX(), loc.getY());
|
||||
}
|
||||
|
||||
public interface ScreenshakeProvider{
|
||||
void accept(float intensity, float duration);
|
||||
}
|
||||
public static void createEffect(Effect effect, float x, float y, float rotation, Color color, Object data){
|
||||
if(headless || effect == Fx.none) return;
|
||||
if(Core.settings.getBool("effects")){
|
||||
Rect view = Core.camera.bounds(Tmp.r1);
|
||||
Rect pos = Tmp.r2.setSize(effect.size).setCenter(x, y);
|
||||
|
||||
public static class Effect{
|
||||
private static int lastid = 0;
|
||||
public final int id;
|
||||
public final EffectRenderer draw;
|
||||
public final float lifetime;
|
||||
/** Clip size. */
|
||||
public float size;
|
||||
|
||||
public Effect(float life, float clipsize, EffectRenderer draw){
|
||||
this.id = lastid++;
|
||||
this.lifetime = life;
|
||||
this.draw = draw;
|
||||
this.size = clipsize;
|
||||
effects.add(this);
|
||||
}
|
||||
|
||||
public Effect(float life, EffectRenderer draw){
|
||||
this(life, 28f, draw);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EffectContainer implements Scaled{
|
||||
public float x, y, time, lifetime, rotation;
|
||||
public Color color;
|
||||
public int id;
|
||||
public Object data;
|
||||
private EffectContainer innerContainer;
|
||||
|
||||
public void set(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.color = color;
|
||||
this.time = life;
|
||||
this.lifetime = lifetime;
|
||||
this.id = id;
|
||||
this.rotation = rotation;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void scaled(float lifetime, Cons<EffectContainer> cons){
|
||||
if(innerContainer == null) innerContainer = new EffectContainer();
|
||||
if(time <= lifetime){
|
||||
innerContainer.set(id, color, time, lifetime, rotation, x, y, data);
|
||||
cons.get(innerContainer);
|
||||
if(view.overlaps(pos)){
|
||||
EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new);
|
||||
entity.effect = effect;
|
||||
entity.color.set(color);
|
||||
entity.rotation = rotation;
|
||||
entity.data = data;
|
||||
entity.id++;
|
||||
entity.set(x, y);
|
||||
//if(data instanceof Entity){
|
||||
// entity.setParent((Entity)data);
|
||||
//}
|
||||
//TODO ground effect
|
||||
//effectGroup.add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float fin(){
|
||||
return time / lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
public interface EffectProvider{
|
||||
void createEffect(Effect effect, Color color, float x, float y, float rotation, Object data);
|
||||
}
|
||||
|
||||
public interface EffectRenderer{
|
||||
void render(EffectContainer effect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package mindustry.entities;
|
||||
import arc.struct.Array;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.entities.traits.Entity;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
@@ -3,7 +3,6 @@ package mindustry.entities.bullet;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.gen.*;
|
||||
|
||||
@@ -29,7 +28,7 @@ public class ArtilleryBulletType extends BasicBulletType{
|
||||
super.update(b);
|
||||
|
||||
if(b.timer.get(0, 3 + b.fslope() * 2f)){
|
||||
Effects.effect(trailEffect, backColor, b.x, b.y, b.fslope() * 4f);
|
||||
trailEffect.at(b.x, b.y, b.fslope() * 4f, backColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ public abstract class BulletType extends Content{
|
||||
}
|
||||
|
||||
public void hit(Bullet b, float x, float y){
|
||||
Effects.effect(hitEffect, x, y, b.rot());
|
||||
hitEffect.at(x, y, b.rot());
|
||||
hitSound.at(b);
|
||||
|
||||
Effects.shake(hitShake, hitShake, b);
|
||||
@@ -133,7 +133,7 @@ public abstract class BulletType extends Content{
|
||||
}
|
||||
|
||||
public void despawned(Bullet b){
|
||||
Effects.effect(despawnEffect, b.x, b.y, b.rot());
|
||||
despawnEffect.at(b.x, b.y, b.rot());
|
||||
hitSound.at(b);
|
||||
|
||||
if(fragBullet != null || splashDamageRadius > 0){
|
||||
|
||||
@@ -3,7 +3,6 @@ package mindustry.entities.bullet;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
@@ -49,7 +48,7 @@ public class HealBulletType extends BulletType{
|
||||
tile = tile.link();
|
||||
|
||||
if(tile.entity != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){
|
||||
Effects.effect(Fx.healBlockFull, Pal.heal, tile.drawx(), tile.drawy(), tile.block().size);
|
||||
Fx.healBlockFull.at(tile.drawx(), tile.drawy(), tile.block().size, Pal.heal);
|
||||
tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class LiquidBulletType extends BulletType{
|
||||
|
||||
@Override
|
||||
public void hit(Bullet b, float hitx, float hity){
|
||||
Effects.effect(hitEffect, liquid.color, hitx, hity);
|
||||
hitEffect.at(liquid.color, hitx, hity);
|
||||
Puddle.deposit(world.tileWorld(hitx, hity), liquid, puddleSize);
|
||||
|
||||
if(liquid.temperature <= 0.5f && liquid.flammability < 0.3f){
|
||||
|
||||
@@ -5,7 +5,6 @@ import arc.graphics.g2d.Draw;
|
||||
import arc.math.Angles;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.world.blocks.distribution.MassDriver.DriverBulletData;
|
||||
@@ -94,7 +93,7 @@ public class MassDriverBolt extends BulletType{
|
||||
int amountDropped = Mathf.random(0, data.items[i]);
|
||||
if(amountDropped > 0){
|
||||
float angle = b.rot() + Mathf.range(100f);
|
||||
Effects.effect(Fx.dropItem, Color.white, b.x, b.y, angle, content.item(i));
|
||||
Fx.dropItem.at(b.x, b.y, angle, Color.white, content.item(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import arc.graphics.Color;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.Pal;
|
||||
@@ -32,7 +31,7 @@ public class MissileBulletType extends BasicBulletType{
|
||||
super.update(b);
|
||||
|
||||
if(Mathf.chance(Time.delta() * 0.2)){
|
||||
Effects.effect(Fx.missileTrail, trailColor, b.x, b.y, 2f);
|
||||
Fx.missileTrail.at(b.x, b.y, 2f, trailColor);
|
||||
}
|
||||
|
||||
if(weaveMag > 0){
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.Bits;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.*;
|
||||
@@ -13,8 +14,9 @@ import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.def.EntityComps.MinerComp.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
@@ -22,11 +24,15 @@ import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.BuildBlock.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
import static arc.math.Mathf.dst;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class EntityComps{
|
||||
|
||||
@Component({HealthComp.class, VelComp.class, StatusComp.class, TeamComp.class, ItemsComp.class})
|
||||
@@ -38,7 +44,7 @@ public class EntityComps{
|
||||
Entityc owner;
|
||||
}
|
||||
|
||||
@Component({TimedComp.class, DamageComp.class, Hitboxc.class})
|
||||
@Component({TimedComp.class, DamageComp.class, HitboxComp.class})
|
||||
class BulletComp{
|
||||
BulletType bullet;
|
||||
|
||||
@@ -58,8 +64,8 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DamageComp{
|
||||
abstract float getDamage();
|
||||
class DamageComp{
|
||||
native float getDamage();
|
||||
}
|
||||
|
||||
@Component
|
||||
@@ -146,12 +152,18 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
@Component
|
||||
class TeamComp{
|
||||
abstract class TeamComp{
|
||||
transient float x, y;
|
||||
|
||||
Team team = Team.sharded;
|
||||
|
||||
public @Nullable TileEntity getClosestCore(){
|
||||
return state.teams.closestCore(x, y, team);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({RotComp.class, PosComp.class})
|
||||
static class WeaponsComp{
|
||||
abstract static class WeaponsComp implements Teamc{
|
||||
transient float x, y, rotation;
|
||||
|
||||
/** 1 */
|
||||
@@ -164,7 +176,7 @@ public class EntityComps{
|
||||
/** weapon mount array, never null */
|
||||
WeaponMount[] mounts = {};
|
||||
|
||||
public void init(UnitDef def){
|
||||
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));
|
||||
@@ -172,12 +184,12 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
/** 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);
|
||||
void aim(Unit unit, float x, float y){
|
||||
Tmp.v1.set(x, y).sub(this.x, this.y);
|
||||
if(Tmp.v1.len() < minAimDst) Tmp.v1.setLength(minAimDst);
|
||||
|
||||
x = Tmp.v1.x + unit.x;
|
||||
y = Tmp.v1.y + unit.y;
|
||||
x = Tmp.v1.x + this.x;
|
||||
y = Tmp.v1.y + this.y;
|
||||
|
||||
for(WeaponMount mount : mounts){
|
||||
mount.aimX = x;
|
||||
@@ -186,7 +198,7 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
/** Update shooting and rotation for this unit. */
|
||||
public void update(Unit unit){
|
||||
void update(Unit unit){
|
||||
for(WeaponMount mount : mounts){
|
||||
Weapon weapon = mount.weapon;
|
||||
mount.reload -= Time.delta();
|
||||
@@ -196,8 +208,8 @@ public class EntityComps{
|
||||
//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);
|
||||
float axisX = this.x + Angles.trnsx(rotation, axisXOffset, weapon.y),
|
||||
axisY = this.y + Angles.trnsy(rotation, axisXOffset, weapon.y);
|
||||
|
||||
mount.rotation = Angles.moveToward(mount.rotation, Angles.angle(axisX, axisY, mount.aimX, mount.aimY), weapon.rotateSpeed);
|
||||
}
|
||||
@@ -210,13 +222,13 @@ public class EntityComps{
|
||||
|
||||
//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 mountX = this.x + Angles.trnsx(rotation, weapon.x * i, weapon.y),
|
||||
mountY = this.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);
|
||||
shoot(weapon, shootX, shootY, shootAngle);
|
||||
}
|
||||
|
||||
mount.side = !mount.side;
|
||||
@@ -247,47 +259,50 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
private void shoot(ShooterTrait shooter, Weapon weapon, float x, float y, float rotation){
|
||||
float baseX = shooter.getX(), baseY = shooter.getY();
|
||||
private void shoot(Weapon weapon, float x, float y, float rotation){
|
||||
float baseX = this.x, baseY = this.y;
|
||||
|
||||
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)));
|
||||
Time.run(sequenceNum * weapon.shotDelay, () -> bullet(weapon, x + this.x - baseX, y + this.y - 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)));
|
||||
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy)));
|
||||
}
|
||||
|
||||
BulletType ammo = weapon.bullet;
|
||||
|
||||
Tmp.v1.trns(rotation + 180f, ammo.recoil);
|
||||
|
||||
shooter.velocity().add(Tmp.v1);
|
||||
if(this instanceof Velc){
|
||||
//TODO apply force?
|
||||
((Velc)this).getVel().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);
|
||||
weapon.ejectEffect.at(x, y, rotation);
|
||||
ammo.shootEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? this : null);
|
||||
ammo.smokeEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? this : null);
|
||||
}
|
||||
|
||||
private void bullet(ShooterTrait owner, Weapon weapon, float x, float y, float angle){
|
||||
private void bullet(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));
|
||||
Bullet.create(weapon.bullet, this, getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd));
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DrawComp{
|
||||
class DrawComp{
|
||||
//TODO ponder.
|
||||
|
||||
abstract float drawSize();
|
||||
native float drawSize();
|
||||
|
||||
void draw(){
|
||||
|
||||
@@ -336,21 +351,161 @@ public class EntityComps{
|
||||
void trns(float x, float y){
|
||||
set(this.x + x, this.y + y);
|
||||
}
|
||||
|
||||
int tileX(){
|
||||
return Vars.world.toTile(getX());
|
||||
}
|
||||
|
||||
int tileY(){
|
||||
return Vars.world.toTile(getY());
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class MinerComp{
|
||||
@Component({ItemsComp.class, TeamComp.class, RotComp.class})
|
||||
static abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc{
|
||||
static float miningRange = 70f;
|
||||
|
||||
@Nullable Tile mineTile;
|
||||
|
||||
native boolean canMine(Item item);
|
||||
|
||||
native float getMiningSpeed();
|
||||
|
||||
native boolean offloadImmediately();
|
||||
|
||||
boolean isMining(){
|
||||
return mineTile != null;
|
||||
}
|
||||
|
||||
void updateMining(){
|
||||
TileEntity core = getClosestCore();
|
||||
|
||||
if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && dst(core) < mineTransferRange){
|
||||
int accepted = core.tile.block().acceptStack(item(), getStack().amount, core.tile, unit);
|
||||
if(accepted > 0){
|
||||
Call.transferItemTo(item(), accepted,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
mineTile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
clearItem();
|
||||
}
|
||||
}
|
||||
|
||||
if(mineTile == null || core == null || mineTile.block() != Blocks.air || dst(mineTile.worldx(), mineTile.worldy()) > miningRange
|
||||
|| mineTile.drop() == null || !acceptsItem(mineTile.drop()) || !canMine(mineTile.drop())){
|
||||
mineTile = null;
|
||||
}else{
|
||||
Item item = mineTile.drop();
|
||||
setRotation(Mathf.slerpDelta(getRotation(), angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f));
|
||||
|
||||
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMiningSpeed())){
|
||||
|
||||
if(dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1 && offloadImmediately()){
|
||||
Call.transferItemTo(item, 1,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
mineTile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
}else if(acceptsItem(item)){
|
||||
//this is clientside, since items are synced anyway
|
||||
ItemTransfer.transferItemToUnit(item,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
mineTile.worldy() + Mathf.range(tilesize / 2f),
|
||||
unit);
|
||||
}
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.06 * Time.delta())){
|
||||
Fx.pulverizeSmall.at(mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class BuilderComp{
|
||||
Queue<BuildRequest> requests = new Queue<>();
|
||||
float buildSpeed = 1f;
|
||||
//boolean building;
|
||||
|
||||
void removeBuild(int x, int y, boolean breaking){
|
||||
//remove matching request
|
||||
int idx = player.buildQueue().indexOf(req -> req.breaking == breaking && req.x == x && req.y == y);
|
||||
if(idx != -1){
|
||||
player.buildQueue().removeIndex(idx);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return whether this builder's place queue contains items. */
|
||||
boolean isBuilding(){
|
||||
return requests.size != 0;
|
||||
}
|
||||
|
||||
/** Clears the placement queue. */
|
||||
void clearBuilding(){
|
||||
requests.clear();
|
||||
}
|
||||
|
||||
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
||||
void addBuild(BuildRequest place){
|
||||
addBuild(place, true);
|
||||
}
|
||||
|
||||
/** Add another build requests to the queue, if it doesn't exist there yet. */
|
||||
void addBuild(BuildRequest place, boolean tail){
|
||||
BuildRequest replace = null;
|
||||
for(BuildRequest request : requests){
|
||||
if(request.x == place.x && request.y == place.y){
|
||||
replace = request;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(replace != null){
|
||||
requests.remove(replace);
|
||||
}
|
||||
Tile tile = world.tile(place.x, place.y);
|
||||
if(tile != null && tile.entity instanceof BuildEntity){
|
||||
place.progress = tile.<BuildEntity>ent().progress;
|
||||
}
|
||||
if(tail){
|
||||
requests.addLast(place);
|
||||
}else{
|
||||
requests.addFirst(place);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the build requests currently active, or the one at the top of the queue.*/
|
||||
@Nullable BuildRequest buildRequest(){
|
||||
return requests.size == 0 ? null : requests.first();
|
||||
}
|
||||
}
|
||||
|
||||
@Component(DamageComp.class)
|
||||
class ShielderComp{
|
||||
|
||||
void absorb(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class ItemsComp{
|
||||
ItemStack item = new ItemStack();
|
||||
ItemStack stack = new ItemStack();
|
||||
|
||||
native int getItemCapacity();
|
||||
|
||||
public Item item(){
|
||||
return stack.item;
|
||||
}
|
||||
|
||||
void clearItem(){
|
||||
stack.amount = 0;
|
||||
}
|
||||
|
||||
boolean acceptsItem(Item item){
|
||||
return !hasItem() || item == stack.item && stack.amount + 1 <= getItemCapacity();
|
||||
}
|
||||
|
||||
boolean hasItem(){
|
||||
return stack.amount > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Component(VelComp.class)
|
||||
@@ -543,7 +698,13 @@ public class EntityComps{
|
||||
|
||||
void update(){}
|
||||
|
||||
void remove(){}
|
||||
void remove(){
|
||||
|
||||
}
|
||||
|
||||
void add(){
|
||||
|
||||
}
|
||||
|
||||
boolean isLocal(){
|
||||
//TODO fix
|
||||
|
||||
@@ -4,7 +4,6 @@ import arc.graphics.g2d.Draw;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.entities.traits.BelowLiquidTrait;
|
||||
import mindustry.graphics.Pal;
|
||||
|
||||
import static mindustry.Vars.groundEffectGroup;
|
||||
@@ -12,7 +11,7 @@ import static mindustry.Vars.groundEffectGroup;
|
||||
/**
|
||||
* Class for creating block rubble on the ground.
|
||||
*/
|
||||
public abstract class Decal extends TimedEntity implements BelowLiquidTrait, DrawTrait{
|
||||
public abstract class Decal extends TimedEntity implements DrawTrait{
|
||||
|
||||
@Override
|
||||
public float lifetime(){
|
||||
|
||||
@@ -97,11 +97,11 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait{
|
||||
@Override
|
||||
public void update(){
|
||||
if(Mathf.chance(0.1 * Time.delta())){
|
||||
Effects.effect(Fx.fire, x + Mathf.range(4f), y + Mathf.range(4f));
|
||||
Fx.fire.at(x + Mathf.range(4f), y + Mathf.range(4f));
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.05 * Time.delta())){
|
||||
Effects.effect(Fx.fireSmoke, x + Mathf.range(4f), y + Mathf.range(4f));
|
||||
Fx.fireSmoke.at(x + Mathf.range(4f), y + Mathf.range(4f));
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.001 * Time.delta())){
|
||||
|
||||
@@ -70,7 +70,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
Puddle p = map.get(tile.pos());
|
||||
|
||||
if(generation == 0 && p != null && p.lastRipple <= Time.time() - 40f){
|
||||
Effects.effect(Fx.ripple, tile.floor().liquidDrop.color,
|
||||
Fx.ripple.at(tile.floor().liquidDrop.color,
|
||||
(tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||
p.lastRipple = Time.time();
|
||||
}
|
||||
@@ -93,7 +93,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
p.accepting = Math.max(amount, p.accepting);
|
||||
|
||||
if(generation == 0 && p.lastRipple <= Time.time() - 40f && p.amount >= maxLiquid / 2f){
|
||||
Effects.effect(Fx.ripple, p.liquid.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||
Fx.ripple.at(p.liquid.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||
p.lastRipple = Time.time();
|
||||
}
|
||||
}else{
|
||||
@@ -119,12 +119,12 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
}
|
||||
}else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle
|
||||
if(Mathf.chance(0.5f * amount)){
|
||||
Effects.effect(Fx.steam, x, y);
|
||||
Fx.steam.at(x, y);
|
||||
}
|
||||
return -0.1f * amount;
|
||||
}else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold puddle
|
||||
if(Mathf.chance(0.8f * amount)){
|
||||
Effects.effect(Fx.steam, x, y);
|
||||
Fx.steam.at(x, y);
|
||||
}
|
||||
return -0.4f * amount;
|
||||
}
|
||||
@@ -204,7 +204,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
unit.applyEffect(liquid.effect, 60 * 2);
|
||||
|
||||
if(unit.velocity().len() > 0.1){
|
||||
Effects.effect(Fx.ripple, liquid.color, unit.x, unit.y);
|
||||
Fx.ripple.at(liquid.color, unit.x, unit.y);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
public interface AbsorbTrait extends Entity, TeamTrait, DamageTrait{
|
||||
void absorb();
|
||||
|
||||
default boolean canBeAbsorbed(){
|
||||
return true;
|
||||
}
|
||||
|
||||
default float getShieldDamage(){
|
||||
return damage();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
/**
|
||||
* A flag interface for marking an effect as appearing below liquids.
|
||||
*/
|
||||
public interface BelowLiquidTrait{
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
/** A class for gracefully merging mining and building traits.*/
|
||||
public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{
|
||||
|
||||
default void updateMechanics(){
|
||||
updateBuilding();
|
||||
|
||||
//mine only when not building
|
||||
if(buildRequest() == null){
|
||||
updateMining();
|
||||
}
|
||||
}
|
||||
|
||||
default void drawMechanics(){
|
||||
if(isBuilding()){
|
||||
drawBuilding();
|
||||
}else{
|
||||
drawMining();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
@@ -281,122 +282,4 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
/** Class for storing build requests. Can be either a place or remove request. */
|
||||
class BuildRequest{
|
||||
/** Position and rotation of this request. */
|
||||
public int x, y, rotation;
|
||||
/** Block being placed. If null, this is a breaking request.*/
|
||||
public @Nullable Block block;
|
||||
/** Whether this is a break request.*/
|
||||
public boolean breaking;
|
||||
/** Whether this request comes with a config int. If yes, any blocks placed with this request will not call playerPlaced.*/
|
||||
public boolean hasConfig;
|
||||
/** Config int. Not used unless hasConfig is true.*/
|
||||
public int config;
|
||||
/** Original position, only used in schematics.*/
|
||||
public int originalX, originalY, originalWidth, originalHeight;
|
||||
|
||||
/** Last progress.*/
|
||||
public float progress;
|
||||
/** Whether construction has started for this request, and other special variables.*/
|
||||
public boolean initialized, worldContext = true, stuck;
|
||||
|
||||
/** Visual scale. Used only for rendering.*/
|
||||
public float animScale = 0f;
|
||||
|
||||
/** This creates a build request. */
|
||||
public BuildRequest(int x, int y, int rotation, Block block){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = rotation;
|
||||
this.block = block;
|
||||
this.breaking = false;
|
||||
}
|
||||
|
||||
/** This creates a remove request. */
|
||||
public BuildRequest(int x, int y){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = -1;
|
||||
this.block = world.tile(x, y).block();
|
||||
this.breaking = true;
|
||||
}
|
||||
|
||||
public BuildRequest(){
|
||||
|
||||
}
|
||||
|
||||
public BuildRequest copy(){
|
||||
BuildRequest copy = new BuildRequest();
|
||||
copy.x = x;
|
||||
copy.y = y;
|
||||
copy.rotation = rotation;
|
||||
copy.block = block;
|
||||
copy.breaking = breaking;
|
||||
copy.hasConfig = hasConfig;
|
||||
copy.config = config;
|
||||
copy.originalX = originalX;
|
||||
copy.originalY = originalY;
|
||||
copy.progress = progress;
|
||||
copy.initialized = initialized;
|
||||
copy.animScale = animScale;
|
||||
return copy;
|
||||
}
|
||||
|
||||
public BuildRequest original(int x, int y, int originalWidth, int originalHeight){
|
||||
originalX = x;
|
||||
originalY = y;
|
||||
this.originalWidth = originalWidth;
|
||||
this.originalHeight = originalHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rect bounds(Rect rect){
|
||||
if(breaking){
|
||||
return rect.set(-100f, -100f, 0f, 0f);
|
||||
}else{
|
||||
return block.bounds(x, y, rect);
|
||||
}
|
||||
}
|
||||
|
||||
public BuildRequest set(int x, int y, int rotation, Block block){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = rotation;
|
||||
this.block = block;
|
||||
this.breaking = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float drawx(){
|
||||
return x*tilesize + block.offset();
|
||||
}
|
||||
|
||||
public float drawy(){
|
||||
return y*tilesize + block.offset();
|
||||
}
|
||||
|
||||
public BuildRequest configure(int config){
|
||||
this.config = config;
|
||||
this.hasConfig = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @Nullable Tile tile(){
|
||||
return world.tile(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "BuildRequest{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", rotation=" + rotation +
|
||||
", recipe=" + block +
|
||||
", breaking=" + breaking +
|
||||
", progress=" + progress +
|
||||
", initialized=" + initialized +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import mindustry.*;
|
||||
import mindustry.entities.*;
|
||||
|
||||
public interface Entity extends MoveTrait{
|
||||
|
||||
int getID();
|
||||
|
||||
void resetID(int id);
|
||||
|
||||
default void update(){}
|
||||
|
||||
default void removed(){}
|
||||
|
||||
default void added(){}
|
||||
|
||||
default int tileX(){
|
||||
return Vars.world.toTile(getX());
|
||||
}
|
||||
|
||||
default int tileY(){
|
||||
return Vars.world.toTile(getY());
|
||||
}
|
||||
|
||||
EntityGroup targetGroup();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default void add(){
|
||||
if(targetGroup() != null){
|
||||
targetGroup().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default void remove(){
|
||||
if(getGroup() != null){
|
||||
getGroup().remove(this);
|
||||
}
|
||||
|
||||
setGroup(null);
|
||||
}
|
||||
|
||||
EntityGroup getGroup();
|
||||
|
||||
void setGroup(EntityGroup group);
|
||||
|
||||
default boolean isAdded(){
|
||||
return getGroup() != null;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import mindustry.*;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.traits.Entity;
|
||||
|
||||
public abstract class BaseEntity implements Entity{
|
||||
private static int lastid;
|
||||
|
||||
@@ -18,6 +18,7 @@ import mindustry.core.*;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.input.*;
|
||||
@@ -491,7 +492,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
|
||||
if(boostHeat <= liftoffBoost + 0.05f && achievedFlight && !mech.flying){
|
||||
if(tile != null){
|
||||
Effects.effect(Fx.unitLand, tile.floor().color, x, y, tile.floor().isLiquid ? 1f : 0.5f);
|
||||
Fx.unitLand.at(x, y, tile.floor().isLiquid ? 1f : 0.5f, tile.floor().color);
|
||||
}
|
||||
mech.onLand(this);
|
||||
achievedFlight = false;
|
||||
|
||||
@@ -124,7 +124,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, getSize() / 2f, Pal.darkFlame);
|
||||
|
||||
ScorchDecal.create(x, y);
|
||||
Effects.effect(Fx.explosion, this);
|
||||
Fx.explosion.at(this);
|
||||
Effects.shake(2f, 2f, this);
|
||||
|
||||
Sounds.bang.at(this);
|
||||
@@ -330,7 +330,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
}
|
||||
|
||||
if(onLiquid && velocity.len() > 0.4f && Mathf.chance((velocity.len() * floor.speedMultiplier) * 0.06f * Time.delta())){
|
||||
Effects.effect(floor.walkEffect, floor.color, x, y);
|
||||
floor.walkEffect.at(floor.color, x, y);
|
||||
}
|
||||
|
||||
if(onLiquid){
|
||||
@@ -344,7 +344,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
if(onLiquid && floor.drownTime > 0){
|
||||
drownTime += Time.delta() * 1f / floor.drownTime;
|
||||
if(Mathf.chance(Time.delta() * 0.05f)){
|
||||
Effects.effect(floor.drownUpdateEffect, floor.color, x, y);
|
||||
floor.drownUpdateEffect.at(floor.color, x, y);
|
||||
}
|
||||
}else{
|
||||
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
||||
|
||||
126
core/src/mindustry/entities/units/BuildRequest.java
Normal file
126
core/src/mindustry/entities/units/BuildRequest.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package mindustry.entities.units;
|
||||
|
||||
import arc.math.geom.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** Class for storing build requests. Can be either a place or remove request. */
|
||||
public class BuildRequest{
|
||||
/** Position and rotation of this request. */
|
||||
public int x, y, rotation;
|
||||
/** Block being placed. If null, this is a breaking request.*/
|
||||
public @Nullable Block block;
|
||||
/** Whether this is a break request.*/
|
||||
public boolean breaking;
|
||||
/** Whether this request comes with a config int. If yes, any blocks placed with this request will not call playerPlaced.*/
|
||||
public boolean hasConfig;
|
||||
/** Config int. Not used unless hasConfig is true.*/
|
||||
public int config;
|
||||
/** Original position, only used in schematics.*/
|
||||
public int originalX, originalY, originalWidth, originalHeight;
|
||||
|
||||
/** Last progress.*/
|
||||
public float progress;
|
||||
/** Whether construction has started for this request, and other special variables.*/
|
||||
public boolean initialized, worldContext = true, stuck;
|
||||
|
||||
/** Visual scale. Used only for rendering.*/
|
||||
public float animScale = 0f;
|
||||
|
||||
/** This creates a build request. */
|
||||
public BuildRequest(int x, int y, int rotation, Block block){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = rotation;
|
||||
this.block = block;
|
||||
this.breaking = false;
|
||||
}
|
||||
|
||||
/** This creates a remove request. */
|
||||
public BuildRequest(int x, int y){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = -1;
|
||||
this.block = world.tile(x, y).block();
|
||||
this.breaking = true;
|
||||
}
|
||||
|
||||
public BuildRequest(){
|
||||
|
||||
}
|
||||
|
||||
public BuildRequest copy(){
|
||||
BuildRequest copy = new BuildRequest();
|
||||
copy.x = x;
|
||||
copy.y = y;
|
||||
copy.rotation = rotation;
|
||||
copy.block = block;
|
||||
copy.breaking = breaking;
|
||||
copy.hasConfig = hasConfig;
|
||||
copy.config = config;
|
||||
copy.originalX = originalX;
|
||||
copy.originalY = originalY;
|
||||
copy.progress = progress;
|
||||
copy.initialized = initialized;
|
||||
copy.animScale = animScale;
|
||||
return copy;
|
||||
}
|
||||
|
||||
public BuildRequest original(int x, int y, int originalWidth, int originalHeight){
|
||||
originalX = x;
|
||||
originalY = y;
|
||||
this.originalWidth = originalWidth;
|
||||
this.originalHeight = originalHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rect bounds(Rect rect){
|
||||
if(breaking){
|
||||
return rect.set(-100f, -100f, 0f, 0f);
|
||||
}else{
|
||||
return block.bounds(x, y, rect);
|
||||
}
|
||||
}
|
||||
|
||||
public BuildRequest set(int x, int y, int rotation, Block block){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.rotation = rotation;
|
||||
this.block = block;
|
||||
this.breaking = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float drawx(){
|
||||
return x*tilesize + block.offset();
|
||||
}
|
||||
|
||||
public float drawy(){
|
||||
return y*tilesize + block.offset();
|
||||
}
|
||||
|
||||
public BuildRequest configure(int config){
|
||||
this.config = config;
|
||||
this.hasConfig = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @Nullable Tile tile(){
|
||||
return world.tile(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "BuildRequest{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", rotation=" + rotation +
|
||||
", recipe=" + block +
|
||||
", breaking=" + breaking +
|
||||
", progress=" + progress +
|
||||
", initialized=" + initialized +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user