Internal refactoring & cleanup
This commit is contained in:
@@ -74,15 +74,12 @@ public class GroundAI extends AIController{
|
||||
}*/
|
||||
}
|
||||
|
||||
protected void moveTo(int pathType){
|
||||
int costType =
|
||||
unit instanceof Legsc ? Pathfinder.costLegs :
|
||||
unit instanceof WaterMovec ? Pathfinder.costWater :
|
||||
Pathfinder.costGround;
|
||||
protected void moveTo(int pathTarget){
|
||||
int costType = unit.pathType();
|
||||
|
||||
Tile tile = unit.tileOn();
|
||||
if(tile == null) return;
|
||||
Tile targetTile = pathfinder.getTargetTile(tile, pathfinder.getField(unit.team, costType, pathType));
|
||||
Tile targetTile = pathfinder.getTargetTile(tile, pathfinder.getField(unit.team, costType, pathTarget));
|
||||
|
||||
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ public class TeamIndexProcess implements AsyncProcess{
|
||||
private QuadTree<Unit>[] trees = new QuadTree[Team.all.length];
|
||||
private int[] counts = new int[Team.all.length];
|
||||
private int[][] typeCounts = new int[Team.all.length][0];
|
||||
private int[][] activeCounts = new int[Team.all.length][0];
|
||||
|
||||
public QuadTree<Unit> tree(Team team){
|
||||
if(trees[team.id] == null) trees[team.id] = new QuadTree<>(Vars.world.getQuadBounds(new Rect()));
|
||||
@@ -30,10 +29,6 @@ public class TeamIndexProcess implements AsyncProcess{
|
||||
return typeCounts[team.id].length <= type.id ? 0 : typeCounts[team.id][type.id];
|
||||
}
|
||||
|
||||
public int countActive(Team team, UnitType type){
|
||||
return activeCounts[team.id].length <= type.id ? 0 : activeCounts[team.id][type.id];
|
||||
}
|
||||
|
||||
public void updateCount(Team team, UnitType type, int amount){
|
||||
counts[team.id] += amount;
|
||||
if(typeCounts[team.id].length <= type.id){
|
||||
@@ -42,16 +37,8 @@ public class TeamIndexProcess implements AsyncProcess{
|
||||
typeCounts[team.id][type.id] += amount;
|
||||
}
|
||||
|
||||
public void updateActiveCount(Team team, UnitType type, int amount){
|
||||
if(activeCounts[team.id].length <= type.id){
|
||||
activeCounts[team.id] = new int[Vars.content.units().size];
|
||||
}
|
||||
activeCounts[team.id][type.id] += amount;
|
||||
}
|
||||
|
||||
private void count(Unit unit){
|
||||
updateCount(unit.team, unit.type(), 1);
|
||||
if(!unit.deactivated) updateActiveCount(unit.team, unit.type(), 1);
|
||||
|
||||
if(unit instanceof Payloadc){
|
||||
((Payloadc)unit).payloads().each(p -> {
|
||||
@@ -77,7 +64,6 @@ public class TeamIndexProcess implements AsyncProcess{
|
||||
}
|
||||
|
||||
Arrays.fill(typeCounts[team.id], 0);
|
||||
Arrays.fill(activeCounts[team.id], 0);
|
||||
}
|
||||
|
||||
Arrays.fill(counts, 0);
|
||||
|
||||
@@ -1306,7 +1306,6 @@ public class UnitTypes implements ContentList{
|
||||
health = 280;
|
||||
accel = 0.4f;
|
||||
rotateSpeed = 3.3f;
|
||||
immunities = ObjectSet.with(StatusEffects.wet);
|
||||
trailLength = 20;
|
||||
rotateShooting = false;
|
||||
|
||||
@@ -1358,7 +1357,6 @@ public class UnitTypes implements ContentList{
|
||||
armor = 4f;
|
||||
accel = 0.3f;
|
||||
rotateSpeed = 2.6f;
|
||||
immunities = ObjectSet.with(StatusEffects.wet);
|
||||
rotateShooting = false;
|
||||
|
||||
trailLength = 20;
|
||||
@@ -1400,7 +1398,6 @@ public class UnitTypes implements ContentList{
|
||||
drag = 0.17f;
|
||||
hitsize = 16f;
|
||||
armor = 7f;
|
||||
immunities = ObjectSet.with(StatusEffects.wet);
|
||||
rotateShooting = false;
|
||||
|
||||
trailLength = 22;
|
||||
@@ -1495,7 +1492,6 @@ public class UnitTypes implements ContentList{
|
||||
hitsize = 39f;
|
||||
accel = 0.2f;
|
||||
rotateSpeed = 1.3f;
|
||||
immunities = ObjectSet.with(StatusEffects.wet);
|
||||
rotateShooting = false;
|
||||
|
||||
trailLength = 50;
|
||||
@@ -1580,10 +1576,9 @@ public class UnitTypes implements ContentList{
|
||||
armor = 16f;
|
||||
accel = 0.19f;
|
||||
rotateSpeed = 0.9f;
|
||||
immunities = ObjectSet.with(StatusEffects.wet);
|
||||
rotateShooting = false;
|
||||
|
||||
float spawnTime = 60f * 25f;
|
||||
float spawnTime = 60f * 15f;
|
||||
|
||||
abilities.add(new UnitSpawnAbility(flare, spawnTime, 19.25f, -31.75f), new UnitSpawnAbility(flare, spawnTime, -19.25f, -31.75f));
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class Units{
|
||||
if(unit != null){
|
||||
unit.dead = true;
|
||||
Fx.unitCapKill.at(unit);
|
||||
Core.app.post(() -> Call.unitDeath(unit.id));
|
||||
Core.app.post(() -> Call.unitDestroy(unit.id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,21 @@ public class Units{
|
||||
}
|
||||
}
|
||||
|
||||
//destroys immediately
|
||||
@Remote(called = Loc.server)
|
||||
public static void unitDestroy(int uid){
|
||||
Unit unit = Groups.unit.getByID(uid);
|
||||
|
||||
//if there's no unit don't add it later and get it stuck as a ghost
|
||||
if(netClient != null){
|
||||
netClient.addRemovedEntity(uid);
|
||||
}
|
||||
|
||||
if(unit != null){
|
||||
unit.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void unitDespawn(Unit unit){
|
||||
Fx.unitDespawn.at(unit.x, unit.y, 0, unit);
|
||||
|
||||
@@ -4,6 +4,12 @@ import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
//TODO this class is bad for multiple reasons, remove/replace it.
|
||||
//- effects unreliable
|
||||
//- not really hitscan but works like it
|
||||
//- buggy trails
|
||||
//- looks bad
|
||||
//- generally unreliable
|
||||
public class RailBulletType extends BulletType{
|
||||
public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
|
||||
/** Multiplier of damage decreased per health pierced. */
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.EntityCollisions.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@Component
|
||||
abstract class ElevationMoveComp implements Velc, Posc, Flyingc, Hitboxc{
|
||||
@Import float x, y;
|
||||
|
||||
@Replace
|
||||
@Override
|
||||
public void move(float cx, float cy){
|
||||
if(isFlying()){
|
||||
x += cx;
|
||||
y += cy;
|
||||
}else{
|
||||
collisions.move(this, cx, cy);
|
||||
}
|
||||
public SolidPred solidity(){
|
||||
return isFlying() ? null : EntityCollisions::solid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,16 +4,16 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.EntityCollisions.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@Component
|
||||
abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
||||
@Import float x, y;
|
||||
@@ -26,8 +26,14 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
||||
|
||||
@Replace
|
||||
@Override
|
||||
public void move(float cx, float cy){
|
||||
collisions.moveCheck(this, cx, cy, !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid);
|
||||
public SolidPred solidity(){
|
||||
return !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Replace
|
||||
public int pathType(){
|
||||
return Pathfinder.costLegs;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -9,11 +10,23 @@ import mindustry.gen.*;
|
||||
abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, ElevationMovec{
|
||||
@SyncField(false) @SyncLocal float baseRotation;
|
||||
transient float walkTime, walkExtension;
|
||||
transient private boolean walked;
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
float len = deltaLen();
|
||||
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
|
||||
walkTime += len;
|
||||
//trigger animation only when walking manually
|
||||
if(walked){
|
||||
float len = deltaLen();
|
||||
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
|
||||
walkTime += len;
|
||||
walked = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAt(Vec2 vector, float acceleration){
|
||||
if(!vector.isZero()){
|
||||
walked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,11 +98,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
||||
Unit u = payload.unit;
|
||||
|
||||
//can't drop ground units
|
||||
//TODO bad code, solidity should not be handled this way
|
||||
if(
|
||||
((tileOn() == null || tileOn().solid()) && u.elevation < 0.1f && !u.type().allowLegStep) ||
|
||||
(!floorOn().isLiquid && u instanceof WaterMovec) ||
|
||||
(u.type().allowLegStep && EntityCollisions.legsSolid(u.tileX(), u.tileY()))){
|
||||
if(!u.canPassOn()){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
@@ -37,7 +38,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
|
||||
private UnitController controller;
|
||||
private UnitType type;
|
||||
boolean spawnedByCore, deactivated; //TODO remove deactivation boolean
|
||||
boolean spawnedByCore;
|
||||
|
||||
transient Seq<Ability> abilities = new Seq<>(0);
|
||||
|
||||
@@ -103,7 +104,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
@Override
|
||||
@Replace
|
||||
public boolean canDrown(){
|
||||
return isGrounded() && !hovering && type.canDrown && !(this instanceof WaterMovec);
|
||||
return isGrounded() && !hovering && type.canDrown;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,6 +150,11 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
return type;
|
||||
}
|
||||
|
||||
/** @return pathfinder path type for calculating costs */
|
||||
public int pathType(){
|
||||
return Pathfinder.costGround;
|
||||
}
|
||||
|
||||
public void lookAt(float angle){
|
||||
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta * speedMultiplier());
|
||||
}
|
||||
@@ -206,12 +212,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
public void add(){
|
||||
|
||||
//check if over unit cap
|
||||
if(count() > cap() && !spawnedByCore){
|
||||
deactivated = true;
|
||||
|
||||
if(!dead){
|
||||
Call.unitCapDeath(self());
|
||||
}
|
||||
if(count() > cap() && !spawnedByCore && !dead){
|
||||
Call.unitCapDeath(self());
|
||||
teamIndex.updateCount(team, type, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,22 +235,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
//activate the unit when possible
|
||||
if(!net.client() && deactivated && teamIndex.countActive(team, type) < Units.getCap(team)){
|
||||
teamIndex.updateActiveCount(team, type, 1);
|
||||
deactivated = false;
|
||||
}
|
||||
|
||||
if(!deactivated){
|
||||
type.update(self());
|
||||
type.update(self());
|
||||
|
||||
if(abilities.size > 0){
|
||||
for(Ability a : abilities){
|
||||
a.update(self());
|
||||
}
|
||||
if(abilities.size > 0){
|
||||
for(Ability a : abilities){
|
||||
a.update(self());
|
||||
}
|
||||
}else if(!dead){
|
||||
Call.unitCapDeath(self());
|
||||
}
|
||||
|
||||
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
|
||||
@@ -305,18 +299,20 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
if(floor.damageTaken > 0f){
|
||||
damageContinuous(floor.damageTaken);
|
||||
}
|
||||
}
|
||||
|
||||
if(tile.solid()){
|
||||
if(type.canBoost){
|
||||
elevation = 1f;
|
||||
}else if(!net.client()){
|
||||
kill();
|
||||
}
|
||||
//kill entities on tiles that are solid to them
|
||||
if(tile != null && !canPassOn()){
|
||||
//boost if possible
|
||||
if(type.canBoost){
|
||||
elevation = 1f;
|
||||
}else if(!net.client()){
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
//AI only updates on the server
|
||||
if(!net.client() && !dead && !deactivated){
|
||||
if(!net.client() && !dead){
|
||||
controller.updateUnit();
|
||||
}
|
||||
|
||||
@@ -325,11 +321,6 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
resetController();
|
||||
}
|
||||
|
||||
//do not control anything when deactivated
|
||||
if(deactivated){
|
||||
controlWeapons(false, false);
|
||||
}
|
||||
|
||||
//remove units spawned by the core
|
||||
if(spawnedByCore && !isPlayer()){
|
||||
Call.unitDespawn(self());
|
||||
|
||||
@@ -3,9 +3,13 @@ package mindustry.entities.comp;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.EntityCollisions.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@Component
|
||||
abstract class VelComp implements Posc{
|
||||
@Import float x, y;
|
||||
@@ -22,12 +26,35 @@ abstract class VelComp implements Posc{
|
||||
vel.scl(Mathf.clamp(1f - drag * Time.delta));
|
||||
}
|
||||
|
||||
/** @return function to use for check solid state. if null, no checking is done. */
|
||||
@Nullable
|
||||
SolidPred solidity(){
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return whether this entity can move through a location*/
|
||||
boolean canPass(int tileX, int tileY){
|
||||
SolidPred s = solidity();
|
||||
return s == null || !s.solid(tileX, tileY);
|
||||
}
|
||||
|
||||
/** @return whether this entity can exist on its current location*/
|
||||
boolean canPassOn(){
|
||||
return canPass(tileX(), tileY());
|
||||
}
|
||||
|
||||
boolean moving(){
|
||||
return !vel.isZero(0.01f);
|
||||
}
|
||||
|
||||
void move(float cx, float cy){
|
||||
x += cx;
|
||||
y += cy;
|
||||
SolidPred check = solidity();
|
||||
|
||||
if(check != null){
|
||||
collisions.move(self(), cx, cy, check);
|
||||
}else{
|
||||
x += cx;
|
||||
y += cy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,17 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.EntityCollisions.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
//just a proof of concept
|
||||
@Component
|
||||
abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
|
||||
@@ -38,16 +38,8 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
|
||||
|
||||
@Override
|
||||
@Replace
|
||||
public void lookAt(float angle){
|
||||
if(onLiquid()){
|
||||
rotation = Angles.moveToward(rotation, angle, type.rotateSpeed * Time.delta);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Replace
|
||||
public boolean canShoot(){
|
||||
return onLiquid();
|
||||
public int pathType(){
|
||||
return Pathfinder.costWater;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,13 +66,8 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc, Unitc{
|
||||
|
||||
@Replace
|
||||
@Override
|
||||
public void move(float cx, float cy){
|
||||
if(isGrounded()){
|
||||
collisions.moveCheck(this, cx, cy, EntityCollisions::waterSolid);
|
||||
}else{
|
||||
x += cx;
|
||||
y += cy;
|
||||
}
|
||||
public SolidPred solidity(){
|
||||
return isFlying() ? null : EntityCollisions::waterSolid;
|
||||
}
|
||||
|
||||
@Replace
|
||||
|
||||
@@ -596,7 +596,7 @@ public class DesktopInput extends InputHandler{
|
||||
}
|
||||
|
||||
protected void updateMovement(Unit unit){
|
||||
boolean omni = !(unit instanceof WaterMovec);
|
||||
boolean omni = unit.type().omniMovement;
|
||||
boolean ground = unit.isGrounded();
|
||||
|
||||
float strafePenalty = ground ? 1f : Mathf.lerp(1f, unit.type().strafePenalty, Angles.angleDist(unit.vel().angle(), unit.rotation()) / 180f);
|
||||
|
||||
@@ -292,7 +292,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}else if(unit == null){ //just clear the unit (is this used?)
|
||||
player.clearUnit();
|
||||
//make sure it's AI controlled, so players can't overwrite each other
|
||||
}else if(unit.isAI() && unit.team == player.team() && !unit.deactivated() && !unit.dead){
|
||||
}else if(unit.isAI() && unit.team == player.team() && !unit.dead){
|
||||
if(!net.client()){
|
||||
player.unit(unit);
|
||||
}
|
||||
@@ -365,7 +365,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
|
||||
if(controlledType != null && player.dead()){
|
||||
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.deactivated() && !u.dead);
|
||||
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.dead);
|
||||
|
||||
if(unit != null){
|
||||
Call.unitControl(player, unit);
|
||||
@@ -375,7 +375,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
public void checkUnit(){
|
||||
if(controlledType != null){
|
||||
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.deactivated() && !u.dead);
|
||||
Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.dead);
|
||||
if(unit == null && controlledType == UnitTypes.block){
|
||||
unit = world.buildWorld(player.x, player.y) instanceof ControlBlock ? ((ControlBlock)world.buildWorld(player.x, player.y)).unit() : null;
|
||||
}
|
||||
@@ -931,7 +931,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
|
||||
public @Nullable Unit selectedUnit(){
|
||||
Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> u.isAI() && !u.deactivated());
|
||||
Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, u -> u.isAI());
|
||||
if(unit != null){
|
||||
unit.hitbox(Tmp.r1);
|
||||
Tmp.r1.grow(6f);
|
||||
|
||||
@@ -804,7 +804,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(type == null) return;
|
||||
|
||||
boolean flying = type.flying;
|
||||
boolean omni = !(unit instanceof WaterMovec);
|
||||
boolean omni = unit.type().omniMovement;
|
||||
boolean legs = unit.isGrounded();
|
||||
boolean allowHealing = type.canHeal;
|
||||
boolean validHealTarget = allowHealing && target instanceof Building && ((Building)target).isValid() && target.team() == unit.team &&
|
||||
|
||||
@@ -55,6 +55,7 @@ public class UnitType extends UnlockableContent{
|
||||
public float visualElevation = -1f;
|
||||
public boolean allowLegStep = false;
|
||||
public boolean hovering = false;
|
||||
public boolean omniMovement = true;
|
||||
public Effect fallEffect = Fx.fallSmoke;
|
||||
public Effect fallThrusterEffect = Fx.fallSmoke;
|
||||
public Seq<Ability> abilities = new Seq<>();
|
||||
@@ -195,13 +196,6 @@ public class UnitType extends UnlockableContent{
|
||||
}).growX();
|
||||
|
||||
table.row();
|
||||
if(unit.deactivated){
|
||||
table.table(d -> {
|
||||
d.left();
|
||||
d.label(() -> Core.bundle.format("bar.limitreached", unit.count(), unit.cap(), Fonts.getUnicodeStr(name)));
|
||||
}).left().visible(() -> unit.deactivated);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -231,6 +225,15 @@ public class UnitType extends UnlockableContent{
|
||||
public void init(){
|
||||
if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'");
|
||||
|
||||
Unit example = constructor.get();
|
||||
|
||||
//water preset
|
||||
if(example instanceof WaterMovec){
|
||||
canDrown = false;
|
||||
omniMovement = false;
|
||||
immunities.add(StatusEffects.wet);
|
||||
}
|
||||
|
||||
singleTarget = weapons.size <= 1;
|
||||
|
||||
if(itemCapacity < 0){
|
||||
@@ -397,10 +400,6 @@ public class UnitType extends UnlockableContent{
|
||||
unit.trns(-legOffset.x, -legOffset.y);
|
||||
}
|
||||
|
||||
if(unit.deactivated){
|
||||
drawDeactive(unit);
|
||||
}
|
||||
|
||||
if(unit.abilities.size > 0){
|
||||
for(Ability a : unit.abilities){
|
||||
Draw.reset();
|
||||
@@ -411,16 +410,6 @@ public class UnitType extends UnlockableContent{
|
||||
}
|
||||
}
|
||||
|
||||
public void drawDeactive(Unit unit){
|
||||
Draw.color(Color.scarlet);
|
||||
Draw.alpha(0.8f);
|
||||
|
||||
float size = 8f;
|
||||
Draw.rect(Icon.warning.getRegion(), unit.x, unit.y, size, size);
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public <T extends Unit & Payloadc> void drawPayload(T unit){
|
||||
if(unit.hasPayload()){
|
||||
Payload pay = unit.payloads().first();
|
||||
|
||||
@@ -17,7 +17,7 @@ import mindustry.world.blocks.production.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class PayloadConveyor extends Block{
|
||||
public float moveTime = 50f;
|
||||
public float moveTime = 40f, moveForce = 201f;
|
||||
public @Load("@-top") TextureRegion topRegion;
|
||||
public @Load("@-edge") TextureRegion edgeRegion;
|
||||
public Interp interp = Interp.pow5;
|
||||
@@ -53,6 +53,7 @@ public class PayloadConveyor extends Block{
|
||||
public class PayloadConveyorBuild extends Building{
|
||||
public @Nullable Payload item;
|
||||
public float progress, itemRotation, animation;
|
||||
public float curInterp, lastInterp;
|
||||
public @Nullable Building next;
|
||||
public boolean blocked;
|
||||
public int step = -1, stepAccepted = -1;
|
||||
@@ -99,6 +100,10 @@ public class PayloadConveyor extends Block{
|
||||
public void updateTile(){
|
||||
if(!enabled) return;
|
||||
|
||||
lastInterp = curInterp;
|
||||
curInterp = fract();
|
||||
//rollover skip
|
||||
if(lastInterp > curInterp) lastInterp = 0f;
|
||||
progress = time() % moveTime;
|
||||
|
||||
updatePayload();
|
||||
@@ -201,6 +206,14 @@ public class PayloadConveyor extends Block{
|
||||
return Time.time();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitOn(Unit unit){
|
||||
//calculate derivative of units moved last frame
|
||||
float delta = (curInterp - lastInterp) * size * tilesize;
|
||||
Tmp.v1.trns(rotdeg(), delta * moveForce).scl(1f / Math.max(unit.mass(), 201f));
|
||||
unit.move(Tmp.v1.x, Tmp.v1.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptPayload(Building source, Payload payload){
|
||||
if(source == this){
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.EntityCollisions.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
@@ -47,15 +48,16 @@ public class UnitPayload implements Payload{
|
||||
return false;
|
||||
}
|
||||
|
||||
//naval units need water.
|
||||
if(unit instanceof WaterMovec){
|
||||
//check if unit can be dumped here
|
||||
SolidPred solid = unit.solidity();
|
||||
if(solid != null){
|
||||
int tx = unit.tileX(), ty = unit.tileY();
|
||||
boolean nearEmpty = !EntityCollisions.waterSolid(tx, ty);
|
||||
boolean nearEmpty = !solid.solid(tx, ty);
|
||||
for(Point2 p : Geometry.d4){
|
||||
nearEmpty |= !EntityCollisions.waterSolid(tx + p.x, ty + p.y);
|
||||
nearEmpty |= !solid.solid(tx + p.x, ty + p.y);
|
||||
}
|
||||
|
||||
//cannot dump on dry land
|
||||
//cannot dump on solid blocks
|
||||
if(!nearEmpty) return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user