Merge branch 'master' into ground-support-heal

This commit is contained in:
genNAowl
2020-10-30 12:37:33 -07:00
committed by GitHub
433 changed files with 12068 additions and 7130 deletions

View File

@@ -9,6 +9,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -82,7 +83,7 @@ public class Damage{
furthest = null;
boolean found = world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y),
boolean found = world.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers);
return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;

View File

@@ -27,8 +27,8 @@ public class Effect{
/** Clip size. */
public float size;
public boolean ground;
public float groundDuration;
public float layer = Layer.effect;
public float layerDuration;
public Effect(float life, float clipsize, Cons<EffectContainer> renderer){
this.id = all.size;
@@ -42,14 +42,14 @@ public class Effect{
this(life,50f, renderer);
}
public Effect ground(){
ground = true;
public Effect layer(float l){
layer = l;
return this;
}
public Effect ground(float duration){
ground = true;
this.groundDuration = duration;
public Effect layer(float l, float duration){
layer = l;
this.layerDuration = duration;
return this;
}
@@ -87,7 +87,7 @@ public class Effect{
public float render(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){
container.set(id, color, life, lifetime, rotation, x, y, data);
Draw.z(ground ? Layer.debris : Layer.effect);
Draw.z(layer);
Draw.reset();
renderer.get(container);
Draw.reset();
@@ -209,4 +209,4 @@ public class Effect{
}
}
}
}

View File

@@ -23,14 +23,14 @@ public class Fires{
if(fire == null){
fire = Fire.create();
fire.tile(tile);
fire.lifetime(baseLifetime);
fire.tile = tile;
fire.lifetime = baseLifetime;
fire.set(tile.worldx(), tile.worldy());
fire.add();
map.put(tile.pos(), fire);
}else{
fire.lifetime(baseLifetime);
fire.time(0f);
fire.lifetime = baseLifetime;
fire.time = 0f;
}
}

View File

@@ -11,5 +11,6 @@ class GroupDefs<G>{
@GroupDef(value = Buildingc.class) G build;
@GroupDef(value = Syncc.class, mapping = true) G sync;
@GroupDef(value = Drawc.class) G draw;
@GroupDef(value = Firec.class) G fire;
@GroupDef(value = WeatherStatec.class) G weather;
}

View File

@@ -5,6 +5,7 @@ import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.entities.bullet.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -54,7 +55,7 @@ public class Lightning{
bhit = false;
Vec2 from = lines.get(lines.size - 2);
Vec2 to = lines.get(lines.size - 1);
world.raycastEach(world.toTile(from.getX()), world.toTile(from.getY()), world.toTile(to.getX()), world.toTile(to.getY()), (wx, wy) -> {
world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
Tile tile = world.tile(wx, wy);
if(tile != null && tile.block().insulated){

View File

@@ -53,13 +53,13 @@ public class Predict{
public static Vec2 intercept(Position src, Position dst, float v){
float ddx = 0, ddy = 0;
if(dst instanceof Hitboxc){
ddx += ((Hitboxc)dst).deltaX();
ddy += ((Hitboxc)dst).deltaY();
if(dst instanceof Hitboxc h){
ddx += h.deltaX();
ddy += h.deltaY();
}
if(src instanceof Hitboxc){
ddx -= ((Hitboxc)src).deltaX()/(Time.delta);
ddy -= ((Hitboxc)src).deltaY()/(Time.delta);
if(src instanceof Hitboxc h){
ddx -= h.deltaX()/(Time.delta);
ddy -= h.deltaY()/(Time.delta);
}
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), ddx, ddy, v);
}

View File

@@ -126,7 +126,7 @@ public class Units{
nearby(x, y, width, height, unit -> {
if(boolResult) return;
if((unit.isGrounded() && !unit.type().hovering) == ground){
if((unit.isGrounded() && !unit.type.hovering) == ground){
unit.hitbox(hitrect);
if(hitrect.overlaps(x, y, width, height)){

View File

@@ -1,5 +1,6 @@
package mindustry.entities.abilities;
import arc.*;
import mindustry.gen.*;
public abstract class Ability implements Cloneable{
@@ -14,4 +15,9 @@ public abstract class Ability implements Cloneable{
throw new RuntimeException("java sucks", e);
}
}
/** @return localized ability name; mods should override this. */
public String localized(){
return Core.bundle.get("ability." + getClass().getSimpleName().replace("Ability", "").toLowerCase());
}
}

View File

@@ -0,0 +1,46 @@
package mindustry.entities.abilities;
import arc.graphics.*;
import arc.math.*;
import arc.util.*;
import arc.audio.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class MoveLightningAbility extends Ability{
//Lightning damage
public float damage = 35f;
//Chance of firing every tick. Set >= 1 to always fire lightning every tick at max speed.
public float chance = 0.15f;
//Length of the lightning
public int length = 12;
//Speeds for when to start lightninging and when to stop getting faster
public float minSpeed = 0.8f, maxSpeed = 1.2f;
//Lightning color
public Color color = Color.valueOf("a9d8ff");
public Effect shootEffect = Fx.sparkShoot;
public Sound shootSound = Sounds.spark;
MoveLightningAbility(){}
public MoveLightningAbility(float damage, int length, float chance, float minSpeed, float maxSpeed, Color color){
this.damage = damage;
this.length = length;
this.chance = chance;
this.minSpeed = minSpeed;
this.maxSpeed = maxSpeed;
this.color = color;
}
@Override
public void update(Unit unit){
float scl = Mathf.clamp((unit.vel().len() - minSpeed) / (maxSpeed - minSpeed));
if(Mathf.chance(Time.delta * chance * scl)){
shootEffect.at(unit.x, unit.y, unit.rotation, color);
Lightning.create(unit.team, color, damage, unit.x + unit.vel.x, unit.y + unit.vel.y, unit.rotation, length);
shootSound.at(unit);
}
}
}

View File

@@ -5,7 +5,7 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class HealFieldAbility extends Ability{
public class RepairFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWaveDynamic;
@@ -13,9 +13,9 @@ public class HealFieldAbility extends Ability{
protected float timer;
protected boolean wasHealed = false;
HealFieldAbility(){}
RepairFieldAbility(){}
public HealFieldAbility(float amount, float reload, float range){
public RepairFieldAbility(float amount, float reload, float range){
this.amount = amount;
this.reload = reload;
this.range = range;

View File

@@ -5,7 +5,7 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class ShieldFieldAbility extends Ability{
public class ShieldRegenFieldAbility extends Ability{
public float amount = 1, max = 100f, reload = 100, range = 60;
public Effect applyEffect = Fx.shieldApply;
public Effect activeEffect = Fx.shieldWave;
@@ -13,9 +13,9 @@ public class ShieldFieldAbility extends Ability{
protected float timer;
protected boolean applied = false;
ShieldFieldAbility(){}
ShieldRegenFieldAbility(){}
public ShieldFieldAbility(float amount, float max, float reload, float range){
public ShieldRegenFieldAbility(float amount, float max, float reload, float range){
this.amount = amount;
this.max = max;
this.reload = reload;

View File

@@ -1,5 +1,6 @@
package mindustry.entities.abilities;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
@@ -56,4 +57,9 @@ public class UnitSpawnAbility extends Ability{
});
}
}
@Override
public String localized(){
return Core.bundle.format("ability.unitspawn", type.localizedName);
}
}

View File

@@ -79,8 +79,10 @@ public abstract class BulletType extends Content{
public boolean backMove = true;
/** Bullet range override. */
public float range = -1f;
/** Heal Bullet Percent **/
/** % of block health healed **/
public float healPercent = 0f;
/** whether to make fire on impact */
public boolean makeFire = false;
//additional effects
@@ -104,6 +106,8 @@ public abstract class BulletType extends Content{
public float incendChance = 1f;
public float homingPower = 0f;
public float homingRange = 50f;
/** Use a negative value to disable homing delay. */
public float homingDelay = -1f;
public Color lightningColor = Pal.surge;
public int lightning;
@@ -158,7 +162,7 @@ public abstract class BulletType extends Content{
}
public void hitTile(Bullet b, Building tile, float initialHealth){
if(status == StatusEffects.burning){
if(makeFire){
Fires.create(tile.tile);
}
@@ -210,14 +214,14 @@ public abstract class BulletType extends Content{
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround);
}
if(healPercent > 0f) {
if(healPercent > 0f){
indexer.eachBlock(b.team, x, y, splashDamageRadius, other -> other.damaged(), other -> {
Fx.healBlockFull.at(other.x, other.y, other.block.size, Pal.heal);
other.heal(healPercent / 100f * other.maxHealth());
});
}
if(status == StatusEffects.burning) {
if(makeFire){
indexer.eachBlock(null, x, y, splashDamageRadius, other -> other.team != b.team, other -> {
Fires.create(other.tile);
});
@@ -248,7 +252,7 @@ public abstract class BulletType extends Content{
}
public void init(Bullet b){
if(pierceCap >= 1) {
if(pierceCap >= 1){
pierce = true;
//pierceBuilding is not enabled by default, because a bullet may want to *not* pierce buildings
}
@@ -263,7 +267,7 @@ public abstract class BulletType extends Content{
}
public void update(Bullet b){
if(homingPower > 0.0001f){
if(homingPower > 0.0001f && b.time >= homingDelay){
Teamc target = Units.closestTarget(b.team, b.x, b.y, homingRange, e -> (e.isGrounded() && collidesGround) || (e.isFlying() && collidesAir), t -> collidesGround);
if(target != null){
b.vel.setAngle(Mathf.slerpDelta(b.rotation(), b.angleTo(target), homingPower));

View File

@@ -39,6 +39,11 @@ public class LaserBulletType extends BulletType{
this(1f);
}
@Override
public float estimateDPS(){
return super.estimateDPS() * 2f;
}
@Override
public void init(){
super.init();

View File

@@ -22,6 +22,8 @@ public class LiquidBulletType extends BulletType{
if(liquid != null){
this.liquid = liquid;
this.status = liquid.effect;
lightColor = liquid.lightColor;
lightOpacity = liquid.lightColor.a;
}
ammoMultiplier = 1f;

View File

@@ -207,7 +207,8 @@ abstract class BuilderComp implements Unitc{
BuildPlan plan = buildPlan();
Tile tile = world.tile(plan.x, plan.y);
if((!within(tile, buildingRange) && !state.isEditor()) || tile == null){
if(tile == null || (!within(tile, buildingRange) && !state.isEditor())){
return;
}

View File

@@ -17,16 +17,19 @@ import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.audio.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.ConstructBlock.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
import mindustry.world.blocks.power.*;
@@ -191,6 +194,36 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
//endregion
//region utility methods
public void addPlan(boolean checkPrevious){
if(!block.rebuildable) return;
if(self() instanceof ConstructBuild entity){
//update block to reflect the fact that something was being constructed
if(entity.cblock != null && entity.cblock.synthetic()){
block = entity.cblock;
}else{
//otherwise this was a deconstruction that was interrupted, don't want to rebuild that
return;
}
}
TeamData data = state.teams.get(team);
if(checkPrevious){
//remove existing blocks that have been placed here.
//painful O(n) iteration + copy
for(int i = 0; i < data.blocks.size; i++){
BlockPlan b = data.blocks.get(i);
if(b.x == tile.x && b.y == tile.y){
data.blocks.removeIndex(i);
break;
}
}
}
data.blocks.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, block.id, config()));
}
/** Configure with the current, local player. */
public void configure(Object value){
//save last used config
@@ -431,7 +464,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
*/
public boolean movePayload(Payload todump){
int trns = block.size/2 + 1;
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
Tile next = tile.nearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(self(), todump)){
next.build.handlePayload(self(), todump);
@@ -514,7 +547,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public float moveLiquidForward(boolean leaks, Liquid liquid){
Tile next = tile.getNearby(rotation);
Tile next = tile.nearby(rotation);
if(next == null) return 0;
@@ -836,7 +869,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void placed(){
if(net.client()) return;
if((block.consumesPower && !block.outputsPower) || (!block.consumesPower && block.outputsPower)){
if(block.consumesPower || block.outputsPower){
int range = 10;
tempTiles.clear();
Geometry.circle(tileX(), tileY(), range, (x, y) -> {
@@ -878,7 +911,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Called when arbitrary configuration is applied to a tile. */
public void configured(@Nullable Unit builder, @Nullable Object value){
//null is of type void.class; anonymous classes use their superclass.
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() || value.getClass().getSimpleName().startsWith("adapter") ? value.getClass().getSuperclass() : value.getClass();
if(builder != null && builder.isPlayer()){
lastAccessed = builder.getPlayer().name;
@@ -1234,8 +1267,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
@Override
public double sense(LAccess sensor){
return switch(sensor){
case x -> x;
case y -> y;
case x -> World.conv(x);
case y -> World.conv(y);
case team -> team.id;
case health -> health;
case maxHealth -> maxHealth;
@@ -1244,8 +1277,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
case totalItems -> items == null ? 0 : items.total();
case totalLiquids -> liquids == null ? 0 : liquids.total();
case totalPower -> power == null || !block.consumes.hasPower() ? 0 : power.status * (block.consumes.getPower().buffered ? block.consumes.getPower().capacity : 1f);
case itemCapacity -> block.itemCapacity;
case liquidCapacity -> block.liquidCapacity;
case itemCapacity -> block.hasItems ? block.itemCapacity : 0;
case liquidCapacity -> block.hasLiquids ? block.liquidCapacity : 0;
case powerCapacity -> block.consumes.hasPower() ? block.consumes.getPower().capacity : 0f;
case powerNetIn -> power == null ? 0 : power.graph.getLastScaledPowerIn() * 60;
case powerNetOut -> power == null ? 0 : power.graph.getLastScaledPowerOut() * 60;
@@ -1263,7 +1296,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
case type -> block;
case firstItem -> items == null ? null : items.first();
case config -> block.configurations.containsKey(Item.class) || block.configurations.containsKey(Liquid.class) ? config() : null;
case payloadType -> getPayload() instanceof UnitPayload p1 ? p1.unit.type() : getPayload() instanceof BuildPayload p2 ? p2.block() : null;
case payloadType -> getPayload() instanceof UnitPayload p1 ? p1.unit.type : getPayload() instanceof BuildPayload p2 ? p2.block() : null;
default -> noSensed;
};
@@ -1286,7 +1319,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
@Override
public void control(LAccess type, Object p1, double p2, double p3, double p4){
if(type == LAccess.configure && block.logicConfigurable){
//change config only if it's new
Object prev = senseObject(LAccess.config);
if(prev != p1){
configureAny(p1);
}
}
}
@Override

View File

@@ -7,6 +7,7 @@ import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.core.*;
import mindustry.entities.bullet.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
@@ -110,7 +111,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
type.update(self());
if(type.collidesTiles && type.collides && type.collidesGround){
world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
world.raycastEach(World.toTile(lastX()), World.toTile(lastY()), tileX(), tileY(), (x, y) -> {
Building tile = world.build(x, y);
if(tile == null || !isAdded()) return false;
@@ -141,7 +142,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
});
}
if(type.pierceCap != -1 && collided.size >= type.pierceCap) {
if(type.pierceCap != -1 && collided.size >= type.pierceCap){
remove();
}
}

View File

@@ -30,7 +30,7 @@ abstract class CommanderComp implements Entityc, Posc{
public void update(){
if(formation != null){
formation.anchor.set(x, y, /*rotation*/ 0); //TODO rotation set to 0 because rotating is pointless
formation.anchor.set(x, y, 0);
formation.updateSlots();
}
}
@@ -59,7 +59,7 @@ abstract class CommanderComp implements Entityc, Posc{
units.clear();
Units.nearby(team, x, y, 150f, u -> {
if(u.isAI() && include.get(u) && u != self() && u.type().flying == type.flying && u.hitSize <= hitSize * 1.1f){
if(u.isAI() && include.get(u) && u != self() && u.type.flying == type.flying && u.hitSize <= hitSize * 1.1f){
units.add(u);
}
});
@@ -74,7 +74,7 @@ abstract class CommanderComp implements Entityc, Posc{
void command(Formation formation, Seq<Unit> units){
clearCommand();
float spacing = hitSize * 0.65f;
float spacing = hitSize * 0.8f;
minFormationSpeed = type.speed;
controlling.addAll(units);
@@ -82,7 +82,7 @@ abstract class CommanderComp implements Entityc, Posc{
FormationAI ai;
unit.controller(ai = new FormationAI(self(), formation));
spacing = Math.max(spacing, ai.formationSize());
minFormationSpeed = Math.min(minFormationSpeed, unit.type().speed);
minFormationSpeed = Math.min(minFormationSpeed, unit.type.speed);
}
this.formation = formation;
@@ -106,7 +106,7 @@ abstract class CommanderComp implements Entityc, Posc{
//reset controlled units
for(Unit unit : controlling){
if(unit.controller().isBeingControlled(self())){
unit.controller(unit.type().createController());
unit.controller(unit.type.createController());
}
}

View File

@@ -16,7 +16,7 @@ import static mindustry.Vars.*;
@EntityDef(value = {Firec.class}, pooled = true)
@Component(base = true)
abstract class FireComp implements Timedc, Posc, Firec, Syncc{
private static final float spreadChance = 0.05f, fireballChance = 0.07f;
private static final float spreadChance = 0.04f, fireballChance = 0.06f;
@Import float time, lifetime, x, y;

View File

@@ -73,4 +73,4 @@ abstract class LaunchCoreComp implements Drawc, Timedc{
Fx.rocketSmokeLarge.at(cx() + Mathf.range(r), cy() + Mathf.range(r), fin());
}
}
}
}

View File

@@ -32,12 +32,16 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
boolean mining(){
return mineTile != null && !(((Object)this) instanceof Builderc && ((Builderc)(Object)this).activelyBuilding());
return mineTile != null && !(((Object)this) instanceof Builderc b && b.activelyBuilding());
}
public boolean validMine(Tile tile, boolean checkDst){
return !(tile == null || tile.block() != Blocks.air || (!within(tile.worldx(), tile.worldy(), miningRange) && checkDst)
|| tile.drop() == null || !canMine(tile.drop()));
}
public boolean validMine(Tile tile){
return !(tile == null || tile.block() != Blocks.air || !within(tile.worldx(), tile.worldy(), miningRange)
|| tile.drop() == null || !canMine(tile.drop()));
return validMine(tile, true);
}
@Override
@@ -54,7 +58,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
}
if(core == null || !validMine(mineTile)){
if(!validMine(mineTile)){
mineTile = null;
mineTimer = 0f;
}else if(mining()){
@@ -69,7 +73,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
if(mineTimer >= 50f + item.hardness*15f){
mineTimer = 0;
if(within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
Call.transferItemTo(item, 1,
mineTile.worldx() + Mathf.range(tilesize / 2f),
mineTile.worldy() + Mathf.range(tilesize / 2f), core);
@@ -84,15 +88,13 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
mineTimer = 0f;
}
}
}
}
@Override
public void draw(){
if(!mining()) return;
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float focusLen = hitSize() / 2f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float swingScl = 12f, swingMag = tilesize / 8f;
float flashScl = 0.3f;

View File

@@ -6,6 +6,7 @@ import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
@@ -120,7 +121,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
/** @return whether the tile has been successfully placed. */
boolean dropBlock(BuildPayload payload){
Building tile = payload.build;
int tx = Vars.world.toTile(x - tile.block.offset), ty = Vars.world.toTile(y - tile.block.offset);
int tx = World.toTile(x - tile.block.offset), ty = World.toTile(y - tile.block.offset);
Tile on = Vars.world.tile(tx, ty);
if(on != null && Build.validPlace(tile.block, tile.team, tx, ty, tile.rotation, false)){
int rot = (int)((rotation + 45f) / 90f) % 4;

View File

@@ -78,8 +78,9 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
team = state.rules.defaultTeam;
admin = typing = false;
textFadeTime = 0f;
x = y = 0f;
if(!dead()){
unit.controller(unit.type().createController());
unit.controller(unit.type.createController());
unit = Nulls.unit;
}
}
@@ -91,7 +92,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
@Replace
public float clipSize(){
return unit.isNull() ? 20 : unit.type().hitSize * 2f;
return unit.isNull() ? 20 : unit.type.hitSize * 2f;
}
@Override
@@ -123,7 +124,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
deathTimer = 0;
//update some basic state to sync things
if(unit.type().canBoost){
if(unit.type.canBoost){
Tile tile = unit.tileOn();
unit.elevation = Mathf.approachDelta(unit.elevation, (tile != null && tile.solid()) || boosting ? 1f : 0f, 0.08f);
}
@@ -177,7 +178,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
if(this.unit != Nulls.unit){
//un-control the old unit
this.unit.controller(this.unit.type().createController());
this.unit.controller(this.unit.type.createController());
}
this.unit = unit;
if(unit != Nulls.unit){

View File

@@ -2,9 +2,9 @@ package mindustry.entities.comp;
import arc.math.geom.*;
import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.world.*;
import mindustry.world.blocks.environment.*;
@@ -32,11 +32,11 @@ abstract class PosComp implements Position{
}
int tileX(){
return Vars.world.toTile(x);
return World.toTile(x);
}
int tileY(){
return Vars.world.toTile(y);
return World.toTile(y);
}
/** Returns air if this unit is on a non-air top block. */

View File

@@ -74,7 +74,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
unit.apply(liquid.effect, 60 * 2);
if(unit.vel.len() > 0.1){
Fx.ripple.at(unit.x, unit.y, unit.type().rippleScale, liquid.color);
Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, liquid.color);
}
}
}
@@ -98,7 +98,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
boolean onLiquid = tile.floor().isLiquid;
float f = Mathf.clamp(amount / (maxLiquid / 1.5f));
float smag = onLiquid ? 0.8f : 0f;
float sscl = 20f;
float sscl = 25f;
Draw.color(tmp.set(liquid.color).shiftValue(-0.05f));
Fill.circle(x + Mathf.sin(Time.time() + seeds * 532, sscl, smag), y + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 8f);

View File

@@ -22,9 +22,9 @@ abstract class ShieldComp implements Healthc, Posc{
@Replace
@Override
public void damage(float amount){
amount /= healthMultiplier;
//apply armor
amount = Math.max(amount - armor, minArmorDamage * amount);
amount /= healthMultiplier;
hitTime = 1f;

View File

@@ -114,13 +114,14 @@ abstract class StatusComp implements Posc, Flyingc{
StatusEntry entry = statuses.get(index++);
entry.time = Math.max(entry.time - Time.delta, 0);
applied.set(entry.effect.id);
if(entry.time <= 0 && !entry.effect.permanent){
if(entry.effect == null || (entry.time <= 0 && !entry.effect.permanent)){
Pools.free(entry);
index --;
statuses.remove(index);
}else{
applied.set(entry.effect.id);
speedMultiplier *= entry.effect.speedMultiplier;
healthMultiplier *= entry.effect.healthMultiplier;
damageMultiplier *= entry.effect.damageMultiplier;

View File

@@ -1,6 +1,7 @@
package mindustry.entities.comp;
import arc.*;
import arc.func.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
@@ -10,6 +11,7 @@ import arc.util.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.entities.abilities.*;
@@ -36,7 +38,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Import int id;
private UnitController controller;
private UnitType type;
UnitType type;
boolean spawnedByCore;
double flag;
@@ -70,6 +72,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation) * type.speed;
}
/** Iterates through this unit and everything it is controlling. */
public void eachGroup(Cons<Unit> cons){
cons.get(self());
controlling().each(cons);
}
@Override
public float range(){
return type.range;
@@ -88,14 +96,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case rotation -> rotation;
case health -> health;
case maxHealth -> maxHealth;
case ammo -> state.rules.unitAmmo ? type.ammoCapacity : ammo;
case ammo -> !state.rules.unitAmmo ? type.ammoCapacity : ammo;
case ammoCapacity -> type.ammoCapacity;
case x -> x;
case y -> y;
case x -> World.conv(x);
case y -> World.conv(y);
case team -> team.id;
case shooting -> isShooting() ? 1 : 0;
case shootX -> aimX();
case shootY -> aimY();
case shootX -> World.conv(aimX());
case shootY -> World.conv(aimY());
case flag -> flag;
case payloadCount -> self() instanceof Payloadc pay ? pay.payloads().size : 0;
default -> 0;
@@ -110,7 +118,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case firstItem -> stack().amount == 0 ? null : item();
case payloadType -> self() instanceof Payloadc pay ?
(pay.payloads().isEmpty() ? null :
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type() :
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type :
pay.payloads().peek() instanceof BuildPayload p2 ? p2.block() : null) : null;
default -> noSensed;
};
@@ -163,22 +171,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void set(UnitType def, UnitController controller){
type(type);
if(this.type != def){
setType(def);
}
controller(controller);
}
@Override
public void type(UnitType type){
if(this.type == type) return;
setStats(type);
}
@Override
public UnitType type(){
return type;
}
/** @return pathfinder path type for calculating costs */
public int pathType(){
return Pathfinder.costGround;
@@ -208,7 +206,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return Units.getCap(team);
}
public void setStats(UnitType type){
public void setType(UnitType type){
this.type = type;
this.maxHealth = type.health;
this.drag = type.drag;
@@ -226,7 +224,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void afterSync(){
//set up type info after reading
setStats(this.type);
setType(this.type);
controller.unit(self());
}
@@ -239,12 +237,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void add(){
team.data().updateCount(type, 1);
//check if over unit cap
if(count() > cap() && !spawnedByCore && !dead){
Call.unitCapDeath(self());
team.data().updateCount(type, -1);
}
}
@Override
@@ -286,7 +286,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
//apply knockback based on spawns
if(team != state.rules.waveTeam && state.rules.waves){
if(team != state.rules.waveTeam && state.hasSpawns()){
float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f;
for(Tile spawn : spawner.getSpawns()){
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){

View File

@@ -95,7 +95,7 @@ public class AIController implements UnitController{
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type().speed));
unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type.speed));
}
protected void updateWeapons(){
@@ -105,7 +105,7 @@ public class AIController implements UnitController{
boolean ret = retarget();
if(ret){
target = findTarget(unit.x, unit.y, unit.range(), unit.type().targetAir, unit.type().targetGround);
target = findTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround);
}
if(invalid(target)){
@@ -119,7 +119,7 @@ public class AIController implements UnitController{
float mountX = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y),
mountY = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y);
if(unit.type().singleTarget){
if(unit.type.singleTarget){
targets[i] = target;
}else{
if(ret){
@@ -160,7 +160,7 @@ public class AIController implements UnitController{
}
protected boolean retarget(){
return timer.get(timerTarget, 30);
return timer.get(timerTarget, 40);
}
protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
@@ -176,7 +176,7 @@ public class AIController implements UnitController{
}
protected void circle(Position target, float circleLength){
circle(target, circleLength, unit.type().speed);
circle(target, circleLength, unit.type.speed);
}
protected void circle(Position target, float circleLength, float speed){