mirror of
https://github.com/Anuken/Mindustry.git
synced 2024-11-13 07:15:28 +03:00
Refactoring
This commit is contained in:
parent
f937cb30f0
commit
141cf518a2
@ -10,7 +10,14 @@ public class Annotations{
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Component{
|
||||
/** Dependencies. */
|
||||
Class[] value() default {};
|
||||
//Class[] value() default {};
|
||||
}
|
||||
|
||||
/** Indicates priority of a method in an entity. Methods with higher priority are done last. */
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface MethodPriority{
|
||||
float value();
|
||||
}
|
||||
|
||||
/** Indicates that a component def is present on all entities. */
|
||||
|
@ -21,6 +21,7 @@ import javax.lang.model.type.*;
|
||||
public class EntityProcess extends BaseProcessor{
|
||||
Array<Definition> definitions = new Array<>();
|
||||
Array<Stype> baseComponents;
|
||||
ObjectMap<String, Stype> componentNames = new ObjectMap<>();
|
||||
ObjectMap<Stype, Array<Stype>> componentDependencies = new ObjectMap<>();
|
||||
ObjectMap<Stype, Array<Stype>> defComponents = new ObjectMap<>();
|
||||
ObjectSet<String> imports = new ObjectSet<>();
|
||||
@ -36,17 +37,12 @@ public class EntityProcess extends BaseProcessor{
|
||||
if(round == 1){
|
||||
baseComponents = types(BaseComponent.class);
|
||||
Array<Stype> allDefs = types(EntityDef.class);
|
||||
Array<Stype> allComponents = types(Component.class);
|
||||
|
||||
ObjectSet<Stype> allComponents = new ObjectSet<>();
|
||||
|
||||
//find all components used...
|
||||
for(Stype type : allDefs){
|
||||
allComponents.addAll(allComponents(type));
|
||||
for(Stype type : allComponents){
|
||||
componentNames.put(type.name(), type);
|
||||
}
|
||||
|
||||
//add all components w/ dependencies
|
||||
allComponents.addAll(types(Component.class).map(s -> Array.withArrays(getDependencies(s), s)).flatten());
|
||||
|
||||
//add component imports
|
||||
for(Stype comp : allComponents){
|
||||
imports.addAll(getImports(comp.e));
|
||||
@ -57,7 +53,7 @@ public class EntityProcess extends BaseProcessor{
|
||||
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component)).addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
||||
|
||||
//implement extra interfaces these components may have, e.g. position
|
||||
for(Stype extraInterface : component.interfaces()){
|
||||
for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){
|
||||
inter.addSuperinterface(extraInterface.mirror());
|
||||
}
|
||||
|
||||
@ -130,6 +126,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
//add all methods from components
|
||||
for(ObjectMap.Entry<String, Array<Smethod>> entry : methods){
|
||||
entry.value.sort(m -> m.has(MethodPriority.class) ? m.annotation(MethodPriority.class).value() : 0);
|
||||
|
||||
//representative method
|
||||
Smethod first = entry.value.first();
|
||||
//build method using same params/returns
|
||||
@ -261,18 +259,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
Array<Stype> getDependencies(Stype component){
|
||||
if(!componentDependencies.containsKey(component)){
|
||||
ObjectSet<Stype> out = new ObjectSet<>();
|
||||
out.addAll(component.superclasses());
|
||||
//TODO extreme confusion
|
||||
//out.addAll(component.interfaces().select(this::isComponent));
|
||||
|
||||
//get dependency classes
|
||||
if(component.annotation(Component.class) != null){
|
||||
try{
|
||||
component.annotation(Component.class).value();
|
||||
}catch(MirroredTypesException e){
|
||||
out.addAll(Array.with(e.getTypeMirrors()).map(Stype::of));
|
||||
}
|
||||
}
|
||||
//add base component interfaces
|
||||
out.addAll(component.interfaces().select(this::isCompInterface).map(this::interfaceToComp));
|
||||
|
||||
//out now contains the base dependencies; finish constructing the tree
|
||||
ObjectSet<Stype> result = new ObjectSet<>();
|
||||
@ -291,6 +279,15 @@ public class EntityProcess extends BaseProcessor{
|
||||
return componentDependencies.get(component);
|
||||
}
|
||||
|
||||
boolean isCompInterface(Stype type){
|
||||
return interfaceToComp(type) != null;
|
||||
}
|
||||
|
||||
Stype interfaceToComp(Stype type){
|
||||
String name = type.name().substring(0, type.name().length() - 1) + "Comp";
|
||||
return componentNames.get(name);
|
||||
}
|
||||
|
||||
boolean isComponent(Stype type){
|
||||
return type.annotation(Component.class) != null;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import mindustry.annotations.*;
|
||||
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.*;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
public class Selement<T extends Element>{
|
||||
public final T e;
|
||||
@ -13,6 +14,14 @@ public class Selement<T extends Element>{
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public <A extends Annotation> A annotation(Class<A> annotation){
|
||||
return e.getAnnotation(annotation);
|
||||
}
|
||||
|
||||
public <A extends Annotation> boolean has(Class<A> annotation){
|
||||
return e.getAnnotation(annotation) != null;
|
||||
}
|
||||
|
||||
public Element up(){
|
||||
return e.getEnclosingElement();
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import mindustry.annotations.*;
|
||||
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.*;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
public class Stype extends Selement<TypeElement>{
|
||||
|
||||
@ -35,10 +34,6 @@ public class Stype extends Selement<TypeElement>{
|
||||
return new Stype((TypeElement)BaseProcessor.typeu.asElement(BaseProcessor.typeu.directSupertypes(mirror()).get(0)));
|
||||
}
|
||||
|
||||
public <A extends Annotation> A annotation(Class<A> annotation){
|
||||
return e.getAnnotation(annotation);
|
||||
}
|
||||
|
||||
public Array<Svar> fields(){
|
||||
return Array.with(e.getEnclosedElements()).select(e -> e instanceof VariableElement).map(e -> new Svar((VariableElement)e));
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ public class Vars implements Loadable{
|
||||
public static EntityGroup<Fire> fireGroup;
|
||||
public static EntityGroup<BaseUnit> unitGroup;
|
||||
|
||||
public static Player player;
|
||||
public static Unitc player;
|
||||
|
||||
@Override
|
||||
public void loadAsync(){
|
||||
|
@ -13,7 +13,6 @@ import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@ -365,8 +364,8 @@ public class NetClient implements ApplicationListener{
|
||||
if(created && entity.getInterpolator() != null && entity.getInterpolator().target != null){
|
||||
//set initial starting position
|
||||
entity.setNet(entity.getInterpolator().target.x, entity.getInterpolator().target.y);
|
||||
if(entity instanceof Unit && entity.getInterpolator().targets.length > 0){
|
||||
((Unit)entity).rotation = entity.getInterpolator().targets[0];
|
||||
if(entity instanceof Unitc && entity.getInterpolator().targets.length > 0){
|
||||
((Unitc)entity).rotation = entity.getInterpolator().targets[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.graphics.*;
|
||||
@ -306,7 +305,7 @@ public class Renderer implements ApplicationListener{
|
||||
Draw.color(0, 0, 0, 0.4f);
|
||||
float rad = 1.6f;
|
||||
|
||||
Cons<Unit> draw = u -> {
|
||||
Cons<Unitc> draw = u -> {
|
||||
float size = Math.max(u.getIconRegion().getWidth(), u.getIconRegion().getHeight()) * Draw.scl;
|
||||
Draw.rect("circle-shadow", u.x, u.y, size * rad, size * rad);
|
||||
};
|
||||
@ -331,14 +330,14 @@ public class Renderer implements ApplicationListener{
|
||||
}
|
||||
|
||||
private void drawAllTeams(boolean flying){
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
||||
playerGroup.draw(p -> p.isFlying() == flying && !p.isDead(), Unit::drawUnder);
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unitc::drawUnder);
|
||||
playerGroup.draw(p -> p.isFlying() == flying && !p.isDead(), Unitc::drawUnder);
|
||||
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
|
||||
playerGroup.draw(p -> p.isFlying() == flying, Unit::drawAll);
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unitc::drawAll);
|
||||
playerGroup.draw(p -> p.isFlying() == flying, Unitc::drawAll);
|
||||
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
||||
playerGroup.draw(p -> p.isFlying() == flying, Unit::drawOver);
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unitc::drawOver);
|
||||
playerGroup.draw(p -> p.isFlying() == flying, Unitc::drawOver);
|
||||
}
|
||||
|
||||
public void scaleCamera(float amount){
|
||||
|
@ -9,7 +9,6 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@ -125,7 +124,7 @@ public class Damage{
|
||||
rect.width += expand * 2;
|
||||
rect.height += expand * 2;
|
||||
|
||||
Cons<Unit> cons = e -> {
|
||||
Cons<Unitc> cons = e -> {
|
||||
e.hitbox(hitrect);
|
||||
Rect other = hitrect;
|
||||
other.y -= expand;
|
||||
@ -146,8 +145,8 @@ public class Damage{
|
||||
}
|
||||
|
||||
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
||||
public static void damageUnits(Team team, float x, float y, float size, float damage, Boolf<Unit> predicate, Cons<Unit> acceptor){
|
||||
Cons<Unit> cons = entity -> {
|
||||
public static void damageUnits(Team team, float x, float y, float size, float damage, Boolf<Unitc> predicate, Cons<Unitc> acceptor){
|
||||
Cons<Unitc> cons = entity -> {
|
||||
if(!predicate.get(entity)) return;
|
||||
|
||||
entity.hitbox(hitrect);
|
||||
@ -178,7 +177,7 @@ public class Damage{
|
||||
|
||||
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
||||
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete){
|
||||
Cons<Unit> cons = entity -> {
|
||||
Cons<Unitc> cons = entity -> {
|
||||
if(entity.getTeam() == team || entity.dst(x, y) > radius){
|
||||
return;
|
||||
}
|
||||
|
8
core/src/mindustry/entities/SaveTrait.java
Normal file
8
core/src/mindustry/entities/SaveTrait.java
Normal file
@ -0,0 +1,8 @@
|
||||
package mindustry.entities;
|
||||
|
||||
/**
|
||||
* Marks an entity as serializable.
|
||||
*/
|
||||
public interface SaveTrait extends Saveable{
|
||||
byte version();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package mindustry.entities.traits;
|
||||
package mindustry.entities;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -3,7 +3,6 @@ package mindustry.entities;
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.world.*;
|
||||
@ -13,7 +12,7 @@ import static mindustry.Vars.*;
|
||||
/** Utility class for unit and team interactions.*/
|
||||
public class Units{
|
||||
private static Rect hitrect = new Rect();
|
||||
private static Unit result;
|
||||
private static Unitc result;
|
||||
private static float cdist;
|
||||
private static boolean boolResult;
|
||||
|
||||
@ -41,7 +40,7 @@ public class Units{
|
||||
}
|
||||
|
||||
/** See {@link #invalidateTarget(TargetTrait, Team, float, float, float)} */
|
||||
public static boolean invalidateTarget(TargetTrait target, Unit targeter){
|
||||
public static boolean invalidateTarget(TargetTrait target, Unitc targeter){
|
||||
return invalidateTarget(target, targeter.getTeam(), targeter.x, targeter.y, targeter.getWeapon().bullet.range());
|
||||
}
|
||||
|
||||
@ -88,19 +87,19 @@ public class Units{
|
||||
|
||||
/** Returns the closest target enemy. First, units are checked, then tile entities. */
|
||||
public static TargetTrait closestTarget(Team team, float x, float y, float range){
|
||||
return closestTarget(team, x, y, range, Unit::isValid);
|
||||
return closestTarget(team, x, y, range, Unitc::isValid);
|
||||
}
|
||||
|
||||
/** Returns the closest target enemy. First, units are checked, then tile entities. */
|
||||
public static TargetTrait closestTarget(Team team, float x, float y, float range, Boolf<Unit> unitPred){
|
||||
public static TargetTrait closestTarget(Team team, float x, float y, float range, Boolf<Unitc> unitPred){
|
||||
return closestTarget(team, x, y, range, unitPred, t -> true);
|
||||
}
|
||||
|
||||
/** Returns the closest target enemy. First, units are checked, then tile entities. */
|
||||
public static TargetTrait closestTarget(Team team, float x, float y, float range, Boolf<Unit> unitPred, Boolf<Tile> tilePred){
|
||||
public static TargetTrait closestTarget(Team team, float x, float y, float range, Boolf<Unitc> unitPred, Boolf<Tile> tilePred){
|
||||
if(team == Team.derelict) return null;
|
||||
|
||||
Unit unit = closestEnemy(team, x, y, range, unitPred);
|
||||
Unitc unit = closestEnemy(team, x, y, range, unitPred);
|
||||
if(unit != null){
|
||||
return unit;
|
||||
}else{
|
||||
@ -109,7 +108,7 @@ public class Units{
|
||||
}
|
||||
|
||||
/** Returns the closest enemy of this team. Filter by predicate. */
|
||||
public static Unit closestEnemy(Team team, float x, float y, float range, Boolf<Unit> predicate){
|
||||
public static Unitc closestEnemy(Team team, float x, float y, float range, Boolf<Unitc> predicate){
|
||||
if(team == Team.derelict) return null;
|
||||
|
||||
result = null;
|
||||
@ -129,7 +128,7 @@ public class Units{
|
||||
}
|
||||
|
||||
/** Returns the closest ally of this team. Filter by predicate. */
|
||||
public static Unit closest(Team team, float x, float y, float range, Boolf<Unit> predicate){
|
||||
public static Unitc closest(Team team, float x, float y, float range, Boolf<Unitc> predicate){
|
||||
result = null;
|
||||
cdist = 0f;
|
||||
|
||||
@ -147,7 +146,7 @@ public class Units{
|
||||
}
|
||||
|
||||
/** Iterates over all units in a rectangle. */
|
||||
public static void nearby(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
||||
public static void nearby(Team team, float x, float y, float width, float height, Cons<Unitc> cons){
|
||||
unitGroup.intersect(x, y, width, height, u -> {
|
||||
if(u.getTeam() == team){
|
||||
cons.get(u);
|
||||
@ -161,7 +160,7 @@ public class Units{
|
||||
}
|
||||
|
||||
/** Iterates over all units in a circle around this position. */
|
||||
public static void nearby(Team team, float x, float y, float radius, Cons<Unit> cons){
|
||||
public static void nearby(Team team, float x, float y, float radius, Cons<Unitc> cons){
|
||||
unitGroup.intersect(x - radius, y - radius, radius*2f, radius*2f, unit -> {
|
||||
if(unit.getTeam() == team && unit.withinDst(x, y, radius)){
|
||||
cons.get(unit);
|
||||
@ -176,18 +175,18 @@ public class Units{
|
||||
}
|
||||
|
||||
/** Iterates over all units in a rectangle. */
|
||||
public static void nearby(float x, float y, float width, float height, Cons<Unit> cons){
|
||||
public static void nearby(float x, float y, float width, float height, Cons<Unitc> cons){
|
||||
unitGroup.intersect(x, y, width, height, cons);
|
||||
playerGroup.intersect(x, y, width, height, cons);
|
||||
}
|
||||
|
||||
/** Iterates over all units in a rectangle. */
|
||||
public static void nearby(Rect rect, Cons<Unit> cons){
|
||||
public static void nearby(Rect rect, Cons<Unitc> cons){
|
||||
nearby(rect.x, rect.y, rect.width, rect.height, cons);
|
||||
}
|
||||
|
||||
/** Iterates over all units that are enemies of this team. */
|
||||
public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
||||
public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons<Unitc> cons){
|
||||
unitGroup.intersect(x, y, width, height, u -> {
|
||||
if(team.isEnemy(u.getTeam())){
|
||||
cons.get(u);
|
||||
@ -202,12 +201,12 @@ public class Units{
|
||||
}
|
||||
|
||||
/** Iterates over all units that are enemies of this team. */
|
||||
public static void nearbyEnemies(Team team, Rect rect, Cons<Unit> cons){
|
||||
public static void nearbyEnemies(Team team, Rect rect, Cons<Unitc> cons){
|
||||
nearbyEnemies(team, rect.x, rect.y, rect.width, rect.height, cons);
|
||||
}
|
||||
|
||||
/** Iterates over all units. */
|
||||
public static void all(Cons<Unit> cons){
|
||||
public static void all(Cons<Unitc> cons){
|
||||
unitGroup.all().each(cons);
|
||||
playerGroup.all().each(cons);
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
package mindustry.entities.def;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.Bits;
|
||||
import arc.struct.Queue;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
@ -15,64 +18,154 @@ import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
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.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.BuildBlock.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static arc.math.Mathf.dst;
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.entities.traits.BuilderTrait.BuildDataStatic.tmptr;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class EntityComps{
|
||||
|
||||
@Component({HealthComp.class, VelComp.class, StatusComp.class, TeamComp.class, ItemsComp.class})
|
||||
class UnitComp{
|
||||
@Component
|
||||
abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitboxc, Rotc{
|
||||
UnitDef type;
|
||||
UnitController controller;
|
||||
|
||||
float getBounds(){
|
||||
return getHitSize() * 2f;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
//apply knockback based on spawns
|
||||
//TODO move elsewhere
|
||||
if(getTeam() != state.rules.waveTeam){
|
||||
float relativeSize = state.rules.dropZoneRadius + getBounds()/2f + 1f;
|
||||
for(Tile spawn : spawner.getGroundSpawns()){
|
||||
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||
getVel().add(Tmp.v1.set(this).sub(spawn.worldx(), spawn.worldy()).setLength(0.1f + 1f - dst(spawn) / relativeSize).scl(0.45f * Time.delta()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tile tile = tileOn();
|
||||
Floor floor = floorOn();
|
||||
|
||||
if(tile != null){
|
||||
//unit block update
|
||||
tile.block().unitOn(tile, (mindustry.gen.Unitc)this);
|
||||
|
||||
//apply damage
|
||||
if(floor.damageTaken > 0f){
|
||||
damageContinuous(floor.damageTaken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawLight(){
|
||||
//TODO move
|
||||
if(type.lightRadius > 0){
|
||||
renderer.lights.add(getX(), getY(), type.lightRadius, type.lightColor, 0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(){
|
||||
//draw power cell - TODO move
|
||||
Draw.color(Color.black, getTeam().color, healthf() + Mathf.absin(Time.time(), Math.max(healthf() * 5f, 1f), 1f - healthf()));
|
||||
Draw.rect(type.cellRegion, getX(), getY(), getRotation() - 90);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
public void killed(){
|
||||
float explosiveness = 2f + item().explosiveness * getStack().amount;
|
||||
float flammability = item().flammability * getStack().amount;
|
||||
Damage.dynamicExplosion(getX(), getY(), flammability, explosiveness, 0f, getBounds() / 2f, Pal.darkFlame);
|
||||
|
||||
//TODO cleanup
|
||||
ScorchDecal.create(getX(), getY());
|
||||
Fx.explosion.at(this);
|
||||
Effects.shake(2f, 2f, this);
|
||||
|
||||
Sounds.bang.at(this);
|
||||
Events.fire(new UnitDestroyEvent((mindustry.gen.Unitc)this));
|
||||
|
||||
//TODO implement suicide bomb trigger
|
||||
//if(explosiveness > 7f && this == player){
|
||||
// Events.fire(Trigger.suicideBomb);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class OwnerComp{
|
||||
Entityc owner;
|
||||
}
|
||||
|
||||
@Component({TimedComp.class, DamageComp.class, HitboxComp.class})
|
||||
class BulletComp{
|
||||
@Component
|
||||
abstract class ChildComp implements Posc{
|
||||
transient float x, y;
|
||||
|
||||
private @Nullable Posc parent;
|
||||
private float offsetX, offsetY;
|
||||
|
||||
public void add(){
|
||||
if(parent != null){
|
||||
offsetX = x - parent.getX();
|
||||
offsetY = y - parent.getY();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(parent != null){
|
||||
x = parent.getX() + offsetX;
|
||||
y = parent.getY() + offsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc{
|
||||
BulletType bullet;
|
||||
|
||||
float getDamage(){
|
||||
public float getDamage(){
|
||||
return bullet.damage;
|
||||
}
|
||||
|
||||
void init(){
|
||||
public void init(){
|
||||
//TODO
|
||||
bullet.init(null);
|
||||
}
|
||||
|
||||
void remove(){
|
||||
public void remove(){
|
||||
//TODO
|
||||
bullet.despawned(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class DamageComp{
|
||||
native float getDamage();
|
||||
abstract class DamageComp{
|
||||
abstract float getDamage();
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class TimedComp extends EntityComp implements Scaled{
|
||||
abstract class TimedComp implements Entityc, Scaled{
|
||||
float time, lifetime;
|
||||
|
||||
void update(){
|
||||
public void update(){
|
||||
time = Math.min(time + Time.delta(), lifetime);
|
||||
|
||||
if(time >= lifetime){
|
||||
@ -87,16 +180,22 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
@Component
|
||||
class HealthComp{
|
||||
abstract class HealthComp implements Entityc{
|
||||
static final float hitDuration = 9f;
|
||||
|
||||
float health, maxHealth, hitTime;
|
||||
boolean dead;
|
||||
|
||||
boolean isValid(){
|
||||
return !dead && isAdded();
|
||||
}
|
||||
|
||||
float healthf(){
|
||||
return health / maxHealth;
|
||||
}
|
||||
|
||||
void update(){
|
||||
hitTime -= Time.delta() / 9f;
|
||||
public void update(){
|
||||
hitTime -= Time.delta() / hitDuration;
|
||||
}
|
||||
|
||||
void killed(){
|
||||
@ -125,6 +224,20 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
void damage(float amount, boolean withEffect){
|
||||
float pre = hitTime;
|
||||
|
||||
damage(amount);
|
||||
|
||||
if(!withEffect){
|
||||
hitTime = pre;
|
||||
}
|
||||
}
|
||||
|
||||
void damageContinuous(float amount){
|
||||
damage(amount * Time.delta(), hitTime <= -20 + hitDuration);
|
||||
}
|
||||
|
||||
void clampHealth(){
|
||||
health = Mathf.clamp(health, 0, maxHealth);
|
||||
}
|
||||
@ -136,23 +249,67 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
@Component
|
||||
class FlyingComp{
|
||||
boolean flying;
|
||||
abstract class FlyingComp implements Posc, Velc, Healthc{
|
||||
transient float x, y;
|
||||
transient Vec2 vel;
|
||||
|
||||
float elevation;
|
||||
float drownTime;
|
||||
|
||||
boolean isGrounded(){
|
||||
return elevation < 0.001f;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
Floor floor = floorOn();
|
||||
|
||||
if(isGrounded() && floor.isLiquid && vel.len2() > 0.4f*0.4f && Mathf.chance((vel.len2() * floor.speedMultiplier) * 0.03f * Time.delta())){
|
||||
floor.walkEffect.at(x, y, 0, floor.color);
|
||||
}
|
||||
|
||||
if(isGrounded() && floor.isLiquid && floor.drownTime > 0){
|
||||
drownTime += Time.delta() * 1f / floor.drownTime;
|
||||
drownTime = Mathf.clamp(drownTime);
|
||||
if(Mathf.chance(Time.delta() * 0.05f)){
|
||||
floor.drownUpdateEffect.at(getX(), getY(), 0f, floor.color);
|
||||
}
|
||||
|
||||
//TODO is the netClient check necessary?
|
||||
if(drownTime >= 0.999f && !net.client()){
|
||||
kill();
|
||||
//TODO drown event!
|
||||
}
|
||||
}else{
|
||||
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class LegsComp{
|
||||
abstract class LegsComp implements Posc, Flyingc{
|
||||
float baseRotation;
|
||||
float drownTime;
|
||||
}
|
||||
|
||||
@Component
|
||||
class RotComp{
|
||||
float rotation;
|
||||
|
||||
void interpolate(){
|
||||
Syncc sync = (Syncc)this;
|
||||
|
||||
if(sync.getInterpolator().values.length > 0){
|
||||
rotation = sync.getInterpolator().values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class TileComp implements Posc, Teamc{
|
||||
Tile tile;
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class TeamComp{
|
||||
abstract class TeamComp implements Posc{
|
||||
transient float x, y;
|
||||
|
||||
Team team = Team.sharded;
|
||||
@ -162,8 +319,8 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Component({RotComp.class, PosComp.class})
|
||||
abstract static class WeaponsComp implements Teamc{
|
||||
@Component
|
||||
abstract static class WeaponsComp implements Teamc, Posc, Rotc{
|
||||
transient float x, y, rotation;
|
||||
|
||||
/** 1 */
|
||||
@ -184,7 +341,7 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
/** Aim at something. This will make all mounts point at it. */
|
||||
void aim(Unit unit, float x, float y){
|
||||
void aim(Unitc unit, float x, float y){
|
||||
Tmp.v1.set(x, y).sub(this.x, this.y);
|
||||
if(Tmp.v1.len() < minAimDst) Tmp.v1.setLength(minAimDst);
|
||||
|
||||
@ -198,12 +355,12 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
/** Update shooting and rotation for this unit. */
|
||||
void update(Unit unit){
|
||||
public void update(){
|
||||
for(WeaponMount mount : mounts){
|
||||
Weapon weapon = mount.weapon;
|
||||
mount.reload -= Time.delta();
|
||||
|
||||
float rotation = unit.rotation - 90;
|
||||
float rotation = this.rotation - 90;
|
||||
|
||||
//rotate if applicable
|
||||
if(weapon.rotate){
|
||||
@ -294,39 +451,115 @@ public class EntityComps{
|
||||
|
||||
private void bullet(Weapon weapon, float x, float y, float angle){
|
||||
Tmp.v1.trns(angle, 3f);
|
||||
Bullet.create(weapon.bullet, this, getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd));
|
||||
//TODO create the bullet
|
||||
//Bullet.create(weapon.bullet, this, getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd));
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class DrawComp{
|
||||
//TODO ponder.
|
||||
abstract static class DrawShadowComp implements Drawc, Rotc, Flyingc{
|
||||
static final float shadowTX = -12, shadowTY = -13, shadowColor = Color.toFloatBits(0, 0, 0, 0.22f);
|
||||
|
||||
native float drawSize();
|
||||
transient float x, y, rotation;
|
||||
|
||||
abstract TextureRegion getShadowRegion();
|
||||
|
||||
void drawShadow(){
|
||||
if(!isGrounded()){
|
||||
Draw.color(shadowColor);
|
||||
Draw.rect(getShadowRegion(), x + shadowTX * getElevation(), y + shadowTY * getElevation(), rotation - 90);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DrawItemsComp implements Drawc, Itemsc, Posc, Rotc{
|
||||
transient float x, y, rotation;
|
||||
|
||||
float itemTime;
|
||||
|
||||
//drawn after base
|
||||
@MethodPriority(3)
|
||||
public void draw(){
|
||||
boolean number = isLocal();
|
||||
itemTime = Mathf.lerpDelta(itemTime, Mathf.num(hasItem()), 0.05f);
|
||||
|
||||
//draw back items
|
||||
if(itemTime > 0.01f){
|
||||
float backTrns = 5f;
|
||||
float size = (itemSize + Mathf.absin(Time.time(), 5f, 1f)) * itemTime;
|
||||
|
||||
Draw.mixcol(Pal.accent, Mathf.absin(Time.time(), 5f, 0.5f));
|
||||
Draw.rect(item().icon(Cicon.medium),
|
||||
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||
y + Angles.trnsy(rotation + 180f, backTrns),
|
||||
size, size, rotation);
|
||||
|
||||
Draw.mixcol();
|
||||
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Lines.circle(
|
||||
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||
y + Angles.trnsy(rotation + 180f, backTrns),
|
||||
(3f + Mathf.absin(Time.time(), 5f, 1f)) * itemTime);
|
||||
|
||||
if(isLocal()){
|
||||
Fonts.outline.draw(getStack().amount + "",
|
||||
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||
y + Angles.trnsy(rotation + 180f, backTrns) - 3,
|
||||
Pal.accent, 0.25f * itemTime / Scl.scl(1f), false, Align.center
|
||||
);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DrawLightComp implements Drawc{
|
||||
void drawLight(){}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DrawOverComp implements Drawc{
|
||||
void drawOver(){}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DrawUnderComp implements Drawc{
|
||||
void drawUnder(){}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class DrawComp{
|
||||
|
||||
abstract float clipSize();
|
||||
|
||||
void draw(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Component(PosComp.class)
|
||||
abstract class SyncComp extends PosComp{
|
||||
@Component
|
||||
abstract class SyncComp implements Posc{
|
||||
transient float x, y;
|
||||
|
||||
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;
|
||||
}
|
||||
interpolator.target.set(x, y);
|
||||
interpolator.last.set(x, y);
|
||||
interpolator.pos.set(0, 0);
|
||||
interpolator.updateSpacing = 16;
|
||||
interpolator.lastUpdated = 0;
|
||||
}
|
||||
|
||||
void update(){
|
||||
public void update(){
|
||||
if(Vars.net.client() && !isLocal()){
|
||||
interpolate();
|
||||
}
|
||||
@ -340,7 +573,35 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class PosComp extends EntityComp implements Position{
|
||||
abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
|
||||
static final float warpDst = 180f;
|
||||
|
||||
transient float x, y;
|
||||
transient Vec2 vel;
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
//repel unit out of bounds
|
||||
if(x < 0) vel.x += (-x/warpDst);
|
||||
if(y < 0) vel.y += (-y/warpDst);
|
||||
if(x > world.unitWidth()) vel.x -= (x - world.unitWidth())/warpDst;
|
||||
if(y > world.unitHeight()) vel.y -= (y - world.unitHeight())/warpDst;
|
||||
|
||||
//clamp position if not flying
|
||||
if(isGrounded()){
|
||||
x = Mathf.clamp(x, 0, world.width() * tilesize - tilesize);
|
||||
y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize);
|
||||
}
|
||||
|
||||
//kill when out of bounds
|
||||
if(x < -finalWorldBounds || y < -finalWorldBounds || x >= world.width() * tilesize + finalWorldBounds || y >= world.height() * tilesize + finalWorldBounds){
|
||||
kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class PosComp implements Position{
|
||||
float x, y;
|
||||
|
||||
void set(float x, float y){
|
||||
@ -359,19 +620,31 @@ public class EntityComps{
|
||||
int tileY(){
|
||||
return Vars.world.toTile(getY());
|
||||
}
|
||||
|
||||
/** Returns air if this unit is on a non-air top block. */
|
||||
public Floor floorOn(){
|
||||
Tile tile = tileOn();
|
||||
return tile == null || tile.block() != Blocks.air ? (Floor)Blocks.air : tile.floor();
|
||||
}
|
||||
|
||||
public @Nullable Tile tileOn(){
|
||||
return world.tileWorld(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({ItemsComp.class, TeamComp.class, RotComp.class})
|
||||
@Component
|
||||
static abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc{
|
||||
static float miningRange = 70f;
|
||||
|
||||
transient float x, y, rotation;
|
||||
|
||||
@Nullable Tile mineTile;
|
||||
|
||||
native boolean canMine(Item item);
|
||||
abstract boolean canMine(Item item);
|
||||
|
||||
native float getMiningSpeed();
|
||||
abstract float getMiningSpeed();
|
||||
|
||||
native boolean offloadImmediately();
|
||||
abstract boolean offloadImmediately();
|
||||
|
||||
boolean isMining(){
|
||||
return mineTile != null;
|
||||
@ -381,7 +654,7 @@ public class EntityComps{
|
||||
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);
|
||||
int accepted = core.tile.block().acceptStack(item(), getStack().amount, core.tile, this);
|
||||
if(accepted > 0){
|
||||
Call.transferItemTo(item(), accepted,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
@ -399,7 +672,7 @@ public class EntityComps{
|
||||
|
||||
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()){
|
||||
if(dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, this) == 1 && offloadImmediately()){
|
||||
Call.transferItemTo(item, 1,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
mineTile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
@ -408,7 +681,7 @@ public class EntityComps{
|
||||
ItemTransfer.transferItemToUnit(item,
|
||||
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||
mineTile.worldy() + Mathf.range(tilesize / 2f),
|
||||
unit);
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,19 +690,136 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawOver(){
|
||||
if(!isMining()) return;
|
||||
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||
float swingScl = 12f, swingMag = tilesize / 8f;
|
||||
float flashScl = 0.3f;
|
||||
|
||||
float px = x + Angles.trnsx(rotation, focusLen);
|
||||
float py = y + Angles.trnsy(rotation, focusLen);
|
||||
|
||||
float ex = mineTile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
|
||||
float ey = mineTile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
|
||||
|
||||
Draw.color(Color.lightGray, Color.white, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
|
||||
|
||||
Drawf.laser(Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f);
|
||||
|
||||
//TODO hack?
|
||||
if(isLocal()){
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Lines.poly(mineTile.worldx(), mineTile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class BuilderComp{
|
||||
abstract static class BuilderComp implements mindustry.gen.Unitc{
|
||||
static final float placeDistance = 220f;
|
||||
static final Vec2[] tmptr = new Vec2[]{new Vec2(), new Vec2(), new Vec2(), new Vec2()};
|
||||
|
||||
transient float x, y, rotation;
|
||||
|
||||
Queue<BuildRequest> requests = new Queue<>();
|
||||
float buildSpeed = 1f;
|
||||
//boolean building;
|
||||
|
||||
void updateBuilding(){
|
||||
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : placeDistance;
|
||||
|
||||
Iterator<BuildRequest> it = requests.iterator();
|
||||
while(it.hasNext()){
|
||||
BuildRequest req = it.next();
|
||||
Tile tile = world.tile(req.x, req.y);
|
||||
if(tile == null || (req.breaking && tile.block() == Blocks.air) || (!req.breaking && (tile.rotation() == req.rotation || !req.block.rotate) && tile.block() == req.block)){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
TileEntity core = getClosestCore();
|
||||
|
||||
//nothing to build.
|
||||
if(buildRequest() == null) return;
|
||||
|
||||
//find the next build request
|
||||
if(requests.size > 1){
|
||||
int total = 0;
|
||||
BuildRequest req;
|
||||
while((dst((req = buildRequest()).tile()) > finalPlaceDst || shouldSkip(req, core)) && total < requests.size){
|
||||
requests.removeFirst();
|
||||
requests.addLast(req);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
BuildRequest current = buildRequest();
|
||||
|
||||
if(dst(current.tile()) > finalPlaceDst) return;
|
||||
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
|
||||
if(!(tile.block() instanceof BuildBlock)){
|
||||
if(!current.initialized && !current.breaking && Build.validPlace(getTeam(), current.x, current.y, current.block, current.rotation)){
|
||||
Build.beginPlace(getTeam(), current.x, current.y, current.block, current.rotation);
|
||||
}else if(!current.initialized && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){
|
||||
Build.beginBreak(getTeam(), current.x, current.y);
|
||||
}else{
|
||||
requests.removeFirst();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(tile.entity instanceof BuildEntity && !current.initialized){
|
||||
Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, getTeam(), (Builderc)this, current.breaking)));
|
||||
current.initialized = true;
|
||||
}
|
||||
|
||||
//if there is no core to build with or no build entity, stop building!
|
||||
if((core == null && !state.rules.infiniteResources) || !(tile.entity instanceof BuildEntity)){
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise, update it.
|
||||
BuildEntity entity = tile.ent();
|
||||
|
||||
if(entity == null){
|
||||
return;
|
||||
}
|
||||
|
||||
if(dst(tile) <= finalPlaceDst){
|
||||
rotation = Mathf.slerpDelta(rotation, angleTo(entity), 0.4f);
|
||||
}
|
||||
|
||||
if(current.breaking){
|
||||
entity.deconstruct(this, core, 1f / entity.buildCost * Time.delta() * buildSpeed * state.rules.buildSpeedMultiplier);
|
||||
}else{
|
||||
if(entity.construct(this, core, 1f / entity.buildCost * Time.delta() * buildSpeed * state.rules.buildSpeedMultiplier, current.hasConfig)){
|
||||
if(current.hasConfig){
|
||||
Call.onTileConfig(null, tile, current.config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current.stuck = Mathf.equal(current.progress, entity.progress);
|
||||
current.progress = entity.progress;
|
||||
}
|
||||
|
||||
/** @return whether this request should be skipped, in favor of the next one. */
|
||||
boolean shouldSkip(BuildRequest request, @Nullable TileEntity core){
|
||||
//requests that you have at least *started* are considered
|
||||
if(state.rules.infiniteResources || request.breaking || !request.initialized || core == null) return false;
|
||||
return request.stuck && !core.items.has(request.block.requirements);
|
||||
}
|
||||
|
||||
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);
|
||||
int idx = requests.indexOf(req -> req.breaking == breaking && req.x == x && req.y == y);
|
||||
if(idx != -1){
|
||||
player.buildQueue().removeIndex(idx);
|
||||
requests.removeIndex(idx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,10 +865,47 @@ public class EntityComps{
|
||||
@Nullable BuildRequest buildRequest(){
|
||||
return requests.size == 0 ? null : requests.first();
|
||||
}
|
||||
|
||||
void drawOver(){
|
||||
if(!isBuilding()) return;
|
||||
BuildRequest request = buildRequest();
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
|
||||
if(dst(tile) > placeDistance && !state.isEditor()){
|
||||
return;
|
||||
}
|
||||
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
float focusLen = 3.8f + Mathf.absin(Time.time(), 1.1f, 0.6f);
|
||||
float px = x + Angles.trnsx(rotation, focusLen);
|
||||
float py = y + Angles.trnsy(rotation, focusLen);
|
||||
|
||||
float sz = Vars.tilesize * tile.block().size / 2f;
|
||||
float ang = angleTo(tile);
|
||||
|
||||
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
|
||||
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
|
||||
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
|
||||
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
|
||||
|
||||
Arrays.sort(tmptr, Structs.comparingFloat(vec -> Angles.angleDist(angleTo(vec), ang)));
|
||||
|
||||
float x1 = tmptr[0].x, y1 = tmptr[0].y,
|
||||
x3 = tmptr[1].x, y3 = tmptr[1].y;
|
||||
|
||||
Draw.alpha(1f);
|
||||
|
||||
Lines.line(px, py, x1, y1);
|
||||
Lines.line(px, py, x3, y3);
|
||||
|
||||
Fill.circle(px, py, 1.6f + Mathf.absin(Time.time(), 0.8f, 1.5f));
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Component(DamageComp.class)
|
||||
class ShielderComp{
|
||||
@Component
|
||||
abstract class ShielderComp implements Damagec{
|
||||
|
||||
void absorb(){
|
||||
|
||||
@ -486,12 +913,16 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
@Component
|
||||
class ItemsComp{
|
||||
abstract class ItemsComp{
|
||||
ItemStack stack = new ItemStack();
|
||||
|
||||
native int getItemCapacity();
|
||||
abstract int getItemCapacity();
|
||||
|
||||
public Item item(){
|
||||
void update(){
|
||||
stack.amount = Mathf.clamp(stack.amount, 0, getItemCapacity());
|
||||
}
|
||||
|
||||
Item item(){
|
||||
return stack.item;
|
||||
}
|
||||
|
||||
@ -508,47 +939,50 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Component(VelComp.class)
|
||||
class MassComp{
|
||||
@Component
|
||||
abstract class MassComp implements Velc{
|
||||
float mass;
|
||||
}
|
||||
|
||||
@Component({PosComp.class, DrawComp.class, TimedComp.class})
|
||||
class EffectComp extends EntityComp{
|
||||
@Component
|
||||
abstract class EffectComp implements Posc, Drawc, Timedc{
|
||||
Effect effect;
|
||||
Color color = new Color(Color.white);
|
||||
Object data;
|
||||
float rotation = 0f;
|
||||
|
||||
void draw(){
|
||||
public void draw(){
|
||||
|
||||
}
|
||||
|
||||
void update(){
|
||||
public void update(){
|
||||
//TODO fix effects, make everything poolable
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
abstract class VelComp extends PosComp{
|
||||
abstract class VelComp implements Posc{
|
||||
transient float x, y;
|
||||
|
||||
final Vec2 vel = new Vec2();
|
||||
float drag = 0f;
|
||||
|
||||
void update(){
|
||||
public void update(){
|
||||
//TODO handle solidity
|
||||
x += vel.x;
|
||||
y += vel.y;
|
||||
vel.scl(1f - drag * Time.delta());
|
||||
}
|
||||
}
|
||||
|
||||
@Component(PosComp.class)
|
||||
class HitboxComp{
|
||||
@Component
|
||||
abstract class HitboxComp implements Posc{
|
||||
transient float x, y;
|
||||
|
||||
float hitSize;
|
||||
float lastX, lastY;
|
||||
|
||||
void update(){
|
||||
public void update(){
|
||||
|
||||
}
|
||||
|
||||
@ -575,8 +1009,8 @@ public class EntityComps{
|
||||
}
|
||||
}
|
||||
|
||||
@Component(PosComp.class)
|
||||
class StatusComp{
|
||||
@Component
|
||||
abstract class StatusComp implements Posc{
|
||||
private Array<StatusEntry> statuses = new Array<>();
|
||||
private Bits applied = new Bits(content.getBy(ContentType.status).size);
|
||||
|
||||
@ -584,6 +1018,11 @@ public class EntityComps{
|
||||
private float damageMultiplier;
|
||||
private float armorMultiplier;
|
||||
|
||||
/** @return damage taken based on status armor multipliers */
|
||||
float getDamage(float amount){
|
||||
return amount * Mathf.clamp(1f - armorMultiplier / 100f);
|
||||
}
|
||||
|
||||
void apply(StatusEffect effect, float duration){
|
||||
if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects
|
||||
|
||||
@ -597,7 +1036,7 @@ public class EntityComps{
|
||||
}else if(entry.effect.reactsWith(effect)){ //find opposite
|
||||
StatusEntry.tmp.effect = entry.effect;
|
||||
//TODO unit cannot be null here
|
||||
entry.effect.getTransition(null, effect, entry.time, duration, StatusEntry.tmp);
|
||||
entry.effect.getTransition((mindustry.gen.Unitc)this, effect, entry.time, duration, StatusEntry.tmp);
|
||||
entry.time = StatusEntry.tmp.time;
|
||||
|
||||
if(StatusEntry.tmp.effect != entry.effect){
|
||||
@ -634,7 +1073,18 @@ public class EntityComps{
|
||||
return Tmp.c1.set(r / statuses.size, g / statuses.size, b / statuses.size, 1f);
|
||||
}
|
||||
|
||||
void update(){
|
||||
public void update(){
|
||||
Floor floor = floorOn();
|
||||
Tile tile = tileOn();
|
||||
boolean flying = false;
|
||||
//TODO conditionally apply status effects on floor, if not flying
|
||||
if(!flying && tile != null){
|
||||
//apply effect
|
||||
if(floor.status != null){
|
||||
apply(floor.status, floor.statusDuration);
|
||||
}
|
||||
}
|
||||
|
||||
applied.clear();
|
||||
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
|
||||
|
||||
@ -651,8 +1101,8 @@ public class EntityComps{
|
||||
speedMultiplier *= entry.effect.speedMultiplier;
|
||||
armorMultiplier *= entry.effect.armorMultiplier;
|
||||
damageMultiplier *= entry.effect.damageMultiplier;
|
||||
//TODO unit can't be null
|
||||
entry.effect.update(null, entry.time);
|
||||
//TODO ugly casting
|
||||
entry.effect.update((mindustry.gen.Unitc)this, entry.time);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -694,6 +1144,10 @@ public class EntityComps{
|
||||
class EntityComp{
|
||||
int id;
|
||||
|
||||
boolean isAdded(){
|
||||
return true;
|
||||
}
|
||||
|
||||
void init(){}
|
||||
|
||||
void update(){}
|
||||
@ -707,8 +1161,7 @@ public class EntityComps{
|
||||
}
|
||||
|
||||
boolean isLocal(){
|
||||
//TODO fix
|
||||
return this == (Object)Vars.player;
|
||||
return this == Vars.player;
|
||||
}
|
||||
|
||||
<T> T as(Class<T> type){
|
||||
|
@ -3,7 +3,6 @@ package mindustry.entities.effect;
|
||||
import arc.graphics.g2d.Draw;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.graphics.Pal;
|
||||
|
||||
import static mindustry.Vars.groundEffectGroup;
|
||||
|
@ -8,7 +8,6 @@ import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
|
@ -6,7 +6,6 @@ import mindustry.Vars;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.Effects.Effect;
|
||||
import mindustry.entities.Effects.EffectRenderer;
|
||||
import mindustry.entities.type.EffectEntity;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
/**
|
||||
|
@ -1,22 +1,19 @@
|
||||
package mindustry.entities.effect;
|
||||
|
||||
import mindustry.annotations.Annotations.Loc;
|
||||
import mindustry.annotations.Annotations.Remote;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Interpolation;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Position;
|
||||
import arc.math.geom.Vec2;
|
||||
import arc.util.Time;
|
||||
import arc.util.pooling.Pools;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.effectGroup;
|
||||
|
||||
public class ItemTransfer extends TimedEntity implements DrawTrait{
|
||||
private Vec2 from = new Vec2();
|
||||
@ -31,14 +28,14 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, unreliable = true)
|
||||
public static void transferItemEffect(Item item, float x, float y, Unit to){
|
||||
public static void transferItemEffect(Item item, float x, float y, Itemsc to){
|
||||
if(to == null) return;
|
||||
create(item, x, y, to, () -> {
|
||||
});
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, unreliable = true)
|
||||
public static void transferItemToUnit(Item item, float x, float y, Unit to){
|
||||
public static void transferItemToUnit(Item item, float x, float y, Itemsc to){
|
||||
if(to == null) return;
|
||||
create(item, x, y, to, () -> to.addItem(item));
|
||||
}
|
||||
|
@ -13,8 +13,6 @@ import mindustry.content.Bullets;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.Units;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.entities.type.TimedEntity;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.game.Team;
|
||||
import mindustry.gen.Call;
|
||||
import mindustry.graphics.Pal;
|
||||
@ -27,7 +25,7 @@ public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{
|
||||
|
||||
private static final Rand random = new Rand();
|
||||
private static final Rect rect = new Rect();
|
||||
private static final Array<Unit> entities = new Array<>();
|
||||
private static final Array<Unitc> entities = new Array<>();
|
||||
private static final IntSet hit = new IntSet();
|
||||
private static final int maxChain = 8;
|
||||
private static final float hitRange = 30f;
|
||||
@ -98,7 +96,7 @@ public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{
|
||||
});
|
||||
}
|
||||
|
||||
Unit furthest = Geometry.findFurthest(x, y, entities);
|
||||
Unitc furthest = Geometry.findFurthest(x, y, entities);
|
||||
|
||||
if(furthest != null){
|
||||
hit.add(furthest.getID());
|
||||
|
@ -11,8 +11,6 @@ import arc.util.pooling.Pool.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
|
@ -1,285 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.Queue;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
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.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.BuildBlock.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.entities.traits.BuilderTrait.BuildDataStatic.*;
|
||||
|
||||
/** Interface for units that build things.*/
|
||||
public interface BuilderTrait extends Entity, TeamTrait{
|
||||
//these are not instance variables!
|
||||
float placeDistance = 220f;
|
||||
float mineDistance = 70f;
|
||||
|
||||
/** Updates building mechanism for this unit.*/
|
||||
default void updateBuilding(){
|
||||
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : placeDistance;
|
||||
Unit unit = (Unit)this;
|
||||
|
||||
Iterator<BuildRequest> it = buildQueue().iterator();
|
||||
while(it.hasNext()){
|
||||
BuildRequest req = it.next();
|
||||
Tile tile = world.tile(req.x, req.y);
|
||||
if(tile == null || (req.breaking && tile.block() == Blocks.air) || (!req.breaking && (tile.rotation() == req.rotation || !req.block.rotate) && tile.block() == req.block)){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
//nothing to build.
|
||||
if(buildRequest() == null) return;
|
||||
|
||||
//find the next build request
|
||||
if(buildQueue().size > 1){
|
||||
int total = 0;
|
||||
BuildRequest req;
|
||||
while((dst((req = buildRequest()).tile()) > finalPlaceDst || shouldSkip(req, core)) && total < buildQueue().size){
|
||||
buildQueue().removeFirst();
|
||||
buildQueue().addLast(req);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
BuildRequest current = buildRequest();
|
||||
|
||||
if(dst(current.tile()) > finalPlaceDst) return;
|
||||
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
|
||||
if(!(tile.block() instanceof BuildBlock)){
|
||||
if(!current.initialized && canCreateBlocks() && !current.breaking && Build.validPlace(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)){
|
||||
Build.beginBreak(getTeam(), current.x, current.y);
|
||||
}else{
|
||||
buildQueue().removeFirst();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(tile.entity instanceof BuildEntity && !current.initialized){
|
||||
Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking)));
|
||||
current.initialized = true;
|
||||
}
|
||||
|
||||
//if there is no core to build with or no build entity, stop building!
|
||||
if((core == null && !state.rules.infiniteResources) || !(tile.entity instanceof BuildEntity)){
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise, update it.
|
||||
BuildEntity entity = tile.ent();
|
||||
|
||||
if(entity == null){
|
||||
return;
|
||||
}
|
||||
|
||||
if(unit.dst(tile) <= finalPlaceDst){
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
||||
}
|
||||
|
||||
if(current.breaking){
|
||||
entity.deconstruct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier);
|
||||
}else{
|
||||
if(entity.construct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier, current.hasConfig)){
|
||||
if(current.hasConfig){
|
||||
Call.onTileConfig(null, tile, current.config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current.stuck = Mathf.equal(current.progress, entity.progress);
|
||||
current.progress = entity.progress;
|
||||
}
|
||||
|
||||
/** @return whether this request should be skipped, in favor of the next one. */
|
||||
default boolean shouldSkip(BuildRequest request, @Nullable TileEntity core){
|
||||
//requests that you have at least *started* are considered
|
||||
if(state.rules.infiniteResources || request.breaking || !request.initialized || core == null) return false;
|
||||
return request.stuck && !core.items.has(request.block.requirements);
|
||||
}
|
||||
|
||||
default void removeRequest(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);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the queue for storing build requests. */
|
||||
Queue<BuildRequest> buildQueue();
|
||||
|
||||
/** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */
|
||||
float getBuildPower(Tile tile);
|
||||
|
||||
/** Whether this type of builder can begin creating new blocks. */
|
||||
default boolean canCreateBlocks(){
|
||||
return true;
|
||||
}
|
||||
|
||||
default void writeBuilding(DataOutput output) throws IOException{
|
||||
BuildRequest request = buildRequest();
|
||||
|
||||
if(request != null && (request.block != null || request.breaking)){
|
||||
output.writeByte(request.breaking ? 1 : 0);
|
||||
output.writeInt(Pos.get(request.x, request.y));
|
||||
output.writeFloat(request.progress);
|
||||
if(!request.breaking){
|
||||
output.writeShort(request.block.id);
|
||||
output.writeByte(request.rotation);
|
||||
}
|
||||
}else{
|
||||
output.writeByte(-1);
|
||||
}
|
||||
}
|
||||
|
||||
default void readBuilding(DataInput input) throws IOException{
|
||||
readBuilding(input, true);
|
||||
}
|
||||
|
||||
default void readBuilding(DataInput input, boolean applyChanges) throws IOException{
|
||||
if(applyChanges) buildQueue().clear();
|
||||
|
||||
byte type = input.readByte();
|
||||
if(type != -1){
|
||||
int position = input.readInt();
|
||||
float progress = input.readFloat();
|
||||
BuildRequest request;
|
||||
|
||||
if(type == 1){ //remove
|
||||
request = new BuildRequest(Pos.x(position), Pos.y(position));
|
||||
}else{ //place
|
||||
short block = input.readShort();
|
||||
byte rotation = input.readByte();
|
||||
request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block));
|
||||
}
|
||||
|
||||
request.progress = progress;
|
||||
|
||||
if(applyChanges){
|
||||
buildQueue().addLast(request);
|
||||
}else if(isBuilding()){
|
||||
BuildRequest last = buildRequest();
|
||||
last.progress = progress;
|
||||
if(last.tile() != null && last.tile().entity instanceof BuildEntity){
|
||||
((BuildEntity)last.tile().entity).progress = progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return whether this builder's place queue contains items. */
|
||||
default boolean isBuilding(){
|
||||
return buildQueue().size != 0;
|
||||
}
|
||||
|
||||
/** Clears the placement queue. */
|
||||
default void clearBuilding(){
|
||||
buildQueue().clear();
|
||||
}
|
||||
|
||||
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
||||
default void addBuildRequest(BuildRequest place){
|
||||
addBuildRequest(place, true);
|
||||
}
|
||||
|
||||
/** Add another build requests to the queue, if it doesn't exist there yet. */
|
||||
default void addBuildRequest(BuildRequest place, boolean tail){
|
||||
BuildRequest replace = null;
|
||||
for(BuildRequest request : buildQueue()){
|
||||
if(request.x == place.x && request.y == place.y){
|
||||
replace = request;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(replace != null){
|
||||
buildQueue().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){
|
||||
buildQueue().addLast(place);
|
||||
}else{
|
||||
buildQueue().addFirst(place);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the build requests currently active, or the one at the top of the queue.
|
||||
* May return null.
|
||||
*/
|
||||
default @Nullable
|
||||
BuildRequest buildRequest(){
|
||||
return buildQueue().size == 0 ? null : buildQueue().first();
|
||||
}
|
||||
|
||||
//due to iOS weirdness, this is apparently required
|
||||
class BuildDataStatic{
|
||||
static Vec2[] tmptr = new Vec2[]{new Vec2(), new Vec2(), new Vec2(), new Vec2()};
|
||||
}
|
||||
|
||||
/** Draw placement effects for an entity. */
|
||||
default void drawBuilding(){
|
||||
if(!isBuilding()) return;
|
||||
|
||||
Unit unit = (Unit)this;
|
||||
BuildRequest request = buildRequest();
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
|
||||
if(dst(tile) > placeDistance && !state.isEditor()){
|
||||
return;
|
||||
}
|
||||
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
float focusLen = 3.8f + Mathf.absin(Time.time(), 1.1f, 0.6f);
|
||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||
|
||||
float sz = Vars.tilesize * tile.block().size / 2f;
|
||||
float ang = unit.angleTo(tile);
|
||||
|
||||
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
|
||||
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
|
||||
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
|
||||
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
|
||||
|
||||
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang),
|
||||
Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang)));
|
||||
|
||||
float x1 = tmptr[0].x, y1 = tmptr[0].y,
|
||||
x3 = tmptr[1].x, y3 = tmptr[1].y;
|
||||
|
||||
Draw.alpha(1f);
|
||||
|
||||
Lines.line(px, py, x1, y1);
|
||||
Lines.line(px, py, x3, y3);
|
||||
|
||||
Fill.circle(px, py, 1.6f + Mathf.absin(Time.time(), 0.8f, 1.5f));
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.Color;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.Time;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.Call;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public interface MinerTrait extends Entity{
|
||||
|
||||
/** Returns the range at which this miner can mine blocks.*/
|
||||
default float getMiningRange(){
|
||||
return 70f;
|
||||
}
|
||||
|
||||
default boolean isMining(){
|
||||
return getMineTile() != null;
|
||||
}
|
||||
|
||||
/** Returns the tile this builder is currently mining. */
|
||||
Tile getMineTile();
|
||||
|
||||
/** Sets the tile this builder is currently mining. */
|
||||
void setMineTile(Tile tile);
|
||||
|
||||
/** Returns the mining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */
|
||||
float getMinePower();
|
||||
|
||||
/** Returns whether or not this builder can mine a specific item type. */
|
||||
boolean canMine(Item item);
|
||||
|
||||
/** @return whether to offload mined items immediately at the core. if false, items are collected and dropped in a burst. */
|
||||
default boolean offloadImmediately(){
|
||||
return false;
|
||||
}
|
||||
|
||||
default void updateMining(){
|
||||
Unit unit = (Unit)this;
|
||||
Tile tile = getMineTile();
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
if(core != null && tile != null && tile.drop() != null && !unit.acceptsItem(tile.drop()) && unit.dst(core) < mineTransferRange){
|
||||
int accepted = core.tile.block().acceptStack(unit.item().item, unit.item().amount, core.tile, unit);
|
||||
if(accepted > 0){
|
||||
Call.transferItemTo(unit.item().item, accepted,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
unit.clearItem();
|
||||
}
|
||||
}
|
||||
|
||||
if(tile == null || core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > getMiningRange()
|
||||
|| tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){
|
||||
setMineTile(null);
|
||||
}else{
|
||||
Item item = tile.drop();
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f);
|
||||
|
||||
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){
|
||||
|
||||
if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1 && offloadImmediately()){
|
||||
Call.transferItemTo(item, 1,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), core.tile);
|
||||
}else if(unit.acceptsItem(item)){
|
||||
//this is clientside, since items are synced anyway
|
||||
ItemTransfer.transferItemToUnit(item,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f),
|
||||
unit);
|
||||
}
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.06 * Time.delta())){
|
||||
Effects.effect(Fx.pulverizeSmall,
|
||||
tile.worldx() + Mathf.range(tilesize / 2f),
|
||||
tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default void drawMining(){
|
||||
Unit unit = (Unit)this;
|
||||
Tile tile = getMineTile();
|
||||
|
||||
if(tile == null) return;
|
||||
|
||||
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||
float swingScl = 12f, swingMag = tilesize / 8f;
|
||||
float flashScl = 0.3f;
|
||||
|
||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||
|
||||
float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
|
||||
float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
|
||||
|
||||
Draw.color(Color.lightGray, Color.white, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
|
||||
|
||||
Drawf.laser(Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f);
|
||||
|
||||
if(unit instanceof Player && ((Player)unit).isLocal){
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
/**
|
||||
* Marks an entity as serializable.
|
||||
*/
|
||||
public interface SaveTrait extends Entity, TypeTrait, Saveable{
|
||||
byte version();
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.math.geom.Position;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
public interface SpawnerTrait extends TargetTrait, Position{
|
||||
Tile getTile();
|
||||
|
||||
void updateSpawning(Player unit);
|
||||
|
||||
boolean hasUnit(Unit unit);
|
||||
|
||||
@Override
|
||||
default boolean isValid(){
|
||||
return getTile().entity instanceof SpawnerTrait;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import mindustry.entities.EntityGroup;
|
||||
|
||||
public abstract class BaseEntity implements Entity{
|
||||
private static int lastid;
|
||||
/** Do not modify. Used for network operations and mapping. */
|
||||
public int id;
|
||||
public float x, y;
|
||||
protected transient EntityGroup group;
|
||||
|
||||
public BaseEntity(){
|
||||
id = lastid++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID(){
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetID(int id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGroup getGroup(){
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroup(EntityGroup group){
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getX(){
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setX(float x){
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getY(){
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(float y){
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return getClass() + " " + id;
|
||||
}
|
||||
|
||||
/** Increments this entity's ID. Used for pooled entities.*/
|
||||
public void incrementID(){
|
||||
id = lastid++;
|
||||
}
|
||||
}
|
@ -11,7 +11,6 @@ import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
@ -31,7 +30,7 @@ import java.io.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** Base class for AI units. */
|
||||
public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
public abstract class BaseUnit extends Unitc implements ShooterTrait{
|
||||
protected static int timerIndex = 0;
|
||||
|
||||
protected static final int timerTarget = timerIndex++;
|
||||
@ -151,7 +150,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
}
|
||||
|
||||
public void updateTargeting(){
|
||||
if(target == null || (target instanceof Unit && (target.isDead() || target.getTeam() == team))
|
||||
if(target == null || (target instanceof Unitc && (target.isDead() || target.getTeam() == team))
|
||||
|| (target instanceof TileEntity && ((TileEntity)target).tile.entity == null)){
|
||||
target = null;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import arc.util.pooling.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
@ -122,8 +121,8 @@ public class Bullet extends SolidEntity implements DamageTrait, Scaled, Poolable
|
||||
}
|
||||
|
||||
public float damageMultiplier(){
|
||||
if(owner instanceof Unit){
|
||||
return ((Unit)owner).getDamageMultipler();
|
||||
if(owner instanceof Unitc){
|
||||
return ((Unitc)owner).getDamageMultipler();
|
||||
}
|
||||
return 1f;
|
||||
}
|
||||
@ -166,7 +165,7 @@ public class Bullet extends SolidEntity implements DamageTrait, Scaled, Poolable
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidTrait other){
|
||||
return type.collides && (other != owner && !(other instanceof DamageTrait)) && !supressCollision && !(other instanceof Unit && ((Unit)other).isFlying() && !type.collidesAir);
|
||||
return type.collides && (other != owner && !(other instanceof DamageTrait)) && !supressCollision && !(other instanceof Unitc && ((Unitc)other).isFlying() && !type.collidesAir);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -174,8 +173,8 @@ public class Bullet extends SolidEntity implements DamageTrait, Scaled, Poolable
|
||||
if(!type.pierce) remove();
|
||||
type.hit(this, x, y);
|
||||
|
||||
if(other instanceof Unit){
|
||||
Unit unit = (Unit)other;
|
||||
if(other instanceof Unitc){
|
||||
Unitc unit = (Unitc)other;
|
||||
unit.velocity().add(Tmp.v3.set(other.getX(), other.getY()).sub(x, y).setLength(type.knockback / unit.mass()));
|
||||
unit.applyEffect(type.status, type.statusDuration);
|
||||
}
|
||||
|
@ -1,79 +0,0 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
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;
|
||||
|
||||
public class EffectEntity extends TimedEntity implements Poolable, DrawTrait{
|
||||
public Effect effect;
|
||||
public Color color = new Color(Color.white);
|
||||
public Object data;
|
||||
public float rotation = 0f;
|
||||
|
||||
public Entity parent;
|
||||
public float poffsetx, poffsety;
|
||||
|
||||
/** For pooling use only! */
|
||||
public EffectEntity(){
|
||||
}
|
||||
|
||||
public void setParent(Entity parent){
|
||||
this.parent = parent;
|
||||
this.poffsetx = x - parent.getX();
|
||||
this.poffsety = y - parent.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGroup targetGroup(){
|
||||
//this should never actually be called
|
||||
return effectGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float lifetime(){
|
||||
return effect.lifetime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drawSize(){
|
||||
return effect.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(effect == null){
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
|
||||
super.update();
|
||||
if(parent != null){
|
||||
x = parent.getX() + poffsetx;
|
||||
y = parent.getY() + poffsety;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
effect = null;
|
||||
color.set(Color.white);
|
||||
rotation = time = poffsetx = poffsety = 0f;
|
||||
parent = null;
|
||||
data = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Effects.renderEffect(id, effect, color, time, rotation, x, y, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
Pools.free(this);
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
public class Player extends Unitc implements BuilderMinerTrait, ShooterTrait{
|
||||
public static final int timerSync = 2;
|
||||
public static final int timerAbility = 3;
|
||||
private static final float liftoffBoost = 0.2f;
|
||||
|
@ -21,7 +21,7 @@ import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
public class TileEntity{
|
||||
public static final float timeToSleep = 60f * 1; //1 second to fall asleep
|
||||
private static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
|
||||
/** This value is only used for debugging. */
|
||||
@ -112,10 +112,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSleeping(){
|
||||
return sleeping;
|
||||
}
|
||||
|
||||
public boolean isDead(){
|
||||
return dead || tile.entity != this;
|
||||
}
|
||||
@ -256,26 +252,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void health(float health){
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float health(){
|
||||
return health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float maxHealth(){
|
||||
return block.health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(boolean dead){
|
||||
this.dead = dead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(){
|
||||
if(!dead){
|
||||
@ -289,16 +265,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Team getTeam(){
|
||||
return tile.getTeam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec2 velocity(){
|
||||
return Vec2.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
timeScaleDuration -= Time.delta();
|
||||
@ -339,11 +305,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
return !isDead() && tile.entity == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGroup targetGroup(){
|
||||
return tileGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "TileEntity{" +
|
||||
|
@ -1,33 +0,0 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import arc.util.pooling.Pool.*;
|
||||
import mindustry.entities.traits.*;
|
||||
|
||||
public abstract class TimedEntity extends BaseEntity implements TimeTrait, Poolable{
|
||||
public float time;
|
||||
|
||||
@Override
|
||||
public void time(float time){
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float time(){
|
||||
return time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
updateTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
time = 0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float fin(){
|
||||
return time() / lifetime();
|
||||
}
|
||||
}
|
@ -1,504 +0,0 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
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. */
|
||||
public static final float velocityPercision = 8f;
|
||||
/** Maximum absolute value of a velocity vector component. */
|
||||
public static final float maxAbsVelocity = 127f / velocityPercision;
|
||||
public static final int noSpawner = Pos.get(-1, 1);
|
||||
|
||||
private static final Vec2 moveVector = new Vec2();
|
||||
|
||||
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){
|
||||
return !isFlying();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Team getTeam(){
|
||||
return team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weapons getWeapons(){
|
||||
return weapons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate(){
|
||||
interpolator.update();
|
||||
|
||||
x = interpolator.pos.x;
|
||||
y = interpolator.pos.y;
|
||||
|
||||
if(interpolator.values.length > 0){
|
||||
rotation = interpolator.values[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interpolator getInterpolator(){
|
||||
return interpolator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(float amount){
|
||||
if(!net.client()){
|
||||
super.damage(calculateDamage(amount));
|
||||
}
|
||||
hitTime = hitDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidTrait other){
|
||||
if(isDead()) return false;
|
||||
|
||||
if(other instanceof DamageTrait){
|
||||
return other instanceof TeamTrait && (((TeamTrait)other).getTeam()).isEnemy(team);
|
||||
}else{
|
||||
return other instanceof Unit && ((Unit)other).isFlying() == isFlying();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(){
|
||||
float explosiveness = 2f + item.item.explosiveness * item.amount;
|
||||
float flammability = item.item.flammability * item.amount;
|
||||
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, getSize() / 2f, Pal.darkFlame);
|
||||
|
||||
ScorchDecal.create(x, y);
|
||||
Fx.explosion.at(this);
|
||||
Effects.shake(2f, 2f, this);
|
||||
|
||||
Sounds.bang.at(this);
|
||||
item.amount = 0;
|
||||
drownTime = 0f;
|
||||
status.clear();
|
||||
Events.fire(new UnitDestroyEvent(this));
|
||||
|
||||
if(explosiveness > 7f && this == player){
|
||||
Events.fire(Trigger.suicideBomb);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec2 velocity(){
|
||||
return velocity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(float x, float y){
|
||||
if(!isFlying()){
|
||||
super.move(x, y);
|
||||
}else{
|
||||
moveBy(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(){
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSave(DataInput stream, byte version) throws IOException{
|
||||
byte team = stream.readByte();
|
||||
boolean dead = stream.readBoolean();
|
||||
float x = stream.readFloat();
|
||||
float y = stream.readFloat();
|
||||
byte xv = stream.readByte();
|
||||
byte yv = stream.readByte();
|
||||
float rotation = stream.readShort() / 2f;
|
||||
int health = stream.readShort();
|
||||
byte itemID = stream.readByte();
|
||||
short itemAmount = stream.readShort();
|
||||
|
||||
this.status.readSave(stream, version);
|
||||
this.item.amount = itemAmount;
|
||||
this.item.item = content.item(itemID);
|
||||
this.dead = dead;
|
||||
this.team = Team.get(team);
|
||||
this.health = health;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.velocity.set(xv / velocityPercision, yv / velocityPercision);
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
public void writeSave(DataOutput stream, boolean net) throws IOException{
|
||||
if(item.item == null) item.item = Items.copper;
|
||||
|
||||
stream.writeByte(team.id);
|
||||
stream.writeBoolean(isDead());
|
||||
stream.writeFloat(net ? interpolator.target.x : x);
|
||||
stream.writeFloat(net ? interpolator.target.y : y);
|
||||
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||
stream.writeByte((byte)(Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||
stream.writeShort((short)(rotation * 2));
|
||||
stream.writeShort((short)health);
|
||||
stream.writeByte(item.item.id);
|
||||
stream.writeShort((short)item.amount);
|
||||
status.writeSave(stream);
|
||||
}
|
||||
|
||||
protected void clampPosition(){
|
||||
x = Mathf.clamp(x, 0, world.width() * tilesize - tilesize);
|
||||
y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize);
|
||||
}
|
||||
|
||||
public boolean isImmune(StatusEffect effect){
|
||||
return type.immunities.contains(effect);
|
||||
}
|
||||
|
||||
public boolean isOutOfBounds(){
|
||||
return x < -worldBounds || y < -worldBounds || x > world.width() * tilesize + worldBounds || y > world.height() * tilesize + worldBounds;
|
||||
}
|
||||
|
||||
public float calculateDamage(float amount){
|
||||
return amount * Mathf.clamp(1f - status.getArmorMultiplier() / 100f);
|
||||
}
|
||||
|
||||
public float getDamageMultipler(){
|
||||
return status.getDamageMultiplier();
|
||||
}
|
||||
|
||||
public boolean hasEffect(StatusEffect effect){
|
||||
return status.hasEffect(effect);
|
||||
}
|
||||
|
||||
public void avoidOthers(){
|
||||
float radScl = 1.5f;
|
||||
float fsize = getSize() / radScl;
|
||||
moveVector.setZero();
|
||||
float cx = x - fsize/2f, cy = y - fsize/2f;
|
||||
avoid(unitGroup.intersect(cx, cy, fsize, fsize));
|
||||
if(!(this instanceof Player)){
|
||||
avoid(playerGroup.intersect(cx, cy, fsize, fsize));
|
||||
}
|
||||
velocity.add(moveVector.x / mass() * Time.delta(), moveVector.y / mass() * Time.delta());
|
||||
}
|
||||
|
||||
private void avoid(Array<? extends Unit> arr){
|
||||
float radScl = 1.5f;
|
||||
|
||||
for(Unit en : arr){
|
||||
if(en.isFlying() != isFlying() || (en instanceof Player && en.getTeam() != getTeam()) || (this instanceof Player && en.isFlying())) continue;
|
||||
float dst = dst(en);
|
||||
float scl = Mathf.clamp(1f - dst / (getSize()/(radScl*2f) + en.getSize()/(radScl*2f)));
|
||||
moveVector.add(Tmp.v1.set((x - en.x) * scl, (y - en.y) * scl).limit(0.4f));
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable TileEntity getClosestCore(){
|
||||
return state.teams.closestCore(x, y, team);
|
||||
}
|
||||
|
||||
public Floor getFloorOn(){
|
||||
Tile tile = world.tileWorld(x, y);
|
||||
return tile == null ? (Floor)Blocks.air : tile.floor();
|
||||
}
|
||||
|
||||
public @Nullable Tile tileOn(){
|
||||
return world.tileWorld(x, y);
|
||||
}
|
||||
|
||||
public void onRespawn(Tile tile){
|
||||
}
|
||||
|
||||
/** Updates velocity and status effects. */
|
||||
public void updateVelocityStatus(){
|
||||
Floor floor = getFloorOn();
|
||||
|
||||
Tile tile = world.tileWorld(x, y);
|
||||
|
||||
status.update(this);
|
||||
item.amount = Mathf.clamp(this.item.amount, 0, getItemCapacity());
|
||||
|
||||
//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();
|
||||
}
|
||||
|
||||
//apply knockback based on spawns
|
||||
if(getTeam() != state.rules.waveTeam){
|
||||
float relativeSize = state.rules.dropZoneRadius + getSize()/2f + 1f;
|
||||
for(Tile spawn : spawner.getGroundSpawns()){
|
||||
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||
velocity.add(Tmp.v1.set(this).sub(spawn.worldx(), spawn.worldy()).setLength(0.1f + 1f - dst(spawn) / relativeSize).scl(0.45f * Time.delta()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//repel player out of bounds
|
||||
final float warpDst = 180f;
|
||||
|
||||
if(x < 0) velocity.x += (-x/warpDst);
|
||||
if(y < 0) velocity.y += (-y/warpDst);
|
||||
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());
|
||||
}else{
|
||||
boolean onLiquid = floor.isLiquid;
|
||||
|
||||
if(tile != null){
|
||||
tile.block().unitOn(tile, this);
|
||||
if(tile.block() != Blocks.air){
|
||||
onLiquid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(onLiquid && velocity.len() > 0.4f && Mathf.chance((velocity.len() * floor.speedMultiplier) * 0.06f * Time.delta())){
|
||||
floor.walkEffect.at(floor.color, x, y);
|
||||
}
|
||||
|
||||
if(onLiquid){
|
||||
status.handleApply(this, floor.status, floor.statusDuration);
|
||||
|
||||
if(floor.damageTaken > 0f){
|
||||
damagePeriodic(floor.damageTaken);
|
||||
}
|
||||
}
|
||||
|
||||
if(onLiquid && floor.drownTime > 0){
|
||||
drownTime += Time.delta() * 1f / floor.drownTime;
|
||||
if(Mathf.chance(Time.delta() * 0.05f)){
|
||||
floor.drownUpdateEffect.at(floor.color, x, y);
|
||||
}
|
||||
}else{
|
||||
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
||||
}
|
||||
|
||||
drownTime = Mathf.clamp(drownTime);
|
||||
|
||||
if(drownTime >= 0.999f && !net.client()){
|
||||
damage(health + 1);
|
||||
if(this == player){
|
||||
Events.fire(Trigger.drown);
|
||||
}
|
||||
}
|
||||
|
||||
float px = x, py = y;
|
||||
move(velocity.x * floor.speedMultiplier * Time.delta(), velocity.y * floor.speedMultiplier * Time.delta());
|
||||
if(Math.abs(px - x) <= 0.0001f) velocity.x = 0f;
|
||||
if(Math.abs(py - y) <= 0.0001f) velocity.y = 0f;
|
||||
}
|
||||
|
||||
//velocity.scl(Mathf.clamp(1f - drag() * (isFlying() ? 1f : floor.dragMultiplier) * Time.delta()));
|
||||
}
|
||||
|
||||
public boolean acceptsItem(Item item){
|
||||
return this.item.amount <= 0 || (this.item.item == item && this.item.amount <= getItemCapacity());
|
||||
}
|
||||
|
||||
public void addItem(Item item){
|
||||
addItem(item, 1);
|
||||
}
|
||||
|
||||
public void addItem(Item item, int amount){
|
||||
this.item.amount = this.item.item == item ? this.item.amount + amount : amount;
|
||||
this.item.item = item;
|
||||
this.item.amount = Mathf.clamp(this.item.amount, 0, getItemCapacity());
|
||||
}
|
||||
|
||||
public void clearItem(){
|
||||
item.amount = 0;
|
||||
}
|
||||
|
||||
public ItemStack item(){
|
||||
return item;
|
||||
}
|
||||
|
||||
public int maxAccepted(Item item){
|
||||
return this.item.item != item && this.item.amount > 0 ? 0 : getItemCapacity() - this.item.amount;
|
||||
}
|
||||
|
||||
public void applyEffect(StatusEffect effect, float duration){
|
||||
if(dead || net.client()) return; //effects are synced and thus not applied through clients
|
||||
status.handleApply(this, effect, duration);
|
||||
}
|
||||
|
||||
public void damagePeriodic(float amount){
|
||||
damage(amount * Time.delta(), hitTime <= -20 + hitDuration);
|
||||
}
|
||||
|
||||
public void damage(float amount, boolean withEffect){
|
||||
float pre = hitTime;
|
||||
|
||||
damage(amount);
|
||||
|
||||
if(!withEffect){
|
||||
hitTime = pre;
|
||||
}
|
||||
}
|
||||
|
||||
public void drawUnder(){
|
||||
}
|
||||
|
||||
public void drawOver(){
|
||||
}
|
||||
|
||||
public void drawStats(){
|
||||
Draw.color(Color.black, team.color, healthf() + Mathf.absin(Time.time(), Math.max(healthf() * 5f, 1f), 1f - healthf()));
|
||||
Draw.rect(getPowerCellRegion(), x, y, rotation - 90);
|
||||
Draw.color();
|
||||
|
||||
drawBackItems(item.amount > 0 ? 1f : 0f, false);
|
||||
|
||||
drawLight();
|
||||
}
|
||||
|
||||
public void drawLight(){
|
||||
if(type.lightRadius > 0){
|
||||
renderer.lights.add(x, y, type.lightRadius, type.lightColor, 0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawBackItems(float itemtime, boolean number){
|
||||
//draw back items
|
||||
if(itemtime > 0.01f && item.item != null){
|
||||
float backTrns = 5f;
|
||||
float size = (itemSize + Mathf.absin(Time.time(), 5f, 1f)) * itemtime;
|
||||
|
||||
Draw.mixcol(Pal.accent, Mathf.absin(Time.time(), 5f, 0.5f));
|
||||
Draw.rect(item.item.icon(Cicon.medium),
|
||||
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||
y + Angles.trnsy(rotation + 180f, backTrns),
|
||||
size, size, rotation);
|
||||
|
||||
Draw.mixcol();
|
||||
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
Lines.circle(
|
||||
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||
y + Angles.trnsy(rotation + 180f, backTrns),
|
||||
(3f + Mathf.absin(Time.time(), 5f, 1f)) * itemtime);
|
||||
|
||||
if(number){
|
||||
Fonts.outline.draw(item.amount + "",
|
||||
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||
y + Angles.trnsy(rotation + 180f, backTrns) - 3,
|
||||
Pal.accent, 0.25f * itemtime / Scl.scl(1f), false, Align.center
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public TextureRegion getPowerCellRegion(){
|
||||
return Core.atlas.find("power-cell");
|
||||
}
|
||||
|
||||
public void drawAll(){
|
||||
if(!isDead()){
|
||||
draw();
|
||||
drawStats();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawShadow(float offsetX, float offsetY){
|
||||
Draw.rect(getIconRegion(), x + offsetX, y + offsetY, rotation - 90);
|
||||
}
|
||||
|
||||
public float getSize(){
|
||||
hitbox(Tmp.r1);
|
||||
return Math.max(Tmp.r1.width, Tmp.r1.height) * 2f;
|
||||
}
|
||||
|
||||
public abstract TextureRegion getIconRegion();
|
||||
|
||||
public final int getItemCapacity(){
|
||||
return type.itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float mass(){
|
||||
return type.mass;
|
||||
}
|
||||
|
||||
public boolean isFlying(){
|
||||
return type.flying;
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package mindustry.entities.type.base;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Structs;
|
||||
import mindustry.content.Blocks;
|
||||
import mindustry.entities.traits.MinerTrait;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.units.UnitState;
|
||||
import mindustry.gen.Call;
|
||||
|
@ -7,8 +7,7 @@ import arc.util.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
import java.io.*;
|
||||
@ -27,7 +26,7 @@ public class Statuses implements Saveable{
|
||||
private float damageMultiplier;
|
||||
private float armorMultiplier;
|
||||
|
||||
public void handleApply(Unit unit, StatusEffect effect, float duration){
|
||||
public void handleApply(Unitc unit, StatusEffect effect, float duration){
|
||||
if(effect == StatusEffects.none || effect == null || unit.isImmune(effect)) return; //don't apply empty or immune effects
|
||||
|
||||
if(statuses.size > 0){
|
||||
@ -76,7 +75,7 @@ public class Statuses implements Saveable{
|
||||
statuses.clear();
|
||||
}
|
||||
|
||||
public void update(Unit unit){
|
||||
public void update(Unitc unit){
|
||||
applied.clear();
|
||||
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
|
||||
|
||||
|
5
core/src/mindustry/entities/units/UnitController.java
Normal file
5
core/src/mindustry/entities/units/UnitController.java
Normal file
@ -0,0 +1,5 @@
|
||||
package mindustry.entities.units;
|
||||
|
||||
//TODO rename
|
||||
public class UnitController{
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
package mindustry.game;
|
||||
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.core.GameState.State;
|
||||
import mindustry.ctype.UnlockableContent;
|
||||
import mindustry.entities.traits.BuilderTrait;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class EventType{
|
||||
|
||||
@ -280,10 +280,10 @@ public class EventType{
|
||||
public static class BuildSelectEvent{
|
||||
public final Tile tile;
|
||||
public final Team team;
|
||||
public final BuilderTrait builder;
|
||||
public final Builderc builder;
|
||||
public final boolean breaking;
|
||||
|
||||
public BuildSelectEvent(Tile tile, Team team, BuilderTrait builder, boolean breaking){
|
||||
public BuildSelectEvent(Tile tile, Team team, Builderc builder, boolean breaking){
|
||||
this.tile = tile;
|
||||
this.team = team;
|
||||
this.builder = builder;
|
||||
@ -302,17 +302,17 @@ public class EventType{
|
||||
}
|
||||
|
||||
public static class UnitDestroyEvent{
|
||||
public final Unit unit;
|
||||
public final Unitc unit;
|
||||
|
||||
public UnitDestroyEvent(Unit unit){
|
||||
public UnitDestroyEvent(Unitc unit){
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitCreateEvent{
|
||||
public final BaseUnit unit;
|
||||
public final Unitc unit;
|
||||
|
||||
public UnitCreateEvent(BaseUnit unit){
|
||||
public UnitCreateEvent(Unitc unit){
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class MinimapRenderer implements Disposable{
|
||||
private static final float baseSize = 16f;
|
||||
private final Array<Unit> units = new Array<>();
|
||||
private final Array<Unitc> units = new Array<>();
|
||||
private Pixmap pixmap;
|
||||
private Texture texture;
|
||||
private TextureRegion region;
|
||||
@ -87,7 +87,7 @@ public class MinimapRenderer implements Disposable{
|
||||
|
||||
rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize);
|
||||
|
||||
for(Unit unit : units){
|
||||
for(Unitc unit : units){
|
||||
if(unit.isDead()) continue;
|
||||
float rx = !withLabels ? (unit.x - rect.x) / rect.width * w : unit.x / (world.width() * tilesize) * w;
|
||||
float ry = !withLabels ? (unit.y - rect.y) / rect.width * h : unit.y / (world.height() * tilesize) * h;
|
||||
|
@ -16,7 +16,6 @@ import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@ -69,7 +68,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
/** Check and assign targets for a specific position. */
|
||||
void checkTargets(float x, float y){
|
||||
Unit unit = Units.closestEnemy(player.getTeam(), x, y, 20f, u -> !u.isDead());
|
||||
Unitc unit = Units.closestEnemy(player.getTeam(), x, y, 20f, u -> !u.isDead());
|
||||
|
||||
if(unit != null){
|
||||
player.setMineTile(null);
|
||||
|
@ -8,7 +8,6 @@ import mindustry.core.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
import mindustry.maps.*;
|
||||
|
@ -42,8 +42,8 @@ public class TypeIO{
|
||||
return id == -1 ? null : playerGroup.getByID(id);
|
||||
}
|
||||
|
||||
@WriteClass(Unit.class)
|
||||
public static void writeUnit(ByteBuffer buffer, Unit unit){
|
||||
@WriteClass(Unitc.class)
|
||||
public static void writeUnit(ByteBuffer buffer, Unitc unit){
|
||||
if(unit.getGroup() == null){
|
||||
buffer.put((byte)-1);
|
||||
return;
|
||||
@ -52,12 +52,12 @@ public class TypeIO{
|
||||
buffer.putInt(unit.getID());
|
||||
}
|
||||
|
||||
@ReadClass(Unit.class)
|
||||
public static Unit readUnit(ByteBuffer buffer){
|
||||
@ReadClass(Unitc.class)
|
||||
public static Unitc readUnit(ByteBuffer buffer){
|
||||
byte gid = buffer.get();
|
||||
if(gid == -1) return null;
|
||||
int id = buffer.getInt();
|
||||
return (Unit)entities.get(gid).getByID(id);
|
||||
return (Unitc)entities.get(gid).getByID(id);
|
||||
}
|
||||
|
||||
@WriteClass(ShooterTrait.class)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package mindustry.io.versions;
|
||||
|
||||
import arc.func.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package mindustry.io.versions;
|
||||
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.type.TypeID;
|
||||
|
||||
|
@ -1,16 +1,14 @@
|
||||
package mindustry.type;
|
||||
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class StatusEffect extends MappableContent{
|
||||
/** Damage dealt by the unit with the effect. */
|
||||
@ -44,15 +42,15 @@ public class StatusEffect extends MappableContent{
|
||||
}
|
||||
|
||||
/** Runs every tick on the affected unit while time is greater than 0. */
|
||||
public void update(Unit unit, float time){
|
||||
public void update(Unitc unit, float time){
|
||||
if(damage > 0){
|
||||
unit.damagePeriodic(damage);
|
||||
unit.damageContinuous(damage);
|
||||
}else if(damage < 0){ //heal unit
|
||||
unit.healBy(damage * Time.delta());
|
||||
unit.heal(damage * Time.delta());
|
||||
}
|
||||
|
||||
if(effect != Fx.none && Mathf.chance(Time.delta() * 0.15f)){
|
||||
effect.at(unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||
effect.at(unit.getX() + Mathf.range(unit.getBounds() / 2f), unit.getY() + Mathf.range(unit.getBounds() / 2f));
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +81,7 @@ public class StatusEffect extends MappableContent{
|
||||
* @param time The current status effect time
|
||||
* @param newTime The time that the new status effect will last
|
||||
*/
|
||||
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){
|
||||
public StatusEntry getTransition(Unitc unit, StatusEffect to, float time, float newTime, StatusEntry result){
|
||||
if(transitions.containsKey(to)){
|
||||
transitions.get(to).handle(unit, time, newTime, result);
|
||||
return result;
|
||||
@ -98,6 +96,6 @@ public class StatusEffect extends MappableContent{
|
||||
}
|
||||
|
||||
public interface TransitionHandler{
|
||||
void handle(Unit unit, float time, float newTime, StatusEntry result);
|
||||
void handle(Unitc unit, float time, float newTime, StatusEntry result);
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class UnitDef extends UnlockableContent{
|
||||
public Sound deathSound = Sounds.bang;
|
||||
|
||||
public Array<Weapon> weapons = new Array<>();
|
||||
public TextureRegion baseRegion, legRegion, region;
|
||||
public TextureRegion baseRegion, legRegion, region, cellRegion;
|
||||
|
||||
public UnitDef(String name){
|
||||
super(name);
|
||||
@ -87,6 +87,7 @@ public class UnitDef extends UnlockableContent{
|
||||
region = Core.atlas.find(name);
|
||||
legRegion = Core.atlas.find(name + "-leg");
|
||||
baseRegion = Core.atlas.find(name + "-base");
|
||||
cellRegion = Core.atlas.find(name + "-cell", Core.atlas.find("power-cell"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,13 +97,13 @@ public class UnitDef extends UnlockableContent{
|
||||
|
||||
//TODO remove methods below!
|
||||
|
||||
public void update(Unit player){
|
||||
public void update(Unitc player){
|
||||
}
|
||||
|
||||
public void draw(Unit player){
|
||||
public void draw(Unitc player){
|
||||
}
|
||||
|
||||
public void drawStats(Unit player){
|
||||
public void drawStats(Unitc player){
|
||||
if(drawCell){
|
||||
float health = player.healthf();
|
||||
Draw.color(Color.black, player.getTeam().color, health + Mathf.absin(Time.time(), health * 5f, 1f - health));
|
||||
@ -118,25 +119,25 @@ public class UnitDef extends UnlockableContent{
|
||||
}
|
||||
}
|
||||
|
||||
public float getExtraArmor(Unit player){
|
||||
public float getExtraArmor(Unitc player){
|
||||
return 0f;
|
||||
}
|
||||
|
||||
//TODO remove
|
||||
public float spreadX(Unit player){
|
||||
public float spreadX(Unitc player){
|
||||
return 0f;
|
||||
}
|
||||
|
||||
//TODO remove
|
||||
public float getRotationAlpha(Unit player){
|
||||
public float getRotationAlpha(Unitc player){
|
||||
return 1f;
|
||||
}
|
||||
|
||||
public boolean canShoot(Unit player){
|
||||
public boolean canShoot(Unitc player){
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onLand(Unit player){
|
||||
public void onLand(Unitc player){
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.net.*;
|
||||
@ -66,7 +65,7 @@ public class PlayerListFragment extends Fragment{
|
||||
|
||||
float h = 74f;
|
||||
|
||||
playerGroup.all().sort(Structs.comparing(Unit::getTeam));
|
||||
playerGroup.all().sort(Structs.comparing(Unitc::getTeam));
|
||||
playerGroup.all().each(user -> {
|
||||
NetConnection connection = user.con;
|
||||
|
||||
|
@ -358,11 +358,11 @@ public class Block extends BlockStorage{
|
||||
}
|
||||
|
||||
/** Called every frame a unit is on this tile. */
|
||||
public void unitOn(Tile tile, Unit unit){
|
||||
public void unitOn(Tile tile, Unitc unit){
|
||||
}
|
||||
|
||||
/** Called when a unit that spawned at this tile is removed. */
|
||||
public void unitRemoved(Tile tile, Unit unit){
|
||||
public void unitRemoved(Tile tile, Unitc unit){
|
||||
}
|
||||
|
||||
/** Returns whether ot not this block can be place on the specified tile. */
|
||||
|
@ -1,21 +1,18 @@
|
||||
package mindustry.world;
|
||||
|
||||
import arc.struct.Array;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Vec2;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.Vars;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.Effects;
|
||||
import mindustry.entities.effect.Puddle;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.ctype.UnlockableContent;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.type.Liquid;
|
||||
import mindustry.world.consumers.Consumers;
|
||||
import mindustry.world.meta.BlockBars;
|
||||
import mindustry.world.meta.BlockStats;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.effect.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.consumers.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public abstract class BlockStorage extends UnlockableContent{
|
||||
public boolean hasItems;
|
||||
@ -51,7 +48,7 @@ public abstract class BlockStorage extends UnlockableContent{
|
||||
}
|
||||
|
||||
/** Returns the amount of items this block can accept. */
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
public int acceptStack(Item item, int amount, Tile tile, Teamc source){
|
||||
if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){
|
||||
return Math.min(getMaximumAccepted(tile, item) - tile.entity.items.get(item), amount);
|
||||
}else{
|
||||
@ -73,7 +70,7 @@ public abstract class BlockStorage extends UnlockableContent{
|
||||
}
|
||||
|
||||
/** Handle a stack input. */
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
public void handleStack(Item item, int amount, Tile tile, Teamc source){
|
||||
tile.entity.noSleep();
|
||||
tile.entity.items.add(item, amount);
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ public class BuildBlock extends Block{
|
||||
private float[] accumulator;
|
||||
private float[] totalAccumulator;
|
||||
|
||||
public boolean construct(Unit builder, @Nullable TileEntity core, float amount, boolean configured){
|
||||
public boolean construct(Unitc builder, @Nullable TileEntity core, float amount, boolean configured){
|
||||
if(cblock == null){
|
||||
kill();
|
||||
return false;
|
||||
@ -238,10 +238,7 @@ public class BuildBlock extends Block{
|
||||
maxProgress = core == null ? maxProgress : checkRequired(core.items, maxProgress, true);
|
||||
|
||||
progress = Mathf.clamp(progress + maxProgress);
|
||||
|
||||
if(builder instanceof Player){
|
||||
builderID = builder.getID();
|
||||
}
|
||||
builderID = builder.getId();
|
||||
|
||||
if(progress >= 1f || state.rules.infiniteResources){
|
||||
constructed(tile, cblock, builderID, tile.rotation(), builder.getTeam(), configured);
|
||||
@ -250,7 +247,7 @@ public class BuildBlock extends Block{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void deconstruct(Unit builder, @Nullable TileEntity core, float amount){
|
||||
public void deconstruct(Unitc builder, @Nullable TileEntity core, float amount){
|
||||
float deconstructMultiplier = 0.5f;
|
||||
|
||||
if(cblock != null){
|
||||
|
@ -1,14 +1,14 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.graphics.MultiPacker.*;
|
||||
import mindustry.type.*;
|
||||
|
@ -9,9 +9,7 @@ import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.type.BaseEntity;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
|
@ -4,7 +4,6 @@ import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.Fill;
|
||||
import arc.math.Mathf;
|
||||
import mindustry.entities.effect.Lightning;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.graphics.Layer;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.world.Block;
|
||||
@ -49,7 +48,7 @@ public class ShockMine extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Tile tile, Unit unit){
|
||||
public void unitOn(Tile tile, Unitc unit){
|
||||
if(unit.getTeam() != tile.getTeam() && tile.entity.timer.get(timerDamage, cooldown)){
|
||||
for(int i = 0; i < tendrils; i++){
|
||||
Lightning.create(tile.getTeam(), Pal.lancerLaser, damage, tile.drawx(), tile.drawy(), Mathf.random(360f), length);
|
||||
|
@ -86,7 +86,7 @@ public class ItemTurret extends CooledTurret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unitc source){
|
||||
TurretEntity entity = tile.ent();
|
||||
|
||||
BulletType type = ammo.get(item);
|
||||
@ -97,7 +97,7 @@ public class ItemTurret extends CooledTurret{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
public void handleStack(Item item, int amount, Tile tile, Unitc source){
|
||||
for(int i = 0; i < amount; i++){
|
||||
handleItem(item, tile, null);
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Tile tile, Unit unit){
|
||||
public void unitOn(Tile tile, Unitc unit){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
|
||||
if(entity.clogHeat > 0.5f){
|
||||
@ -256,13 +256,13 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unitc source){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
return Math.min((int)(entity.minitem / itemSpace), amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
public void handleStack(Item item, int amount, Tile tile, Unitc source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
|
||||
for(int i = amount - 1; i >= 0; i--){
|
||||
|
@ -2,7 +2,6 @@ package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.gen.BufferItem;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.Block;
|
||||
@ -31,7 +30,7 @@ public class Junction extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unitc source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@ -239,7 +238,7 @@ public class CoreBlock extends StorageBlock{
|
||||
protected int storageCapacity;
|
||||
|
||||
@Override
|
||||
public boolean hasUnit(Unit unit){
|
||||
public boolean hasUnit(Unitc unit){
|
||||
return unit == spawnPlayer;
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,11 @@ import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
@ -143,7 +141,7 @@ public class MechPad extends Block{
|
||||
float heat;
|
||||
|
||||
@Override
|
||||
public boolean hasUnit(Unit unit){
|
||||
public boolean hasUnit(Unitc unit){
|
||||
return unit == player;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@ import arc.math.geom.Rect;
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.Units;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.type.Unit;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
@ -141,7 +140,7 @@ public class RepairPoint extends Block{
|
||||
}
|
||||
|
||||
public class RepairPointEntity extends TileEntity{
|
||||
public Unit target;
|
||||
public Unitc target;
|
||||
public float strength, rotation = 90;
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ public class UnitFactory extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitRemoved(Tile tile, Unit unit){
|
||||
public void unitRemoved(Tile tile, Unitc unit){
|
||||
UnitFactoryEntity entity = tile.ent();
|
||||
entity.spawned--;
|
||||
entity.spawned = Math.max(entity.spawned, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user