Merge branch 'master' into master
@@ -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")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 984 B After Width: | Height: | Size: 893 B |
@@ -4,6 +4,5 @@
|
||||
flattenPaths: true,
|
||||
maxWidth: 4096,
|
||||
maxHeight: 4096,
|
||||
minHeight: 2048,
|
||||
fast: true
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
@@ -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
|
||||
|
||||
@@ -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 = 메가
|
||||
|
||||
@@ -91,3 +91,4 @@ GioIacca9
|
||||
SnakkiZXZ
|
||||
sk7725
|
||||
The Slaylord
|
||||
ThePlayerA
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 811 B |
|
Before Width: | Height: | Size: 647 KiB After Width: | Height: | Size: 642 KiB |
|
Before Width: | Height: | Size: 958 KiB After Width: | Height: | Size: 735 KiB |
|
Before Width: | Height: | Size: 365 KiB After Width: | Height: | Size: 1013 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 187 KiB |
|
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 415 KiB After Width: | Height: | Size: 416 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 314 KiB After Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 418 KiB After Width: | Height: | Size: 420 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.4 MiB |
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
}};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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()){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()){
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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"){
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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)];
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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);
|
||||
|
||||