Merge branch 'master' into master

This commit is contained in:
Felix Corvus
2020-09-19 17:01:57 +03:00
committed by GitHub
134 changed files with 15238 additions and 12129 deletions
@@ -77,7 +77,11 @@ public class EntityProcess extends BaseProcessor{
for(Smethod elem : component.methods()){
if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE)) continue;
//get all statements in the method, store them
methodBlocks.put(elem.descString(), elem.tree().getBody().toString());
methodBlocks.put(elem.descString(), elem.tree().getBody().toString()
//replace all self() invocations with this
.replaceAll("this\\.<(.*)>self\\(\\)", "this")
.replaceAll("self\\(\\)", "this")
);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 893 B

-1
View File
@@ -4,6 +4,5 @@
flattenPaths: true,
maxWidth: 4096,
maxHeight: 4096,
minHeight: 2048,
fast: true
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+5
View File
@@ -876,9 +876,11 @@ liquid.water.name = Water
liquid.slag.name = Slag
liquid.oil.name = Oil
liquid.cryofluid.name = Cryofluid
item.explosiveness = [lightgray]Explosiveness: {0}%
item.flammability = [lightgray]Flammability: {0}%
item.radioactivity = [lightgray]Radioactivity: {0}%
unit.health = [lightgray]Health: {0}
unit.speed = [lightgray]Speed: {0}
unit.weapon = [lightgray]Weapon: {0}
@@ -914,6 +916,8 @@ unit.mega.name = Mega
unit.risso.name = Risso
unit.minke.name = Minke
unit.bryde.name = Bryde
unit.sei.name = Sei
unit.omura.name = Omura
unit.alpha.name = Alpha
unit.beta.name = Beta
unit.gamma.name = Gamma
@@ -979,6 +983,7 @@ block.dune-wall.name = Dune Wall
block.pine.name = Pine
block.dirt.name = Dirt
block.dirt-wall.name = Dirt Wall
block.mud.name = Mud
block.white-tree-dead.name = White Tree Dead
block.white-tree.name = White Tree
block.spore-cluster.name = Spore Cluster
+7 -6
View File
@@ -803,7 +803,7 @@ rules.title.unit = 유닛
rules.title.experimental = 실험적인 기능
rules.title.environment = 환경
rules.lighting = 조명
rules.ambientlight = 주변 조명
rules.ambientlight = 자연 조명
rules.solarpowermultiplier = 태양광 발전 배수
content.item.name = 자원
@@ -856,11 +856,12 @@ unit.crawler.name = 크롤러
unit.atrax.name = 아트락스
unit.spiroct.name = 스피록트
unit.arkyid.name = 아키드
unit.flare.name = 화염
unit.horizon.name = 수평선
unit.zenith.name = 천정
unit.antumbra.name = 그림자
unit.eclipse.name = 일식
unit.toxipod.name = 독소포드
unit.flare.name = 플레어
unit.horizon.name = 호라이즌
unit.zenith.name = 제니스
unit.antumbra.name = 안텀브라
unit.eclipse.name = 이클립스
unit.mono.name = 모노
unit.poly.name = 폴리
unit.mega.name = 메가
File diff suppressed because it is too large Load Diff
+1
View File
@@ -91,3 +91,4 @@ GioIacca9
SnakkiZXZ
sk7725
The Slaylord
ThePlayerA
+3
View File
@@ -311,3 +311,6 @@
63433=dacite-wall|block-dacite-wall-medium
63432=dacite-boulder|block-dacite-boulder-medium
63431=large-logic-display|block-large-logic-display-medium
63430=omura|unit-omura-medium
63429=mud|block-mud-medium
63428=sei|unit-sei-medium
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
#define HIGHP
#define NSCALE 180.0 / 2.0
uniform sampler2D u_texture;
uniform sampler2D u_noise;
uniform vec2 u_campos;
uniform vec2 u_resolution;
uniform float u_time;
varying vec2 v_texCoords;
void main(){
vec2 c = v_texCoords.xy;
vec2 coords = vec2(c.x * u_resolution.x + u_campos.x, c.y * u_resolution.y + u_campos.y);
float btime = u_time / 8000000.0;
float noise = sin((texture2D(u_noise, (coords) / NSCALE + vec2(btime) * vec2(-0.9, 0.8)).r + texture2D(u_noise, (coords) / NSCALE + vec2(abs(sin(btime)) * 1.1) * vec2(-0.8, -1.0)).r) / 2.0);
vec4 color = texture2D(u_texture, c);
if(noise > 0.54 && noise < 0.68){
color.rgb *= 1.4;
}else if(!(noise > 0.40 && noise < 0.54)){
color.rgb *= 1.2;
}
gl_FragColor = color;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 B

After

Width:  |  Height:  |  Size: 811 B

File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 KiB

After

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 958 KiB

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 KiB

After

Width:  |  Height:  |  Size: 1013 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 KiB

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 KiB

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

+7 -38
View File
@@ -33,7 +33,7 @@ public class BlockIndexer{
/** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */
private GridBits[] structQuadrants;
/** Stores all damaged tile entities by team. */
private BuildingArray[] damagedTiles = new BuildingArray[Team.all.length];
private ObjectSet<Building>[] damagedTiles = new ObjectSet[Team.all.length];
/** All ores available on this map. */
private ObjectSet<Item> allOres = new ObjectSet<>();
/** Stores teams that are present here as tiles. */
@@ -70,7 +70,7 @@ public class BlockIndexer{
Events.on(WorldLoadEvent.class, event -> {
scanOres.clear();
scanOres.addAll(Item.getAllOres());
damagedTiles = new BuildingArray[Team.all.length];
damagedTiles = new ObjectSet[Team.all.length];
flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
unitCaps = new int[Team.all.length];
activeTeams = new Seq<>(Team.class);
@@ -139,14 +139,14 @@ public class BlockIndexer{
}
/** Returns all damaged tiles by team. */
public BuildingArray getDamaged(Team team){
returnArray.clear();
public ObjectSet<Building> getDamaged(Team team){
breturnArray.clear();
if(damagedTiles[team.id] == null){
damagedTiles[team.id] = new BuildingArray();
damagedTiles[team.id] = new ObjectSet<>();
}
BuildingArray set = damagedTiles[team.id];
ObjectSet<Building> set = damagedTiles[team.id];
for(Building build : set){
if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){
breturnArray.add(build);
@@ -214,7 +214,7 @@ public class BlockIndexer{
public void notifyTileDamaged(Building entity){
if(damagedTiles[entity.team.id] == null){
damagedTiles[entity.team.id] = new BuildingArray();
damagedTiles[entity.team.id] = new ObjectSet<Building>();
}
damagedTiles[entity.team.id].add(entity);
@@ -476,35 +476,4 @@ public class BlockIndexer{
return tiles.iterator();
}
}
//TODO copy-pasted code, generics would be nice here
public static class BuildingArray implements Iterable<Building>{
private Seq<Building> tiles = new Seq<>(false, 16);
private IntSet contained = new IntSet();
public void add(Building tile){
if(contained.add(tile.pos())){
tiles.add(tile);
}
}
public void remove(Building tile){
if(contained.remove(tile.pos())){
tiles.remove(tile);
}
}
public int size(){
return tiles.size;
}
public Building first(){
return tiles.first();
}
@Override
public Iterator<Building> iterator(){
return tiles.iterator();
}
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ public class Pathfinder implements Runnable{
Flowfield[][][] cache;
/** tile data, see PathTileStruct */
int[][] tiles;
int[][] tiles = new int[0][0];
/** unordered array of path data for iteration only. DO NOT iterate or access this in the main thread. */
Seq<Flowfield> threadList = new Seq<>(), mainList = new Seq<>();
/** handles task scheduling on the update thread. */
+1 -2
View File
@@ -1,7 +1,6 @@
package mindustry.ai.types;
import arc.math.*;
import arc.util.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.world.meta.*;
@@ -59,7 +58,7 @@ public class FlyingAI extends AIController{
vec.setAngle(Mathf.slerpDelta(unit.vel().angle(), vec.angle(), 0.6f));
}
vec.setLength(unit.type().speed * Time.delta);
vec.setLength(unit.type().speed);
unit.moveAt(vec);
}
@@ -58,6 +58,7 @@ public class FormationAI extends AIController implements FormationMember{
public void removed(Unit unit){
if(formation != null){
formation.removeMember(this);
unit.resetController();
}
}
+2 -2
View File
@@ -49,10 +49,10 @@ public class GroundAI extends AIController{
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
}
if(!Units.invalidateTarget(target, unit, unit.range())){
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type().rotateShooting){
if(unit.type().hasWeapons()){
//TODO certain units should not look at the target, e.g. ships
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
unit.lookAt(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
}
}else if(unit.moving()){
unit.lookAt(unit.vel().angle());
+2 -2
View File
@@ -12,8 +12,8 @@ public class RepairAI extends AIController{
boolean shoot = false;
if(target != null){
if(!target.within(unit, unit.type().range)){
moveTo(target, unit.type().range * 0.9f);
if(!target.within(unit, unit.type().range * 0.8f)){
moveTo(target, unit.type().range * 0.8f);
}else{
unit.aim(target);
shoot = true;
@@ -35,6 +35,7 @@ public class PhysicsProcess implements AsyncProcess{
refs.removeAll(ref -> {
if(!ref.entity.isAdded()){
physics.destroyBody(ref.body);
ref.entity.physref(null);
return true;
}
return false;
+19 -7
View File
@@ -34,7 +34,7 @@ public class Blocks implements ContentList{
public static Block
//environment
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, ice, snow, darksandTaintedWater,
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater,
dacite, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, grass, salt,
metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, basalt, magmarock, hotrock, snowWall, boulder, snowBoulder, saltWall,
@@ -260,6 +260,16 @@ public class Blocks implements ContentList{
dirt = new Floor("dirt");
mud = new Floor("mud"){{
speedMultiplier = 0.6f;
variants = 3;
status = StatusEffects.muddy;
statusDuration = 30f;
attributes.set(Attribute.water, 2f);
cacheLayer = CacheLayer.mud;
albedo = 0.35f;
}};
((ShallowLiquid)darksandTaintedWater).set(Blocks.taintedWater, Blocks.darksand);
((ShallowLiquid)sandWater).set(Blocks.water, Blocks.sand);
((ShallowLiquid)darksandWater).set(Blocks.water, Blocks.darksand);
@@ -327,7 +337,7 @@ public class Blocks implements ContentList{
duneWall = new StaticWall("dune-wall"){{
variants = 2;
basalt.asFloor().wall = this;
basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this;
}};
sandWall = new StaticWall("sand-wall"){{
@@ -1011,7 +1021,7 @@ public class Blocks implements ContentList{
mechanicalPump = new Pump("mechanical-pump"){{
requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10));
pumpAmount = 0.1f;
pumpAmount = 0.11f;
}};
rotaryPump = new Pump("rotary-pump"){{
@@ -1136,7 +1146,7 @@ public class Blocks implements ContentList{
requirements(Category.power, with(Items.copper, 35, Items.graphite, 25, Items.lead, 40, Items.silicon, 30));
powerProduction = 5.5f;
itemDuration = 90f;
consumes.liquid(Liquids.water, 0.06f);
consumes.liquid(Liquids.water, 0.07f);
hasLiquids = true;
size = 2;
}};
@@ -1269,7 +1279,7 @@ public class Blocks implements ContentList{
hasItems = true;
consumes.power(0.80f);
consumes.liquid(Liquids.water, 0.18f);
consumes.liquid(Liquids.water, 0.2f);
}};
oilExtractor = new Fracker("oil-extractor"){{
@@ -1645,7 +1655,7 @@ public class Blocks implements ContentList{
}};
spectre = new ItemTurret("spectre"){{
requirements(Category.turret, with(Items.copper, 350, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250));
requirements(Category.turret, with(Items.copper, 900, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250));
ammo(
Items.graphite, Bullets.standardDenseBig,
Items.pyratite, Bullets.standardIncendiaryBig,
@@ -1671,7 +1681,7 @@ public class Blocks implements ContentList{
}};
meltdown = new LaserTurret("meltdown"){{
requirements(Category.turret, with(Items.copper, 250, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325));
requirements(Category.turret, with(Items.copper, 1200, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325));
shootEffect = Fx.shootBigSmoke2;
shootCone = 40f;
recoilAmount = 4f;
@@ -1793,6 +1803,7 @@ public class Blocks implements ContentList{
{UnitTypes.zenith, UnitTypes.antumbra},
{UnitTypes.spiroct, UnitTypes.arkyid},
{UnitTypes.fortress, UnitTypes.scepter},
{UnitTypes.bryde, UnitTypes.sei},
};
}};
@@ -1811,6 +1822,7 @@ public class Blocks implements ContentList{
{UnitTypes.antumbra, UnitTypes.eclipse},
{UnitTypes.arkyid, UnitTypes.toxopid},
{UnitTypes.scepter, UnitTypes.reign},
{UnitTypes.sei, UnitTypes.omura}
};
}};
+3 -3
View File
@@ -269,13 +269,13 @@ public class Bullets implements ContentList{
status = StatusEffects.burning;
}};
missileSurge = new MissileBulletType(3.7f, 20){{
missileSurge = new MissileBulletType(3.7f, 18){{
width = 8f;
height = 8f;
shrinkY = 0f;
drag = -0.01f;
splashDamageRadius = 28f;
splashDamage = 35f;
splashDamageRadius = 25f;
splashDamage = 25f;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
lightning = 2;
+67 -3
View File
@@ -686,6 +686,13 @@ public class Fx{
Fill.circle(e.x, e.y, e.fout() * 1f);
}),
muddy = new Effect(80f, e -> {
color(Color.valueOf("432722"));
alpha(Mathf.clamp(e.fin() * 2f));
Fill.circle(e.x, e.y, e.fout() * 1f);
}),
sapped = new Effect(40f, e -> {
color(Pal.sap);
@@ -989,6 +996,53 @@ public class Fx{
}).ground(400f),
railShoot = new Effect(24f, e -> {
e.scaled(10f, b -> {
color(Color.white, Color.lightGray, b.fin());
stroke(b.fout() * 3f + 0.2f);
Lines.circle(b.x, b.y, b.fin() * 50f);
});
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 13f * e.fout(), 85f, e.rotation + 90f * i);
}
}),
railTrail = new Effect(16f, e -> {
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 10f * e.fout(), 24f, e.rotation + 90 + 90f * i);
}
}),
railHit = new Effect(18f, 200f, e -> {
if(true){
color(Pal.orangeSpark);
for(int i : Mathf.signs){
Drawf.tri(e.x, e.y, 10f * e.fout(), 60f, e.rotation + 140f * i);
}
}else{
e.scaled(7f, b -> {
color(Color.white, Color.lightGray, b.fin());
stroke(b.fout() * 2f + 0.2f);
Lines.circle(b.x, b.y, b.fin() * 28f);
});
color(Pal.orangeSpark);
float rot = e.rotation + Mathf.randomSeedRange(e.id, 20f);
float w = 9f * e.fout();
Drawf.tri(e.x, e.y, w, 100f, rot);
Drawf.tri(e.x, e.y, w, 10f, rot + 180f);
}
}),
lancerLaserShoot = new Effect(21f, e -> {
color(Pal.lancerLaser);
@@ -1000,7 +1054,7 @@ public class Fx{
lancerLaserShootSmoke = new Effect(26f, e -> {
color(Color.white);
float length = e.data == null ? 70f : (Float)e.data;
float length = e.data == null || !(e.data instanceof Float) ? 70f : (Float)e.data;
randLenVectors(e.id, 7, length, e.rotation, 0f, (x, y) -> {
lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fout() * 9f);
@@ -1070,6 +1124,15 @@ public class Fx{
});
}),
cloudsmoke = new Effect(70, e -> {
randLenVectors(e.id, 12, 15f + e.fin() * 45f, (x, y) -> {
float size = e.fslope() * 2f;
color(Color.gray);
alpha(e.fslope());
Fill.circle(e.x + x, e.y + y, size);
});
}),
nuclearcloud = new Effect(90, 200f, e -> {
randLenVectors(e.id, 10, e.finpow() * 90f, (x, y) -> {
float size = e.fout() * 14f;
@@ -1295,10 +1358,11 @@ public class Fx{
}),
//TODO fix false in constructor
ripple = new Effect(30, e -> {
e.lifetime = 30f*e.rotation;
color(Tmp.c1.set(e.color).mul(1.5f));
stroke(e.fout() + 0.4f);
stroke(e.fout() * 1.4f);
Lines.circle(e.x, e.y, (2f + e.fin() * 4f) * e.rotation);
}).ground(),
@@ -9,7 +9,7 @@ import mindustry.type.StatusEffect;
import static mindustry.Vars.*;
public class StatusEffects implements ContentList{
public static StatusEffect none, burning, freezing, wet, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
public static StatusEffect none, burning, freezing, wet, muddy, melting, sapped, tarred, overdrive, overclock, shielded, shocked, blasted, corroded, boss, sporeSlowed;
@Override
public void load(){
@@ -62,6 +62,13 @@ public class StatusEffects implements ContentList{
opposite(burning);
});
}};
muddy = new StatusEffect("muddy"){{
color = Color.valueOf("46382a");
speedMultiplier = 0.94f;
effect = Fx.muddy;
effectChance = 0.09f;
}};
melting = new StatusEffect("melting"){{
speedMultiplier = 0.8f;
+157 -8
View File
@@ -41,8 +41,8 @@ public class UnitTypes implements ContentList{
//air + building + mining
public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma;
//water
public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risso, minke, bryde;
//water + commander
public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risso, minke, bryde, sei, omura;
//special block unit type
public static @EntityDef({Unitc.class, BlockUnitc.class}) UnitType block;
@@ -61,6 +61,7 @@ public class UnitTypes implements ContentList{
reload = 14f;
x = 4f;
y = 2f;
top = false;
ejectEffect = Fx.shellEjectSmall;
bullet = Bullets.standardCopper;
}});
@@ -75,6 +76,7 @@ public class UnitTypes implements ContentList{
immunities.add(StatusEffects.burning);
weapons.add(new Weapon("flamethrower"){{
top = false;
shootSound = Sounds.flame;
shootY = 2f;
reload = 14f;
@@ -106,6 +108,7 @@ public class UnitTypes implements ContentList{
mechFrontSway = 0.55f;
weapons.add(new Weapon("artillery"){{
top = false;
y = 1f;
x = 9f;
reload = 60f;
@@ -142,6 +145,7 @@ public class UnitTypes implements ContentList{
weapons.add(
new Weapon("scepter-weapon"){{
top = false;
y = 1f;
x = 16f;
shootY = 8f;
@@ -201,6 +205,7 @@ public class UnitTypes implements ContentList{
weapons.add(
new Weapon("reign-weapon"){{
top = false;
y = 1f;
x = 21.5f;
shootY = 11f;
@@ -259,6 +264,7 @@ public class UnitTypes implements ContentList{
abilities.add(new HealFieldAbility(10f, 60f * 4, 60f));
weapons.add(new Weapon("heal-weapon"){{
top = false;
shootY = 2f;
reload = 24f;
x = 4.5f;
@@ -274,7 +280,7 @@ public class UnitTypes implements ContentList{
itemCapacity = 60;
canBoost = true;
boostMultiplier = 1.5f;
speed = 0.48f;
speed = 0.62f;
hitsize = 10f;
health = 320f;
buildSpeed = 0.9f;
@@ -287,6 +293,7 @@ public class UnitTypes implements ContentList{
abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 5, 60f));
weapons.add(new Weapon("heal-shotgun-weapon"){{
top = false;
x = 5f;
shake = 2.2f;
y = 0.5f;
@@ -336,6 +343,7 @@ public class UnitTypes implements ContentList{
abilities.add(new ForceFieldAbility(60f, 0.3f, 400f, 60f * 6));
weapons.add(new Weapon("beam-weapon"){{
top = false;
shake = 2f;
shootY = 4f;
x = 6.5f;
@@ -406,6 +414,7 @@ public class UnitTypes implements ContentList{
groundLayer = Layer.legUnit - 1f;
weapons.add(new Weapon("eruption"){{
top = false;
shootY = 3f;
reload = 10f;
ejectEffect = Fx.none;
@@ -668,8 +677,8 @@ public class UnitTypes implements ContentList{
width = height = 25f;
collidesTiles = collides = true;
ammoMultiplier = 4f;
splashDamageRadius = 95f;
splashDamage = 90f;
splashDamageRadius = 90f;
splashDamage = 75f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 5;
@@ -690,7 +699,7 @@ public class UnitTypes implements ContentList{
width = height = 20f;
collidesTiles = false;
splashDamageRadius = 80f;
splashDamage = 45f;
splashDamage = 40f;
backColor = Pal.sapBulletBack;
frontColor = lightningColor = Pal.sapBullet;
lightning = 2;
@@ -1125,6 +1134,7 @@ public class UnitTypes implements ContentList{
accel = 0.3f;
rotateSpeed = 2.6f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 20;
trailX = 5.5f;
@@ -1164,7 +1174,7 @@ public class UnitTypes implements ContentList{
accel = 0.2f;
rotateSpeed = 1.8f;
drag = 0.17f;
hitsize = 14f;
hitsize = 16f;
armor = 6f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
@@ -1186,7 +1196,7 @@ public class UnitTypes implements ContentList{
shootY = 7f;
shake = 5f;
recoil = 4f;
occlusion = 17f;
occlusion = 12f;
shots = 1;
inaccuracy = 3f;
@@ -1252,6 +1262,142 @@ public class UnitTypes implements ContentList{
}});
}};
sei = new UnitType("sei"){{
health = 10000;
armor = 12f;
speed = 0.73f;
drag = 0.17f;
hitsize = 39f;
accel = 0.2f;
rotateSpeed = 1.3f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
trailLength = 50;
trailX = 18f;
trailY = -21f;
trailScl = 3f;
weapons.add(new Weapon("sei-launcher"){{
x = 0f;
y = 0f;
rotate = true;
rotateSpeed = 4f;
mirror = false;
occlusion = 20f;
shootY = 2f;
recoil = 4f;
reload = 45f;
shots = 6;
spacing = 10f;
velocityRnd = 0.4f;
inaccuracy = 7f;
ejectEffect = Fx.none;
shake = 3f;
shootSound = Sounds.shootBig;
xRand = 8f;
shotDelay = 1f;
bullet = new MissileBulletType(4.2f, 25){{
homingPower = 0.12f;
width = 8f;
height = 8f;
shrinkX = shrinkY = 0f;
drag = -0.003f;
homingRange = 80f;
keepVelocity = false;
splashDamageRadius = 25f;
splashDamage = 25f;
lifetime = 56f;
trailColor = Pal.bulletYellowBack;
backColor = Pal.bulletYellowBack;
frontColor = Pal.bulletYellow;
hitEffect = Fx.blastExplosion;
despawnEffect = Fx.blastExplosion;
weaveScale = 8f;
weaveMag = 2f;
}};
}});
weapons.add(new Weapon("large-bullet-mount"){{
reload = 80f;
cooldownTime = 90f;
x = 70f/4f;
y = -66f/4f;
rotateSpeed = 4f;
rotate = true;
shootY = 7f;
shake = 2f;
recoil = 3f;
occlusion = 12f;
ejectEffect = Fx.shellEjectBig;
shots = 3;
shotDelay = 4f;
inaccuracy = 1f;
bullet = new BasicBulletType(7f, 50){{
width = 13f;
height = 19f;
shootEffect = Fx.shootBig;
lifetime = 30f;
}};
}});
}};
omura = new UnitType("omura"){{
health = 22000;
speed = 0.62f;
drag = 0.18f;
hitsize = 50f;
armor = 16f;
accel = 0.19f;
rotateSpeed = 0.9f;
immunities = ObjectSet.with(StatusEffects.wet);
rotateShooting = false;
float spawnTime = 60f * 25f;
abilities.add(new UnitSpawnAbility(flare, spawnTime, 19.25f, -31.75f), new UnitSpawnAbility(flare, spawnTime, -19.25f, -31.75f));
trailLength = 70;
trailX = 23f;
trailY = -32f;
trailScl = 3.5f;
weapons.add(new Weapon("omura-cannon"){{
reload = 110f;
cooldownTime = 90f;
mirror = false;
x = 0f;
y = -3.5f;
rotateSpeed = 1.4f;
rotate = true;
shootY = 23f;
shake = 6f;
recoil = 10.5f;
occlusion = 50f;
shots = 1;
ejectEffect = Fx.none;
bullet = new RailBulletType(){{
shootEffect = Fx.railShoot;
speed = 67f;
lifetime = 8f;
pierceEffect = Fx.railHit;
updateEffect = Fx.railTrail;
hitEffect = Fx.massiveExplosion;
smokeEffect = Fx.shootBig2;
damage = 1250;
pierceDamageFactor = 0.5f;
}};
}});
}};
//endregion
//region core
@@ -1276,6 +1422,7 @@ public class UnitTypes implements ContentList{
reload = 17f;
x = 2.75f;
y = 1f;
top = false;
bullet = new BasicBulletType(2.5f, 9){{
width = 7f;
@@ -1308,6 +1455,7 @@ public class UnitTypes implements ContentList{
lowAltitude = true;
weapons.add(new Weapon("small-mount-weapon"){{
top = false;
reload = 20f;
x = 3f;
y = 0.5f;
@@ -1345,6 +1493,7 @@ public class UnitTypes implements ContentList{
hitsize = 10f;
weapons.add(new Weapon("small-mount-weapon"){{
top = false;
reload = 15f;
x = 1f;
y = 2f;
+5
View File
@@ -191,6 +191,10 @@ public class Control implements ApplicationListener, Loadable{
}
void resetCamera(){
}
@Override
public void loadAsync(){
Draw.scl = 1f / Core.atlas.find("scale_marker").width;
@@ -280,6 +284,7 @@ public class Control implements ApplicationListener, Loadable{
try{
net.reset();
slot.load();
slot.setAutosave(true);
state.rules.sector = sector;
//if there is no base, simulate a new game and place the right loadout at the spawn position
+1 -1
View File
@@ -17,7 +17,7 @@ public class GameState{
/** Wave countdown in ticks. */
public float wavetime;
/** Whether the game is in game over state. */
public boolean gameOver = false, launched = false, serverPaused = false;
public boolean gameOver = false, launched = false, serverPaused = false, wasTimeout;
/** Map that is currently being played on. */
public @NonNull Map map = emptyMap;
/** The current game rules. */
+8 -1
View File
@@ -337,7 +337,14 @@ public class Logic implements ApplicationListener{
//force pausing when the player is out of sector time
if(state.isOutOfTime()){
state.set(State.paused);
if(!state.wasTimeout){
universe.displayTimeEnd();
state.wasTimeout = true;
}
//if no turn was run.
if(state.isOutOfTime()){
state.set(State.paused);
}
}
if(!state.isPaused()){
+4
View File
@@ -549,6 +549,10 @@ public class NetClient implements ApplicationListener{
quiet = true;
}
public void clearRemovedEntity(int id){
removed.remove(id);
}
public void addRemovedEntity(int id){
removed.add(id);
}
+26 -26
View File
@@ -593,38 +593,38 @@ public class NetServer implements ApplicationListener{
if(player.isBuilder()){
player.builder().clearBuilding();
player.builder().updateBuilding(building);
if(requests != null){
for(BuildPlan req : requests){
if(req == null) continue;
Tile tile = world.tile(req.x, req.y);
if(tile == null || (!req.breaking && req.block == null)) continue;
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
action.block = req.block;
action.rotation = req.rotation;
action.config = req.config;
})){
//force the player to remove this request if that's not the case
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
con.rejectedRequests.add(req);
continue;
}
player.builder().plans().addLast(req);
}
}
}
if(player.isMiner()){
player.miner().mineTile(mining);
}
if(requests != null){
for(BuildPlan req : requests){
if(req == null) continue;
Tile tile = world.tile(req.x, req.y);
if(tile == null || (!req.breaking && req.block == null)) continue;
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
action.block = req.block;
action.rotation = req.rotation;
action.config = req.config;
})){
//force the player to remove this request if that's not the case
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
con.rejectedRequests.add(req);
continue;
}
player.builder().plans().addLast(req);
}
}
con.rejectedRequests.clear();
if(!player.dead()){
+79 -4
View File
@@ -5,11 +5,13 @@ import arc.func.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.struct.ObjectIntMap.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import arc.util.noise.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
import mindustry.ctype.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
@@ -19,7 +21,6 @@ import mindustry.maps.*;
import mindustry.maps.filters.*;
import mindustry.maps.filters.GenerateFilter.*;
import mindustry.type.*;
import mindustry.type.Sector.*;
import mindustry.type.Weather.*;
import mindustry.world.*;
import mindustry.world.blocks.environment.*;
@@ -33,11 +34,17 @@ public class World{
public @NonNull Tiles tiles = new Tiles(0, 0);
private boolean generating, invalidMap;
private ObjectMap<Map, Runnable> customMapLoaders = new ObjectMap<>();
public World(){
}
/** Adds a custom handler function for loading a custom map - usually a generated one. */
public void addMapLoader(Map map, Runnable loader){
customMapLoaders.put(map, loader);
}
public boolean isInvalidMap(){
return invalidMap;
}
@@ -255,9 +262,71 @@ public class World{
state.rules.weather.clear();
if(sector.is(SectorAttribute.rainy)) state.rules.weather.add(new WeatherEntry(Weathers.rain));
if(sector.is(SectorAttribute.snowy)) state.rules.weather.add(new WeatherEntry(Weathers.snow));
if(sector.is(SectorAttribute.desert)) state.rules.weather.add(new WeatherEntry(Weathers.sandstorm));
//apply weather based on terrain
ObjectIntMap<Block> floorc = new ObjectIntMap<>();
ObjectSet<UnlockableContent> content = new ObjectSet<>();
float waterFloors = 0, totalFloors = 0;
for(Tile tile : world.tiles){
if(world.getDarkness(tile.x, tile.y) >= 3){
continue;
}
Liquid liquid = tile.floor().liquidDrop;
if(tile.floor().itemDrop != null) content.add(tile.floor().itemDrop);
if(tile.overlay().itemDrop != null) content.add(tile.overlay().itemDrop);
if(liquid != null) content.add(liquid);
if(!tile.block().isStatic()){
totalFloors ++;
if(liquid == Liquids.water){
waterFloors += tile.floor().isDeep() ? 1f : 0.7f;
}
floorc.increment(tile.floor());
if(tile.overlay() != Blocks.air){
floorc.increment(tile.overlay());
}
}
}
//sort counts in descending order
Seq<Entry<Block>> entries = floorc.entries().toArray();
entries.sort(e -> -e.value);
//remove all blocks occuring < 30 times - unimportant
entries.removeAll(e -> e.value < 30);
Block[] floors = new Block[entries.size];
int[] floorCounts = new int[entries.size];
for(int i = 0; i < entries.size; i++){
floorCounts[i] = entries.get(i).value;
floors[i] = entries.get(i).key;
}
//TODO bad code
boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow");
boolean hasRain = !hasSnow && floors[0].name.contains("water");
boolean hasDesert = !hasSnow && !hasRain && floors[0].name.contains("sand");
boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted");
if(hasSnow){
state.rules.weather.add(new WeatherEntry(Weathers.snow));
}
if(hasRain){
state.rules.weather.add(new WeatherEntry(Weathers.rain));
}
if(hasDesert){
state.rules.weather.add(new WeatherEntry(Weathers.sandstorm));
}
if(hasSpores){
state.rules.weather.add(new WeatherEntry(Weathers.sporestorm));
}
state.secinfo.resources = content.asArray();
state.secinfo.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));
}
@@ -270,6 +339,12 @@ public class World{
}
public void loadMap(Map map, Rules checkRules){
//load using custom loader if possible
if(customMapLoaders.containsKey(map)){
customMapLoaders.get(map).run();
return;
}
try{
SaveIO.load(map.file, new FilterContext(map));
}catch(Throwable e){
+17 -8
View File
@@ -20,7 +20,7 @@ public class EditorTile extends Tile{
@Override
public void setFloor(@NonNull Floor type){
if(state.isGame()){
if(skip()){
super.setFloor(type);
return;
}
@@ -41,20 +41,25 @@ public class EditorTile extends Tile{
@Override
public void setBlock(Block type, Team team, int rotation){
if(state.isGame()){
if(skip()){
super.setBlock(type, team, rotation);
return;
}
op(OpType.block, block.id);
//if(this.block == type && (build == null || build.rotation == rotation)){
// ui.editor.editor.renderer().updatePoint(x, y);
// return;
//}
if(rotation != 0) op(OpType.rotation, (byte)rotation);
if(team() != Team.derelict) op(OpType.team, (byte)team().id);
op(OpType.block, block.id);
super.setBlock(type, team, rotation);
}
@Override
public void setTeam(Team team){
if(state.isGame()){
if(skip()){
super.setTeam(team);
return;
}
@@ -66,7 +71,7 @@ public class EditorTile extends Tile{
@Override
public void setOverlay(Block overlay){
if(state.isGame()){
if(skip()){
super.setOverlay(overlay);
return;
}
@@ -79,7 +84,7 @@ public class EditorTile extends Tile{
@Override
protected void fireChanged(){
if(state.isGame()){
if(skip()){
super.fireChanged();
}else{
ui.editor.editor.renderer().updatePoint(x, y);
@@ -88,14 +93,14 @@ public class EditorTile extends Tile{
@Override
public void recache(){
if(state.isGame()){
if(skip()){
super.recache();
}
}
@Override
protected void changeEntity(Team team, Prov<Building> entityprov, int rotation){
if(state.isGame()){
if(skip()){
super.changeEntity(team, entityprov, rotation);
return;
}
@@ -116,6 +121,10 @@ public class EditorTile extends Tile{
}
}
private boolean skip(){
return state.isGame() || ui.editor.editor.isLoading();
}
private void op(OpType type, short value){
ui.editor.editor.addTileOp(TileOp.get(x, y, (byte)type.ordinal(), value));
}
+1 -1
View File
@@ -17,7 +17,7 @@ public enum EditorTool{
if(!Structs.inBounds(x, y, editor.width(), editor.height())) return;
Tile tile = editor.tile(x, y);
editor.drawBlock = tile.block() == Blocks.air ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
editor.drawBlock = tile.block() == Blocks.air || !tile.block().inEditor ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
}
},
line(KeyCode.l, "replace", "orthogonal"){
+13 -3
View File
@@ -31,6 +31,10 @@ public class MapEditor{
public Block drawBlock = Blocks.stone;
public Team drawTeam = Team.sharded;
public boolean isLoading(){
return loading;
}
public StringMap getTags(){
return tags;
}
@@ -52,7 +56,7 @@ public class MapEditor{
if(map.file.parent().parent().name().equals("1127400") && steam){
tags.put("steamid", map.file.parent().name());
}
MapIO.loadMap(map, context);
load(() -> MapIO.loadMap(map, context));
renderer.resize(width(), height());
loading = false;
}
@@ -227,8 +231,14 @@ public class MapEditor{
int px = offsetX + x, py = offsetY + y;
if(previous.in(px, py)){
tiles.set(x, y, previous.getn(px, py));
tiles.getn(x, y).x = (short)x;
tiles.getn(x, y).y = (short)y;
Tile tile = tiles.getn(x, y);
tile.x = (short)x;
tile.y = (short)y;
if(tile.build != null && tile.isCenter()){
tile.build.x = x * tilesize + tile.block().offset;
tile.build.y = y * tilesize + tile.block().offset;
}
}else{
tiles.set(x, y, new EditorTile(x, y, Blocks.stone.id, (short)0, (short)0));
}
+1 -1
View File
@@ -116,7 +116,7 @@ public class MapRenderer implements Disposable{
wx * tilesize + wall.offset + (tilesize - width) / 2f,
wy * tilesize + wall.offset + (tilesize - height) / 2f,
width, height,
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg() - 90);
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg());
}else{
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
+9 -7
View File
@@ -86,12 +86,14 @@ public class Effect{
create(this, x, y, rotation, Color.white, data);
}
public void render(int id, Color color, float life, float rotation, float x, float y, Object data){
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.reset();
renderer.get(container);
Draw.reset();
return container.lifetime;
}
public static @Nullable Effect get(int id){
@@ -125,13 +127,13 @@ public class Effect{
if(view.overlaps(pos)){
EffectState entity = EffectState.create();
entity.effect(effect);
entity.rotation(rotation);
entity.data(data);
entity.lifetime(effect.lifetime);
entity.effect = effect;
entity.rotation = rotation;
entity.data = (data);
entity.lifetime = (effect.lifetime);
entity.set(x, y);
entity.color().set(color);
if(data instanceof Posc) entity.parent((Posc)data);
entity.color.set(color);
if(data instanceof Posc) entity.parent = ((Posc)data);
entity.add();
}
}
@@ -2,7 +2,16 @@ package mindustry.entities.abilities;
import mindustry.gen.*;
public interface Ability{
default void update(Unit unit){}
default void draw(Unit unit){}
public abstract class Ability implements Cloneable{
public void update(Unit unit){}
public void draw(Unit unit){}
public Ability copy(){
try{
return (Ability)clone();
}catch(CloneNotSupportedException e){
//I am disgusted
throw new RuntimeException("java sucks", e);
}
}
}
@@ -11,7 +11,7 @@ import mindustry.content.*;
import mindustry.gen.*;
import mindustry.graphics.*;
public class ForceFieldAbility implements Ability{
public class ForceFieldAbility extends Ability{
/** Shield radius. */
public float radius = 60f;
/** Shield regen speed in damage/tick. */
@@ -21,18 +21,22 @@ public class ForceFieldAbility implements Ability{
/** Cooldown after the shield is broken, in ticks. */
public float cooldown = 60f * 5;
private float realRad;
private Unit paramUnit;
private final Cons<Shielderc> shieldConsumer = trait -> {
/** State: radius scaling. */
protected float radiusScale;
private static float realRad;
private static Unit paramUnit;
private static ForceFieldAbility paramField;
private static final Cons<Shielderc> shieldConsumer = trait -> {
if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){
trait.absorb();
Fx.absorb.at(trait);
//break shield
if(paramUnit.shield <= trait.damage()){
paramUnit.shield -= cooldown * regen;
paramUnit.shield -= paramField.cooldown * paramField.regen;
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color);
Fx.shieldBreak.at(paramUnit.x, paramUnit.y, paramField.radius, paramUnit.team.color);
}
paramUnit.shield -= trait.damage();
@@ -56,13 +60,14 @@ public class ForceFieldAbility implements Ability{
}
if(unit.shield > 0){
unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f);
radiusScale = Mathf.lerpDelta(radiusScale, 1f, 0.06f);
paramUnit = unit;
paramField = this;
checkRadius(unit);
Groups.bullet.intersect(unit.x - realRad, unit.y - realRad, realRad * 2f, realRad * 2f, shieldConsumer);
}else{
unit.timer2 = 0f;
radiusScale = 0f;
}
}
@@ -89,6 +94,6 @@ public class ForceFieldAbility implements Ability{
private void checkRadius(Unit unit){
//timer2 is used to store radius scale as an effect
realRad = unit.timer2 * radius;
realRad = radiusScale * radius;
}
}
@@ -5,12 +5,13 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class HealFieldAbility implements Ability{
public class HealFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWave;
private boolean wasHealed = false;
protected float timer;
protected boolean wasHealed = false;
HealFieldAbility(){}
@@ -22,9 +23,9 @@ public class HealFieldAbility implements Ability{
@Override
public void update(Unit unit){
unit.timer1 += Time.delta;
timer += Time.delta;
if(unit.timer1 >= reload){
if(timer >= reload){
wasHealed = false;
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
@@ -39,7 +40,7 @@ public class HealFieldAbility implements Ability{
activeEffect.at(unit);
}
unit.timer1 = 0f;
timer = 0f;
}
}
}
@@ -5,12 +5,13 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class ShieldFieldAbility implements Ability{
public class ShieldFieldAbility extends Ability{
public float amount = 1, max = 100f, reload = 100, range = 60;
public Effect applyEffect = Fx.shieldApply;
public Effect activeEffect = Fx.shieldWave;
private boolean applied = false;
protected float timer;
protected boolean applied = false;
ShieldFieldAbility(){}
@@ -23,9 +24,9 @@ public class ShieldFieldAbility implements Ability{
@Override
public void update(Unit unit){
unit.timer1 += Time.delta;
timer += Time.delta;
if(unit.timer1 >= reload){
if(timer >= reload){
applied = false;
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
@@ -41,7 +42,7 @@ public class ShieldFieldAbility implements Ability{
activeEffect.at(unit);
}
unit.timer1 = 0f;
timer = 0f;
}
}
}
@@ -7,12 +7,14 @@ import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
public class StatusFieldAbility implements Ability{
public class StatusFieldAbility extends Ability{
public @NonNull StatusEffect effect;
public float duration = 60, reload = 100, range = 20;
public Effect applyEffect = Fx.heal;
public Effect activeEffect = Fx.overdriveWave;
protected float timer;
StatusFieldAbility(){}
public StatusFieldAbility(@NonNull StatusEffect effect, float duration, float reload, float range){
@@ -24,9 +26,9 @@ public class StatusFieldAbility implements Ability{
@Override
public void update(Unit unit){
unit.timer2 += Time.delta;
timer += Time.delta;
if(unit.timer2 >= reload){
if(timer >= reload){
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
other.apply(effect, duration);
@@ -34,7 +36,7 @@ public class StatusFieldAbility implements Ability{
activeEffect.at(unit);
unit.timer2 = 0f;
timer = 0f;
}
}
}
@@ -0,0 +1,60 @@
package mindustry.entities.abilities;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
public class UnitSpawnAbility extends Ability{
public @NonNull UnitType type;
public float spawnTime = 60f, spawnX, spawnY;
public Effect spawnEffect = Fx.spawn;
protected float timer;
public UnitSpawnAbility(@NonNull UnitType type, float spawnTime, float spawnX, float spawnY){
this.type = type;
this.spawnTime = spawnTime;
this.spawnX = spawnX;
this.spawnY = spawnY;
}
public UnitSpawnAbility(){
}
@Override
public void update(Unit unit){
timer += Time.delta;
if(timer >= spawnTime && Units.canCreate(unit.team, type)){
float x = unit.x + Angles.trnsx(unit.rotation, spawnY, spawnX), y = unit.y + Angles.trnsy(unit.rotation, spawnY, spawnX);
spawnEffect.at(x, y);
Unit u = type.create(unit.team);
u.set(x, y);
u.rotation = unit.rotation;
if(!Vars.net.client()){
u.add();
}
timer = 0f;
}
}
@Override
public void draw(Unit unit){
if(Units.canCreate(unit.team, type)){
Draw.draw(Draw.z(), () -> {
float x = unit.x + Angles.trnsx(unit.rotation, spawnY, spawnX), y = unit.y + Angles.trnsy(unit.rotation, spawnY, spawnX);
Drawf.construct(x, y, type.icon(Cicon.full), unit.rotation - 90, timer / spawnTime, 1f, timer);
});
}
}
}
@@ -24,7 +24,7 @@ public abstract class BulletType extends Content{
public float hitSize = 4;
public float drawSize = 40f;
public float drag = 0f;
public boolean pierce;
public boolean pierce, pierceBuilding;
public Effect hitEffect, despawnEffect;
/** Effect created when shooting. */
@@ -69,6 +69,8 @@ public abstract class BulletType extends Content{
public boolean scaleVelocity;
/** Whether this bullet can be hit by point defense. */
public boolean hittable = true;
/** Whether this bullet can be reflected. */
public boolean reflectable = true;
//additional effects
@@ -131,10 +133,14 @@ public abstract class BulletType extends Content{
return true;
}
public void hitTile(Bullet b, Building tile){
public void hitTile(Bullet b, Building tile, float initialHealth){
hit(b);
}
public void hitEntity(Bullet b, Hitboxc other, float initialHealth){
}
public void hit(Bullet b){
hit(b, b.x, b.y);
}
@@ -43,7 +43,7 @@ public class HealBulletType extends BulletType{
}
@Override
public void hitTile(Bullet b, Building tile){
public void hitTile(Bullet b, Building tile, float initialHealth){
super.hit(b);
if(tile.team == b.team && !(tile.block instanceof ConstructBlock)){
@@ -0,0 +1,52 @@
package mindustry.entities.bullet;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class RailBulletType extends BulletType{
public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
/** Multiplier of damage decreased per health pierced. */
public float pierceDamageFactor = 1f;
public RailBulletType(){
pierceBuilding = true;
pierce = true;
reflectable = false;
hitEffect = Fx.none;
despawnEffect = Fx.none;
}
void handle(Bullet b, Posc pos, float initialHealth){
float sub = initialHealth*pierceDamageFactor;
if(sub >= b.damage){
//cause a despawn
b.remove();
}
//subtract health from each consecutive pierce
b.damage -= Math.min(b.damage, sub);
if(b.damage > 0){
pierceEffect.at(pos.getX(), pos.getY(), b.rotation());
}
hitEffect.at(pos.getX(), pos.getY());
}
@Override
public void update(Bullet b){
updateEffect.at(b.x, b.y, b.rotation());
}
@Override
public void hitEntity(Bullet b, Hitboxc entity, float initialHealth){
handle(b, entity, initialHealth);
}
@Override
public void hitTile(Bullet b, Building tile, float initialHealth){
handle(b, tile, initialHealth);
}
}
@@ -39,10 +39,15 @@ public class SapBulletType extends BulletType{
Draw.reset();
Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f);
Drawf.light(b.team, b.x, b.y, Tmp.v1.x, Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f);
}
}
@Override
public void drawLight(Bullet b){
}
@Override
public float range(){
return length;
@@ -108,9 +108,9 @@ abstract class BuilderComp implements Unitc{
ConstructBuild entity = tile.bc();
if(current.breaking){
entity.deconstruct(base(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier);
entity.deconstruct(self(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier);
}else{
entity.construct(base(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier, current.config);
entity.construct(self(), core, 1f / entity.buildCost * Time.delta * type().buildSpeed * state.rules.buildSpeedMultiplier, current.config);
}
current.stuck = Mathf.equal(current.progress, entity.progress);
@@ -80,7 +80,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(block.hasPower){
//reinit power graph
power.graph = new PowerGraph();
power.graph.add(base());
power.graph.add(self());
}
}
this.rotation = rotation;
@@ -94,7 +94,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
created();
return base();
return self();
}
/** Sets up all the necessary variables, but does not add this entity anywhere. */
@@ -111,17 +111,17 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
maxHealth(block.health);
timer(new Interval(block.timers));
cons = new ConsumeModule(base());
cons = new ConsumeModule(self());
if(block.hasItems) items = new ItemModule();
if(block.hasLiquids) liquids = new LiquidModule();
if(block.hasPower){
power = new PowerModule();
power.graph.add(base());
power.graph.add(self());
}
initialized = true;
return base();
return self();
}
@Override
@@ -195,17 +195,17 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void configure(Object value){
//save last used config
block.lastConfig = value;
Call.tileConfig(player, base(), value);
Call.tileConfig(player, self(), value);
}
/** Configure from a server. */
public void configureAny(Object value){
Call.tileConfig(null, base(), value);
Call.tileConfig(null, self(), value);
}
/** Deselect this tile from configuration. */
public void deselect(){
if(!headless && control.input.frag.config.getSelectedTile() == base()){
if(!headless && control.input.frag.config.getSelectedTile() == self()){
control.input.frag.config.hideConfig();
}
}
@@ -372,7 +372,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Returns the amount of items this block can accept. */
public int acceptStack(Item item, int amount, Teamc source){
if(acceptItem(base(), item) && block.hasItems && (source == null || source.team() == team)){
if(acceptItem(self(), item) && block.hasItems && (source == null || source.team() == team)){
return Math.min(getMaximumAccepted(item) - items.get(item), amount);
}else{
return 0;
@@ -425,8 +425,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
int trns = block.size/2 + 1;
Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(base(), todump)){
next.build.handlePayload(base(), todump);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(self(), todump)){
next.build.handlePayload(self(), todump);
return true;
}
@@ -446,8 +446,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptPayload(base(), todump)){
other.handlePayload(base(), todump);
if(other.team == team && other.acceptPayload(self(), todump)){
other.handlePayload(self(), todump);
incrementDump(proximity.size);
return true;
}
@@ -480,7 +480,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
other = other.getLiquidDestination(base(), liquid);
other = other.getLiquidDestination(self(), liquid);
if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity;
@@ -499,8 +499,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void transferLiquid(Building next, float amount, Liquid liquid){
float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f, amount);
if(next.acceptLiquid(base(), liquid, flow)){
next.handleLiquid(base(), liquid, flow);
if(next.acceptLiquid(self(), liquid, flow)){
next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow);
}
}
@@ -523,7 +523,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public float moveLiquid(Building next, Liquid liquid){
if(next == null) return 0;
next = next.getLiquidDestination(base(), liquid);
next = next.getLiquidDestination(self(), liquid);
if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
float ofract = next.liquids.get(liquid) / next.block.liquidCapacity;
@@ -531,8 +531,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid));
flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f);
if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){
next.handleLiquid(base(), liquid, flow);
if(flow > 0f && ofract <= fract && next.acceptLiquid(self(), liquid, flow)){
next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow);
return flow;
}else if(next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
@@ -558,7 +558,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public Building getLiquidDestination(Building from, Liquid liquid){
return base();
return self();
}
public @Nullable Payload getPayload(){
@@ -580,13 +580,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
if(other.team == team && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(self(), item);
return;
}
}
handleItem(base(), item);
handleItem(self(), item);
}
/**
@@ -598,8 +598,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size);
Building other = proximity.get((i + dump) % proximity.size);
if(other.team == team && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
if(other.team == team && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(self(), item);
return true;
}
}
@@ -631,16 +631,16 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
for(int ii = 0; ii < content.items().size; ii++){
Item item = content.item(ii);
if(other.team == team && items.has(item) && other.acceptItem(base(), item) && canDump(other, item)){
other.handleItem(base(), item);
if(other.team == team && items.has(item) && other.acceptItem(self(), item) && canDump(other, item)){
other.handleItem(self(), item);
items.remove(item, 1);
incrementDump(proximity.size);
return true;
}
}
}else{
if(other.team == team && other.acceptItem(base(), todump) && canDump(other, todump)){
other.handleItem(base(), todump);
if(other.team == team && other.acceptItem(self(), todump) && canDump(other, todump)){
other.handleItem(self(), todump);
items.remove(todump, 1);
incrementDump(proximity.size);
return true;
@@ -665,8 +665,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
public boolean moveForward(Item item){
Building other = front();
if(other != null && other.team == team && other.acceptItem(base(), item)){
other.handleItem(base(), item);
if(other != null && other.team == team && other.acceptItem(self(), item)){
other.handleItem(self(), item);
return true;
}
return false;
@@ -696,7 +696,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return;
}
power.graph.remove(base());
power.graph.remove(self());
for(int i = 0; i < power.links.size; i++){
Tile other = world.tile(power.links.get(i));
if(other != null && other.build != null && other.build.power != null){
@@ -833,8 +833,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
tempTiles.clear();
Geometry.circle(tileX(), tileY(), range, (x, y) -> {
Building other = world.build(x, y);
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, base()) && !PowerNode.insulated(other, base())
&& !other.proximity().contains(this.<Building>base()) &&
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, self()) && !PowerNode.insulated(other, self())
&& !other.proximity().contains(this.<Building>self()) &&
!(block.outputsPower && proximity.contains(p -> p.power != null && p.power.graph == other.power.graph))){
tempTiles.add(other.tile);
}
@@ -1037,13 +1037,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
table.left();
for(Consume cons : block.consumes.all()){
if(cons.isOptional() && cons.isBoost()) continue;
cons.build(base(), table);
cons.build(self(), table);
}
}
public void displayBars(Table table){
for(Func<Building, Bar> bar : block.bars.list()){
table.add(bar.get(base())).growX();
table.add(bar.get(self())).growX();
table.row();
}
}
@@ -1069,7 +1069,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
* @return whether or not this block should be deselected.
*/
public boolean onConfigureTileTapped(Building other){
return base() != other;
return self() != other;
}
/** Returns whether this config menu should show when the specified player taps it. */
@@ -1128,7 +1128,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
for(Building other : tmpTiles){
other.proximity.remove(base(), true);
other.proximity.remove(self(), true);
other.onProximityUpdate();
}
}
@@ -1144,8 +1144,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(other == null || !(other.tile.interactable(team))) continue;
//add this tile to proximity of nearby tiles
if(!other.proximity.contains(base(), true)){
other.proximity.add(base());
if(!other.proximity.contains(self(), true)){
other.proximity.add(self());
}
tmpTiles.add(other);
@@ -1184,13 +1184,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
@Replace
@Override
public boolean isValid(){
return tile.build == base() && !dead();
return tile.build == self() && !dead();
}
@Replace
@Override
public void kill(){
Call.tileDestroyed(base());
Call.tileDestroyed(self());
}
@Replace
@@ -1204,10 +1204,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
damage /= state.rules.blockHealthMultiplier;
}
Call.tileDamage(base(), health - handleDamage(damage));
Call.tileDamage(self(), health - handleDamage(damage));
if(health <= 0){
Call.tileDestroyed(base());
Call.tileDestroyed(self());
}
}
@@ -1292,7 +1292,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
if(block.idleSound != Sounds.none && shouldIdleSound()){
loops.play(block.idleSound, base(), block.idleSoundVolume);
loops.play(block.idleSound, self(), block.idleSoundVolume);
}
if(enabled || !block.noUpdateDisabled){
@@ -44,17 +44,17 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@Override
public void drawBullets(){
type.draw(base());
type.draw(self());
}
@Override
public void add(){
type.init(base());
type.init(self());
}
@Override
public void remove(){
type.despawned(base());
type.despawned(self());
collided.clear();
}
@@ -92,10 +92,12 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@MethodPriority(100)
@Override
public void collision(Hitboxc other, float x, float y){
type.hit(base(), x, y);
type.hit(self(), x, y);
float health = 0f;
if(other instanceof Healthc){
Healthc h = (Healthc)other;
health = h.health();
h.damage(damage);
}
@@ -111,30 +113,40 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
}else{
collided.add(other.id());
}
type.hitEntity(self(), other, health);
}
@Override
public void update(){
type.update(base());
type.update(self());
if(type.collidesTiles && type.collides && type.collidesGround){
world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
Building tile = world.build(x, y);
if(tile == null) return false;
if(tile == null || !isAdded()) return false;
if(tile.collide(base()) && type.collides(base(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team)){
if(tile.collide(self()) && type.collides(self(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team) && !(type.pierceBuilding && collided.contains(tile.id))){
boolean remove = false;
float health = tile.health;
if(tile.team != team){
remove = tile.collision(base());
remove = tile.collision(self());
}
if(remove || type.collidesTeam){
type.hitTile(base(), tile);
remove();
if(!type.pierceBuilding){
remove();
}else{
collided.add(tile.id);
}
}
return true;
type.hitTile(self(), tile, health);
return !type.pierceBuilding;
}
return false;
@@ -146,8 +158,8 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
public void draw(){
Draw.z(Layer.bullet);
type.draw(base());
type.drawLight(base());
type.draw(self());
type.drawLight(self());
}
/** Sets the bullet's rotation in degrees. */
@@ -59,7 +59,7 @@ abstract class CommanderComp implements Unitc{
units.clear();
Units.nearby(team(), x, y, 200f, u -> {
if(u.isAI() && include.get(u) && u != base()){
if(u.isAI() && include.get(u) && u != self()){
units.add(u);
}
});
@@ -79,7 +79,7 @@ abstract class CommanderComp implements Unitc{
controlling.addAll(units);
for(Unit unit : units){
FormationAI ai;
unit.controller(ai = new FormationAI(base(), formation));
unit.controller(ai = new FormationAI(self(), formation));
spacing = Math.max(spacing, ai.formationSize());
minFormationSpeed = Math.min(minFormationSpeed, unit.type().speed);
}
@@ -104,7 +104,7 @@ abstract class CommanderComp implements Unitc{
void clearCommand(){
//reset controlled units
for(Unit unit : controlling){
if(unit.controller().isBeingControlled(base())){
if(unit.controller().isBeingControlled(self())){
unit.controller(unit.type().createController());
}
}
@@ -8,13 +8,16 @@ import mindustry.gen.*;
@EntityDef(value = {EffectStatec.class, Childc.class}, pooled = true, serialize = false)
@Component(base = true)
abstract class EffectStateComp implements Posc, Drawc, Timedc, Rotc, Childc{
@Import float time, lifetime, rotation, x, y;
@Import int id;
Color color = new Color(Color.white);
Effect effect;
Object data;
@Override
public void draw(){
effect.render(id(), color, time(), rotation(), x(), y(), data);
lifetime = effect.render(id, color, time, lifetime, rotation, x, y, data);
}
@Replace
@@ -40,7 +40,7 @@ abstract class EntityComp{
return false;
}
<T extends Entityc> T base(){
<T extends Entityc> T self(){
return (T)this;
}
@@ -97,11 +97,11 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{
@Override
public void afterRead(){
Fires.register(base());
Fires.register(self());
}
@Override
public void afterSync(){
Fires.register(base());
Fires.register(self());
}
}
@@ -74,7 +74,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
}
if(!hovering && isGrounded() && floor.isLiquid){
if((splashTimer += Mathf.dst(deltaX(), deltaY())) >= 7f){
if((splashTimer += Mathf.dst(deltaX(), deltaY())) >= (7f + hitSize()/8f)){
floor.walkEffect.at(x, y, hitSize() / 8f, floor.mapColor);
splashTimer = 0f;
}
@@ -33,7 +33,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
boolean mining(){
return mineTile != null;
return mineTile != null && !(((Object)this) instanceof Builderc && ((Builderc)(Object)this).activelyBuilding());
}
@Override
@@ -51,13 +51,12 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
if(mineTile == null || core == null || mineTile.block() != Blocks.air || dst(mineTile.worldx(), mineTile.worldy()) > miningRange
|| (((Object)this) instanceof Builderc && ((Builderc)(Object)this).activelyBuilding())
|| mineTile.drop() == null || !canMine(mineTile.drop())){
mineTile = null;
mineTimer = 0f;
}else{
}else if(mining()){
Item item = mineTile.drop();
rotation(Mathf.slerpDelta(rotation(), angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f));
rotation = Mathf.slerpDelta(rotation, angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f);
mineTimer += Time.delta *type.mineSpeed;
if(Mathf.chance(0.06 * Time.delta)){
@@ -48,6 +48,9 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
unit.remove();
payloads.add(new UnitPayload(unit));
Fx.unitPickup.at(unit);
if(Vars.net.client()){
Vars.netClient.clearRemovedEntity(unit.id);
}
}
void pickup(Building tile){
@@ -71,6 +74,11 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
boolean tryDropPayload(Payload payload){
Tile on = tileOn();
//clear removed state of unit so it can be synced
if(Vars.net.client() && payload instanceof UnitPayload){
Vars.netClient.clearRemovedEntity(((UnitPayload)payload).unit.id);
}
//drop off payload on an acceptor if possible
if(on != null && on.build != null && on.build.acceptPayload(on.build, payload)){
Fx.unitDrop.at(on.build);
@@ -134,7 +134,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
deathTimer += Time.delta;
if(deathTimer >= deathDelay){
//request spawn - this happens serverside only
core.requestSpawn(base());
core.requestSpawn(self());
deathTimer = 0;
}
}
@@ -191,7 +191,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
}
}
Events.fire(new UnitChangeEvent(base(), unit));
Events.fire(new UnitChangeEvent(self(), unit));
}
boolean dead(){
@@ -128,6 +128,6 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
@Override
public void afterRead(){
Puddles.register(base());
Puddles.register(self());
}
}
@@ -42,7 +42,7 @@ abstract class StatusComp implements Posc, Flyingc{
return;
}else if(entry.effect.reactsWith(effect)){ //find opposite
StatusEntry.tmp.effect = entry.effect;
entry.effect.getTransition(base(), effect, entry.time, duration, StatusEntry.tmp);
entry.effect.getTransition(self(), effect, entry.time, duration, StatusEntry.tmp);
entry.time = StatusEntry.tmp.time;
if(StatusEntry.tmp.effect != entry.effect){
@@ -125,14 +125,14 @@ abstract class StatusComp implements Posc, Flyingc{
armorMultiplier *= entry.effect.armorMultiplier;
damageMultiplier *= entry.effect.damageMultiplier;
reloadMultiplier *= entry.effect.reloadMultiplier;
entry.effect.update(base(), entry.time);
entry.effect.update(self(), entry.time);
}
}
}
public void draw(){
for(StatusEntry e : statuses){
e.effect.draw(base());
e.effect.draw(self());
}
}
+25 -12
View File
@@ -5,12 +5,14 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.entities.abilities.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
@@ -37,7 +39,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
private UnitType type;
boolean spawnedByCore, deactivated;
transient float timer1, timer2;
transient Seq<Ability> abilities = new Seq<>(0);
public void moveAt(Vec2 vector){
moveAt(vector, type.accel);
@@ -117,7 +119,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void controller(UnitController next){
this.controller = next;
if(controller.unit() != base()) controller.unit(base());
if(controller.unit() != self()) controller.unit(self());
}
@Override
@@ -171,7 +173,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return Units.getCap(team);
}
private void setStats(UnitType type){
public void setStats(UnitType type){
this.type = type;
this.maxHealth = type.health;
this.drag = type.drag;
@@ -181,13 +183,16 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(controller == null) controller(type.createController());
if(mounts().length != type.weapons.size) setupWeapons(type);
if(abilities.size != type.abilities.size){
abilities = type.abilities.map(Ability::copy);
}
}
@Override
public void afterSync(){
//set up type info after reading
setStats(this.type);
controller.unit(base());
controller.unit(self());
}
@Override
@@ -212,7 +217,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void remove(){
teamIndex.updateCount(team, type, -1);
controller.removed(base());
controller.removed(self());
}
@Override
@@ -221,7 +226,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
Effect.shake(type.landShake, type.landShake, this);
}
type.landed(base());
type.landed(self());
}
@Override
@@ -232,7 +237,15 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
deactivated = false;
}
if(!deactivated) type.update(base());
if(!deactivated){
type.update(self());
if(abilities.size > 0){
for(Ability a : abilities){
a.update(self());
}
}
}
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
@@ -282,7 +295,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(tile != null && isGrounded() && !type.hovering){
//unit block update
if(tile.build != null){
tile.build.unitOn(base());
tile.build.unitOn(self());
}
//apply damage
@@ -316,7 +329,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
//remove units spawned by the core
if(spawnedByCore && !isPlayer()){
Call.unitDespawn(base());
Call.unitDespawn(self());
}
}
@@ -338,7 +351,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
Effect.shake(shake, shake, this);
type.deathSound.at(this);
Events.fire(new UnitDestroyEvent(base()));
Events.fire(new UnitDestroyEvent(self()));
if(explosiveness > 7f && isLocal()){
Events.fire(Trigger.suicideBomb);
@@ -364,7 +377,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void display(Table table){
type.display(base(), table);
type.display(self(), table);
}
@Override
@@ -374,7 +387,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void draw(){
type.draw(base());
type.draw(self());
}
@Override
@@ -93,6 +93,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
for(WeaponMount mount : mounts){
Weapon weapon = mount.weapon;
mount.reload = Math.max(mount.reload - Time.delta * reloadMultiplier, 0);
mount.heat = Math.max(mount.heat - Time.delta * reloadMultiplier / mount.weapon.cooldownTime, 0);
//flip weapon shoot side for alternating weapons at half reload
if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite &&
@@ -127,7 +128,6 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
float rotation = this.rotation - 90;
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
//m a t h
float mountX = this.x + Angles.trnsx(rotation, weapon.x, weapon.y),
mountY = this.y + Angles.trnsy(rotation, weapon.x, weapon.y);
@@ -138,6 +138,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x));
mount.reload = weapon.reload;
mount.heat = 1f;
ammo--;
if(ammo < 0) ammo = 0;
@@ -164,9 +165,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl));
}
if(this instanceof Velc){
((Velc)this).vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
}
vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil));
boolean parentize = ammo.keepVelocity;
Effect.shake(weapon.shake, weapon.shake, x, y);
@@ -176,6 +176,11 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc{
}
private void bullet(Weapon weapon, float x, float y, float angle, float lifescl){
weapon.bullet.create(this, team(), x, y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl);
float xr = Mathf.range(weapon.xRand);
weapon.bullet.create(this, team(),
x + Angles.trnsx(angle, 0, xr),
y + Angles.trnsy(angle, 0, xr),
angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl);
}
}
@@ -152,7 +152,7 @@ public class AIController implements UnitController{
vec.rotate((circleLength - vec.len()) / circleLength * 180f);
}
vec.setLength(speed * Time.delta);
vec.setLength(speed);
unit.moveAt(vec);
}
@@ -164,7 +164,7 @@ public class AIController implements UnitController{
float length = circleLength <= 0.001f ? 1f : Mathf.clamp((unit.dst(target) - circleLength) / 100f, -1f, 1f);
vec.setLength(unit.type().speed * Time.delta * length);
vec.setLength(unit.type().speed * length);
if(length < -0.5f){
vec.rotate(180f);
}else if(length < 0){
@@ -11,6 +11,8 @@ public class WeaponMount{
public float rotation;
/** destination rotation; do not modify! */
public float targetRotation;
/** current heat, 0 to 1*/
public float heat;
/** aiming position in world coordinates */
public float aimX, aimY;
/** whether to shoot right now */
+1
View File
@@ -128,6 +128,7 @@ public class Saves{
sector.save.setName(sector.save.file.nameWithoutExtension());
saves.add(sector.save);
}
sector.save.setAutosave(true);
sector.save.save();
lastSectorSave = sector.save;
Core.settings.put("last-sector-save", sector.save.getName());
+4 -6
View File
@@ -2,9 +2,10 @@ package mindustry.game;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.CoreBlock.*;
@@ -32,6 +33,8 @@ public class SectorInfo{
public boolean hasCore = true;
/** Sector that was launched from. */
public @Nullable Sector origin;
/** Resources known to occur at this sector. */
public Seq<UnlockableContent> resources = new Seq<>();
/** Time spent at this sector. Do not use unless you know what you're doing. */
public transient float internalTimeSpent;
@@ -86,11 +89,6 @@ public class SectorInfo{
public void update(){
internalTimeSpent += Time.delta;
//time spent exceeds turn duration!
if(internalTimeSpent >= turnDuration && internalTimeSpent - Time.delta < turnDuration){
universe.displayTimeEnd();
}
//create last stored core items
if(lastCoreItems == null){
lastCoreItems = new int[content.items().size];
+1 -1
View File
@@ -39,7 +39,7 @@ public class Stats{
//weigh used fractions
float frac = 0f;
Seq<Item> obtainable = Seq.select(zone.data.resources, i -> i instanceof Item).as();
Seq<Item> obtainable = zone.save == null ? new Seq<>() : zone.save.meta.secinfo.resources.select(i -> i instanceof Item).as();
for(Item item : obtainable){
frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size;
}
+1 -1
View File
@@ -56,7 +56,7 @@ public class Universe{
public void displayTimeEnd(){
if(!headless){
//check if any sectors are under attack to display this
Seq<Sector> attacked = state.getSector().planet.sectors.select(s -> s.hasWaves() && s.hasBase() && !s.isBeingPlayed());
Seq<Sector> attacked = state.getSector().planet.sectors.select(s -> s.hasWaves() && s.hasBase() && !s.isBeingPlayed() && s.getSecondsPassed() > 1);
if(attacked.any()){
state.set(State.paused);
@@ -18,6 +18,17 @@ public enum CacheLayer{
endShader(Shaders.water);
}
},
mud{
@Override
public void begin(){
beginShader();
}
@Override
public void end(){
endShader(Shaders.mud);
}
},
tar{
@Override
public void begin(){
+14
View File
@@ -172,6 +172,20 @@ public class Drawf{
construct(t, content.icon(Cicon.full), rotation, progress, speed, time);
}
public static void construct(float x, float y, TextureRegion region, float rotation, float progress, float speed, float time){
Shaders.build.region = region;
Shaders.build.progress = progress;
Shaders.build.color.set(Pal.accent);
Shaders.build.color.a = speed;
Shaders.build.time = -time / 20f;
Draw.shader(Shaders.build);
Draw.rect(region, x, y, rotation);
Draw.shader();
Draw.reset();
}
public static void construct(Building t, TextureRegion region, float rotation, float progress, float speed, float time){
Shaders.build.region = region;
Shaders.build.progress = progress;
@@ -228,7 +228,7 @@ public class FloorRenderer implements Disposable{
int chunksx = Mathf.ceil((float)(world.width()) / chunksize),
chunksy = Mathf.ceil((float)(world.height()) / chunksize);
cache = new Chunk[chunksx][chunksy];
cbatch = new MultiCacheBatch(chunksize * chunksize * 6);
cbatch = new MultiCacheBatch(chunksize * chunksize * 7);
Time.mark();
@@ -96,24 +96,24 @@ public class IndexedRenderer implements Disposable{
vertices[idx++] = v2;
//tri2
vertices[idx++] = x;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = fx2;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v;
vertices[idx++] = fx2;
vertices[idx++] = fy2;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v2;
vertices[idx++] = fx2;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v;
vertices[idx++] = x;
vertices[idx++] = y;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v;
mesh.updateVertices(index * vsize * 6, vertices);
}
@@ -155,6 +155,19 @@ public class IndexedRenderer implements Disposable{
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = x2;
vertices[idx++] = y2;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v2;
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v2;
//tri2
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = color;
@@ -164,28 +177,15 @@ public class IndexedRenderer implements Disposable{
vertices[idx++] = x4;
vertices[idx++] = y4;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v2;
vertices[idx++] = u2;
vertices[idx++] = v;
//tri2
vertices[idx++] = x1;
vertices[idx++] = y1;
vertices[idx++] = color;
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = x2;
vertices[idx++] = y2;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v;
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = color;
vertices[idx++] = u2;
vertices[idx++] = v2;
mesh.updateVertices(index * vsize * 6, vertices);
}
+2 -1
View File
@@ -20,7 +20,7 @@ public class Shaders{
public static UnitBuild build;
public static DarknessShader darkness;
public static LightShader light;
public static SurfaceShader water, tar, slag;
public static SurfaceShader water, mud, tar, slag;
public static PlanetShader planet;
public static PlanetGridShader planetGrid;
public static AtmosphereShader atmosphere;
@@ -42,6 +42,7 @@ public class Shaders{
darkness = new DarknessShader();
light = new LightShader();
water = new SurfaceShader("water");
mud = new SurfaceShader("mud");
tar = new SurfaceShader("tar");
slag = new SurfaceShader("slag");
planet = new PlanetShader();
+2 -1
View File
@@ -47,6 +47,7 @@ public class DesktopInput extends InputHandler{
@Override
public void buildUI(Group group){
group.fill(t -> {
t.visible(() -> Core.settings.getBool("hints") && ui.hudfrag.shown() && !player.dead() && !player.unit().spawnedByCore() && !(Core.settings.getBool("hints") && lastSchematic != null && !selectRequests.isEmpty()));
t.bottom();
@@ -224,7 +225,7 @@ public class DesktopInput extends InputHandler{
if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){
updateMovement(player.unit());
if(Core.input.keyDown(Binding.respawn) && !player.unit().spawnedByCore()){
if(Core.input.keyDown(Binding.respawn) && !player.unit().spawnedByCore() && !scene.hasField()){
Call.unitClear(player);
controlledType = null;
}
+2 -1
View File
@@ -236,7 +236,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
@Remote(targets = Loc.both, forward = true, called = Loc.server)
public static void transferInventory(Player player, Building tile){
if(player == null || tile == null || !player.within(tile, buildingRange)) return;
if(player == null || tile == null || !player.within(tile, buildingRange) || tile.items == null) return;
if(net.server() && (player.unit().stack.amount <= 0 || !Units.canInteract(player, tile) ||
!netServer.admins.allowAction(player, ActionType.depositItem, tile.tile, action -> {
@@ -980,6 +980,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
uiGroup.touchable = Touchable.childrenOnly;
uiGroup.setFillParent(true);
ui.hudGroup.addChild(uiGroup);
uiGroup.toBack();
buildUI(uiGroup);
frag.add();
+29
View File
@@ -100,6 +100,20 @@ public class JsonIO{
}
});
json.setSerializer(Liquid.class, new Serializer<Liquid>(){
@Override
public void write(Json json, Liquid object, Class knownType){
json.writeValue(object.name);
}
@Override
public Liquid read(Json json, JsonValue jsonData, Class type){
if(jsonData.asString() == null) return Liquids.water;
Liquid i = Vars.content.getByName(ContentType.liquid, jsonData.asString());
return i == null ? Liquids.water : i;
}
});
json.setSerializer(Item.class, new Serializer<Item>(){
@Override
public void write(Json json, Item object, Class knownType){
@@ -165,6 +179,21 @@ public class JsonIO{
return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount"));
}
});
json.setSerializer(UnlockableContent.class, new Serializer<UnlockableContent>(){
@Override
public void write(Json json, UnlockableContent object, Class knownType){
json.writeValue(object.name);
}
@Override
public UnlockableContent read(Json json, JsonValue jsonData, Class type){
String str = jsonData.asString();
Item item = Vars.content.getByName(ContentType.item, str);
Liquid liquid = Vars.content.getByName(ContentType.liquid, str);
return item != null ? item : liquid;
}
});
}
static class CustomJson extends Json{
+12 -10
View File
@@ -3,6 +3,7 @@ package mindustry.io;
import arc.*;
import arc.files.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
import mindustry.game.EventType.*;
@@ -41,7 +42,7 @@ public class SaveIO{
if(exists) file.moveTo(backupFileFor(file));
try{
write(file);
}catch(Exception e){
}catch(Throwable e){
if(exists) backupFileFor(file).moveTo(file);
throw new RuntimeException(e);
}
@@ -56,9 +57,9 @@ public class SaveIO{
}
public static boolean isSaveValid(Fi file){
try{
return isSaveValid(new DataInputStream(new InflaterInputStream(file.read(bufferSize))));
}catch(Exception e){
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(file.read(bufferSize)))){
return isSaveValid(stream);
}catch(Throwable e){
return false;
}
}
@@ -67,8 +68,8 @@ public class SaveIO{
try{
getMeta(stream);
return true;
}catch(Exception e){
e.printStackTrace();
}catch(Throwable e){
Log.err(e);
return false;
}
}
@@ -76,7 +77,8 @@ public class SaveIO{
public static SaveMeta getMeta(Fi file){
try{
return getMeta(getStream(file));
}catch(Exception e){
}catch(Throwable e){
Log.err(e);
return getMeta(getBackupStream(file));
}
}
@@ -119,7 +121,7 @@ public class SaveIO{
}else{
getVersion().write(stream, tags);
}
}catch(Exception e){
}catch(Throwable e){
throw new RuntimeException(e);
}
}
@@ -133,7 +135,7 @@ public class SaveIO{
//try and load; if any exception at all occurs
load(new InflaterInputStream(file.read(bufferSize)), context);
}catch(SaveException e){
e.printStackTrace();
Log.err(e);
Fi backup = file.sibling(file.name() + "-backup." + file.extension());
if(backup.exists()){
load(new InflaterInputStream(backup.read(bufferSize)), context);
@@ -153,7 +155,7 @@ public class SaveIO{
ver.read(stream, counter, context);
Events.fire(new SaveLoadEvent());
}catch(Exception e){
}catch(Throwable e){
throw new SaveException(e);
}finally{
world.setGenerating(false);

Some files were not shown because too many files have changed in this diff Show More