More branch merging
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 626 B |
BIN
core/assets-raw/sprites/blocks/liquid/liquid-container-top.png
Normal file
BIN
core/assets-raw/sprites/blocks/liquid/liquid-container-top.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 298 B |
Binary file not shown.
|
Before Width: | Height: | Size: 712 B After Width: | Height: | Size: 1.2 KiB |
@@ -1295,6 +1295,7 @@ block.plated-conduit.name = Plated Conduit
|
|||||||
block.phase-conduit.name = Phase Conduit
|
block.phase-conduit.name = Phase Conduit
|
||||||
block.liquid-router.name = Liquid Router
|
block.liquid-router.name = Liquid Router
|
||||||
block.liquid-tank.name = Liquid Tank
|
block.liquid-tank.name = Liquid Tank
|
||||||
|
block.liquid-container.name = Liquid Container
|
||||||
block.liquid-junction.name = Liquid Junction
|
block.liquid-junction.name = Liquid Junction
|
||||||
block.bridge-conduit.name = Bridge Conduit
|
block.bridge-conduit.name = Bridge Conduit
|
||||||
block.rotary-pump.name = Rotary Pump
|
block.rotary-pump.name = Rotary Pump
|
||||||
@@ -1506,6 +1507,7 @@ block.conduit.description = Moves liquids forward. Used in conjunction with pump
|
|||||||
block.pulse-conduit.description = Moves liquids forward. Transports faster and stores more than standard conduits.
|
block.pulse-conduit.description = Moves liquids forward. Transports faster and stores more than standard conduits.
|
||||||
block.plated-conduit.description = Moves liquids forward. Does not accept input from the sides. Does not leak.
|
block.plated-conduit.description = Moves liquids forward. Does not accept input from the sides. Does not leak.
|
||||||
block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid.
|
block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid.
|
||||||
|
block.liquid-container.description = Stores a sizeable amount of liquid. Outputs to all sides, similarly to a liquid router.
|
||||||
block.liquid-tank.description = Stores a large amount of liquid. Outputs to all sides, similarly to a liquid router.
|
block.liquid-tank.description = Stores a large amount of liquid. Outputs to all sides, similarly to a liquid router.
|
||||||
block.liquid-junction.description = Acts as a bridge for two crossing conduits.
|
block.liquid-junction.description = Acts as a bridge for two crossing conduits.
|
||||||
block.bridge-conduit.description = Transports liquids over terrain or buildings.
|
block.bridge-conduit.description = Transports liquids over terrain or buildings.
|
||||||
|
|||||||
@@ -361,3 +361,10 @@
|
|||||||
63347=crater-stone|block-crater-stone-ui
|
63347=crater-stone|block-crater-stone-ui
|
||||||
63346=deep-tainted-water|block-deep-tainted-water-ui
|
63346=deep-tainted-water|block-deep-tainted-water-ui
|
||||||
63345=pooled-cryofluid|block-pooled-cryofluid-ui
|
63345=pooled-cryofluid|block-pooled-cryofluid-ui
|
||||||
|
63344=empty|block-empty-ui
|
||||||
|
63343=liquid-container|block-liquid-container-ui
|
||||||
|
63342=deconstructor|block-deconstructor-ui
|
||||||
|
63341=constructor|block-constructor-ui
|
||||||
|
63340=large-constructor|block-large-constructor-ui
|
||||||
|
63339=payload-loader|block-payload-loader-ui
|
||||||
|
63338=payload-unloader|block-payload-unloader-ui
|
||||||
|
|||||||
Binary file not shown.
20
core/assets/shaders/clouds.vert
Executable file
20
core/assets/shaders/clouds.vert
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec3 a_normal;
|
||||||
|
attribute vec4 a_color;
|
||||||
|
|
||||||
|
uniform mat4 u_proj;
|
||||||
|
uniform mat4 u_trans;
|
||||||
|
uniform vec3 u_lightdir;
|
||||||
|
uniform vec3 u_ambientColor;
|
||||||
|
uniform float u_alpha;
|
||||||
|
|
||||||
|
varying vec4 v_col;
|
||||||
|
|
||||||
|
const vec3 diffuse = vec3(0.01);
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec3 norc = u_ambientColor * (diffuse + vec3(clamp((dot(a_normal, u_lightdir) + 1.0) / 2.0, 0.0, 1.0)));
|
||||||
|
|
||||||
|
v_col = a_color * vec4(norc, u_alpha);
|
||||||
|
gl_Position = u_proj * u_trans * a_position;
|
||||||
|
}
|
||||||
@@ -380,7 +380,7 @@ public class Vars implements Loadable{
|
|||||||
log.log(level, text);
|
log.log(level, text);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
writer.write("[" + Character.toUpperCase(level.name().charAt(0)) +"] " + Log.removeColors(text) + "\n");
|
writer.write("[" + Character.toUpperCase(level.name().charAt(0)) + "] " + Log.removeColors(text) + "\n");
|
||||||
writer.flush();
|
writer.flush();
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class Pathfinder implements Runnable{
|
|||||||
|
|
||||||
//legs
|
//legs
|
||||||
(team, tile) -> PathTile.legSolid(tile) ? impassable : 1 +
|
(team, tile) -> PathTile.legSolid(tile) ? impassable : 1 +
|
||||||
|
(PathTile.deep(tile) ? 6000 : 0) + //leg units can now drown
|
||||||
(PathTile.solid(tile) ? 5 : 0),
|
(PathTile.solid(tile) ? 5 : 0),
|
||||||
|
|
||||||
//water
|
//water
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ public class WaveSpawner{
|
|||||||
unit.apply(StatusEffects.unmoving, 30f);
|
unit.apply(StatusEffects.unmoving, 30f);
|
||||||
unit.apply(StatusEffects.invincible, 60f);
|
unit.apply(StatusEffects.invincible, 60f);
|
||||||
unit.add();
|
unit.add();
|
||||||
|
unit.unloaded();
|
||||||
|
|
||||||
Events.fire(new UnitSpawnEvent(unit));
|
Events.fire(new UnitSpawnEvent(unit));
|
||||||
Call.spawnEffect(unit.x, unit.y, unit.rotation, unit.type);
|
Call.spawnEffect(unit.x, unit.y, unit.rotation, unit.type);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class Blocks implements ContentList{
|
|||||||
public static Block
|
public static Block
|
||||||
|
|
||||||
//environment
|
//environment
|
||||||
air, spawn, cliff, deepwater, water, taintedWater, deepTaintedWater, tar, slag, cryofluid, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space,
|
air, spawn, cliff, deepwater, water, taintedWater, deepTaintedWater, tar, slag, cryofluid, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space, empty,
|
||||||
dacite,
|
dacite,
|
||||||
stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
|
stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
|
||||||
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, boulder, snowBoulder, basaltBoulder, grass, salt,
|
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, boulder, snowBoulder, basaltBoulder, grass, salt,
|
||||||
@@ -435,18 +435,6 @@ public class Blocks implements ContentList{
|
|||||||
basalt.asFloor().decoration = hotrock.asFloor().decoration = darksand.asFloor().decoration = magmarock.asFloor().decoration = this;
|
basalt.asFloor().decoration = hotrock.asFloor().decoration = darksand.asFloor().decoration = magmarock.asFloor().decoration = this;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
moss = new Floor("moss"){{
|
|
||||||
variants = 3;
|
|
||||||
attributes.set(Attribute.spores, 0.15f);
|
|
||||||
wall = sporePine;
|
|
||||||
}};
|
|
||||||
|
|
||||||
sporeMoss = new Floor("spore-moss"){{
|
|
||||||
variants = 3;
|
|
||||||
attributes.set(Attribute.spores, 0.3f);
|
|
||||||
wall = sporeWall;
|
|
||||||
}};
|
|
||||||
|
|
||||||
metalFloor = new Floor("metal-floor", 0);
|
metalFloor = new Floor("metal-floor", 0);
|
||||||
metalFloorDamaged = new Floor("metal-floor-damaged", 3);
|
metalFloorDamaged = new Floor("metal-floor-damaged", 3);
|
||||||
|
|
||||||
@@ -2105,14 +2093,15 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
constructor = new Constructor("constructor"){{
|
constructor = new Constructor("constructor"){{
|
||||||
requirements(Category.units, with(Items.thorium, 100));
|
requirements(Category.units, with(Items.silicon, 50, Items.thorium, 70, Items.graphite, 50));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
consumes.power(2f);
|
consumes.power(2f);
|
||||||
size = 3;
|
size = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//yes this block is pretty much useless
|
||||||
largeConstructor = new Constructor("large-constructor"){{
|
largeConstructor = new Constructor("large-constructor"){{
|
||||||
requirements(Category.units, with(Items.thorium, 100));
|
requirements(Category.units, with(Items.silicon, 100, Items.thorium, 150, Items.graphite, 50, Items.phaseFabric, 40));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
consumes.power(2f);
|
consumes.power(2f);
|
||||||
maxBlockSize = 4;
|
maxBlockSize = 4;
|
||||||
@@ -2121,20 +2110,20 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
payloadLoader = new PayloadLoader("payload-loader"){{
|
payloadLoader = new PayloadLoader("payload-loader"){{
|
||||||
requirements(Category.units, with(Items.thorium, 100));
|
requirements(Category.units, with(Items.graphite, 50, Items.silicon, 50, Items.copper, 100));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
consumes.power(2f);
|
consumes.power(2f);
|
||||||
size = 3;
|
size = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
payloadUnloader = new PayloadUnloader("payload-unloader"){{
|
payloadUnloader = new PayloadUnloader("payload-unloader"){{
|
||||||
requirements(Category.units, with(Items.thorium, 100));
|
requirements(Category.units, with(Items.graphite, 50, Items.silicon, 50, Items.copper, 100));
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
consumes.power(2f);
|
consumes.power(2f);
|
||||||
size = 3;
|
size = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//TODO deprecated
|
//deprecated, will be removed.
|
||||||
blockForge = constructor;
|
blockForge = constructor;
|
||||||
blockLoader = payloadLoader;
|
blockLoader = payloadLoader;
|
||||||
blockUnloader = payloadUnloader;
|
blockUnloader = payloadUnloader;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class Planets implements ContentList{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
sun = new Planet("sun", null, 0, 2){{
|
sun = new Planet("sun", null, 4){{
|
||||||
bloom = true;
|
bloom = true;
|
||||||
accessible = false;
|
accessible = false;
|
||||||
|
|
||||||
@@ -31,9 +31,13 @@ public class Planets implements ContentList{
|
|||||||
);
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
serpulo = new Planet("serpulo", sun, 3, 1){{
|
serpulo = new Planet("serpulo", sun, 1, 3){{
|
||||||
generator = new SerpuloPlanetGenerator();
|
generator = new SerpuloPlanetGenerator();
|
||||||
meshLoader = () -> new HexMesh(this, 6);
|
meshLoader = () -> new HexMesh(this, 6);
|
||||||
|
cloudMeshLoader = () -> new MultiMesh(
|
||||||
|
new HexSkyMesh(this, 11, 0.15f, 0.13f, 5, new Color().set(Pal.spore).mul(0.9f).a(0.75f), 2, 0.45f, 0.9f, 0.38f),
|
||||||
|
new HexSkyMesh(this, 1, 0.6f, 0.16f, 5, Color.white.cpy().lerp(Pal.spore, 0.55f).a(0.75f), 2, 0.45f, 1f, 0.41f)
|
||||||
|
);
|
||||||
atmosphereColor = Color.valueOf("3c1b8f");
|
atmosphereColor = Color.valueOf("3c1b8f");
|
||||||
atmosphereRadIn = 0.02f;
|
atmosphereRadIn = 0.02f;
|
||||||
atmosphereRadOut = 0.3f;
|
atmosphereRadOut = 0.3f;
|
||||||
|
|||||||
@@ -157,13 +157,13 @@ public class UnitTypes implements ContentList{
|
|||||||
rotateSpeed = 2.1f;
|
rotateSpeed = 2.1f;
|
||||||
health = 9000;
|
health = 9000;
|
||||||
armor = 10f;
|
armor = 10f;
|
||||||
canDrown = false;
|
|
||||||
mechFrontSway = 1f;
|
mechFrontSway = 1f;
|
||||||
ammoType = new ItemAmmoType(Items.thorium);
|
ammoType = new ItemAmmoType(Items.thorium);
|
||||||
|
|
||||||
mechStepParticles = true;
|
mechStepParticles = true;
|
||||||
mechStepShake = 0.15f;
|
mechStepShake = 0.15f;
|
||||||
singleTarget = true;
|
singleTarget = true;
|
||||||
|
drownTimeMultiplier = 4f;
|
||||||
|
|
||||||
weapons.add(
|
weapons.add(
|
||||||
new Weapon("scepter-weapon"){{
|
new Weapon("scepter-weapon"){{
|
||||||
@@ -221,7 +221,7 @@ public class UnitTypes implements ContentList{
|
|||||||
armor = 14f;
|
armor = 14f;
|
||||||
mechStepParticles = true;
|
mechStepParticles = true;
|
||||||
mechStepShake = 0.75f;
|
mechStepShake = 0.75f;
|
||||||
canDrown = false;
|
drownTimeMultiplier = 6f;
|
||||||
mechFrontSway = 1.9f;
|
mechFrontSway = 1.9f;
|
||||||
mechSideSway = 0.6f;
|
mechSideSway = 0.6f;
|
||||||
ammoType = new ItemAmmoType(Items.thorium);
|
ammoType = new ItemAmmoType(Items.thorium);
|
||||||
@@ -414,13 +414,13 @@ public class UnitTypes implements ContentList{
|
|||||||
hitSize = 24f;
|
hitSize = 24f;
|
||||||
|
|
||||||
rotateSpeed = 1.8f;
|
rotateSpeed = 1.8f;
|
||||||
canDrown = false;
|
|
||||||
mechFrontSway = 1f;
|
mechFrontSway = 1f;
|
||||||
buildSpeed = 3f;
|
buildSpeed = 3f;
|
||||||
|
|
||||||
mechStepParticles = true;
|
mechStepParticles = true;
|
||||||
mechStepShake = 0.15f;
|
mechStepShake = 0.15f;
|
||||||
ammoType = new PowerAmmoType(2500);
|
ammoType = new PowerAmmoType(2500);
|
||||||
|
drownTimeMultiplier = 4f;
|
||||||
|
|
||||||
speed = 0.44f;
|
speed = 0.44f;
|
||||||
boostMultiplier = 2.4f;
|
boostMultiplier = 2.4f;
|
||||||
@@ -501,6 +501,7 @@ public class UnitTypes implements ContentList{
|
|||||||
armor = 9f;
|
armor = 9f;
|
||||||
landShake = 1.5f;
|
landShake = 1.5f;
|
||||||
rotateSpeed = 1.5f;
|
rotateSpeed = 1.5f;
|
||||||
|
drownTimeMultiplier = 6f;
|
||||||
|
|
||||||
commandLimit = 8;
|
commandLimit = 8;
|
||||||
|
|
||||||
@@ -511,7 +512,6 @@ public class UnitTypes implements ContentList{
|
|||||||
legTrns = 0.58f;
|
legTrns = 0.58f;
|
||||||
hovering = true;
|
hovering = true;
|
||||||
visualElevation = 0.2f;
|
visualElevation = 0.2f;
|
||||||
allowLegStep = true;
|
|
||||||
ammoType = new PowerAmmoType(4000);
|
ammoType = new PowerAmmoType(4000);
|
||||||
groundLayer = Layer.legUnit;
|
groundLayer = Layer.legUnit;
|
||||||
|
|
||||||
@@ -602,7 +602,7 @@ public class UnitTypes implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
atrax = new UnitType("atrax"){{
|
atrax = new UnitType("atrax"){{
|
||||||
speed = 0.54f;
|
speed = 0.57f;
|
||||||
drag = 0.4f;
|
drag = 0.4f;
|
||||||
hitSize = 13f;
|
hitSize = 13f;
|
||||||
rotateSpeed = 3f;
|
rotateSpeed = 3f;
|
||||||
@@ -618,7 +618,6 @@ public class UnitTypes implements ContentList{
|
|||||||
armor = 3f;
|
armor = 3f;
|
||||||
ammoType = new ItemAmmoType(Items.coal);
|
ammoType = new ItemAmmoType(Items.coal);
|
||||||
|
|
||||||
allowLegStep = true;
|
|
||||||
visualElevation = 0.2f;
|
visualElevation = 0.2f;
|
||||||
groundLayer = Layer.legUnit - 1f;
|
groundLayer = Layer.legUnit - 1f;
|
||||||
|
|
||||||
@@ -632,8 +631,8 @@ public class UnitTypes implements ContentList{
|
|||||||
shootSound = Sounds.flame;
|
shootSound = Sounds.flame;
|
||||||
|
|
||||||
bullet = new LiquidBulletType(Liquids.slag){{
|
bullet = new LiquidBulletType(Liquids.slag){{
|
||||||
damage = 11;
|
damage = 13;
|
||||||
speed = 2.4f;
|
speed = 2.5f;
|
||||||
drag = 0.009f;
|
drag = 0.009f;
|
||||||
shootEffect = Fx.shootSmall;
|
shootEffect = Fx.shootSmall;
|
||||||
lifetime = 57f;
|
lifetime = 57f;
|
||||||
@@ -643,11 +642,11 @@ public class UnitTypes implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
spiroct = new UnitType("spiroct"){{
|
spiroct = new UnitType("spiroct"){{
|
||||||
speed = 0.48f;
|
speed = 0.52f;
|
||||||
drag = 0.4f;
|
drag = 0.4f;
|
||||||
hitSize = 15f;
|
hitSize = 15f;
|
||||||
rotateSpeed = 3f;
|
rotateSpeed = 3f;
|
||||||
health = 910;
|
health = 940;
|
||||||
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
|
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
|
||||||
legCount = 6;
|
legCount = 6;
|
||||||
legLength = 13f;
|
legLength = 13f;
|
||||||
@@ -660,7 +659,6 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
buildSpeed = 0.75f;
|
buildSpeed = 0.75f;
|
||||||
|
|
||||||
allowLegStep = true;
|
|
||||||
visualElevation = 0.3f;
|
visualElevation = 0.3f;
|
||||||
groundLayer = Layer.legUnit;
|
groundLayer = Layer.legUnit;
|
||||||
|
|
||||||
@@ -678,7 +676,7 @@ public class UnitTypes implements ContentList{
|
|||||||
bullet = new SapBulletType(){{
|
bullet = new SapBulletType(){{
|
||||||
sapStrength = 0.5f;
|
sapStrength = 0.5f;
|
||||||
length = 75f;
|
length = 75f;
|
||||||
damage = 20;
|
damage = 23;
|
||||||
shootEffect = Fx.shootSmall;
|
shootEffect = Fx.shootSmall;
|
||||||
hitColor = color = Color.valueOf("bf92f9");
|
hitColor = color = Color.valueOf("bf92f9");
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
@@ -698,7 +696,7 @@ public class UnitTypes implements ContentList{
|
|||||||
bullet = new SapBulletType(){{
|
bullet = new SapBulletType(){{
|
||||||
sapStrength = 0.8f;
|
sapStrength = 0.8f;
|
||||||
length = 40f;
|
length = 40f;
|
||||||
damage = 16;
|
damage = 18;
|
||||||
shootEffect = Fx.shootSmall;
|
shootEffect = Fx.shootSmall;
|
||||||
hitColor = color = Color.valueOf("bf92f9");
|
hitColor = color = Color.valueOf("bf92f9");
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
@@ -711,7 +709,7 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
arkyid = new UnitType("arkyid"){{
|
arkyid = new UnitType("arkyid"){{
|
||||||
drag = 0.1f;
|
drag = 0.1f;
|
||||||
speed = 0.6f;
|
speed = 0.62f;
|
||||||
hitSize = 23f;
|
hitSize = 23f;
|
||||||
health = 8000;
|
health = 8000;
|
||||||
armor = 6f;
|
armor = 6f;
|
||||||
@@ -733,16 +731,16 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
legSplashDamage = 32;
|
legSplashDamage = 32;
|
||||||
legSplashRange = 30;
|
legSplashRange = 30;
|
||||||
|
drownTimeMultiplier = 2f;
|
||||||
|
|
||||||
hovering = true;
|
hovering = true;
|
||||||
allowLegStep = true;
|
|
||||||
visualElevation = 0.65f;
|
visualElevation = 0.65f;
|
||||||
groundLayer = Layer.legUnit;
|
groundLayer = Layer.legUnit;
|
||||||
|
|
||||||
BulletType sapper = new SapBulletType(){{
|
BulletType sapper = new SapBulletType(){{
|
||||||
sapStrength = 0.85f;
|
sapStrength = 0.85f;
|
||||||
length = 55f;
|
length = 55f;
|
||||||
damage = 37;
|
damage = 40;
|
||||||
shootEffect = Fx.shootSmall;
|
shootEffect = Fx.shootSmall;
|
||||||
hitColor = color = Color.valueOf("bf92f9");
|
hitColor = color = Color.valueOf("bf92f9");
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
@@ -820,6 +818,7 @@ public class UnitTypes implements ContentList{
|
|||||||
lightRadius = 140f;
|
lightRadius = 140f;
|
||||||
|
|
||||||
rotateSpeed = 1.9f;
|
rotateSpeed = 1.9f;
|
||||||
|
drownTimeMultiplier = 3f;
|
||||||
|
|
||||||
legCount = 8;
|
legCount = 8;
|
||||||
legMoveSpace = 0.8f;
|
legMoveSpace = 0.8f;
|
||||||
@@ -828,7 +827,6 @@ public class UnitTypes implements ContentList{
|
|||||||
legExtension = -20;
|
legExtension = -20;
|
||||||
legBaseOffset = 8f;
|
legBaseOffset = 8f;
|
||||||
landShake = 1f;
|
landShake = 1f;
|
||||||
legSpeed = 0.1f;
|
|
||||||
legLengthScl = 0.93f;
|
legLengthScl = 0.93f;
|
||||||
rippleScale = 3f;
|
rippleScale = 3f;
|
||||||
legSpeed = 0.19f;
|
legSpeed = 0.19f;
|
||||||
@@ -839,7 +837,6 @@ public class UnitTypes implements ContentList{
|
|||||||
legSplashRange = 60;
|
legSplashRange = 60;
|
||||||
|
|
||||||
hovering = true;
|
hovering = true;
|
||||||
allowLegStep = true;
|
|
||||||
visualElevation = 0.95f;
|
visualElevation = 0.95f;
|
||||||
groundLayer = Layer.legUnit;
|
groundLayer = Layer.legUnit;
|
||||||
|
|
||||||
@@ -2287,6 +2284,7 @@ public class UnitTypes implements ContentList{
|
|||||||
defaultController = BuilderAI::new;
|
defaultController = BuilderAI::new;
|
||||||
isCounted = false;
|
isCounted = false;
|
||||||
|
|
||||||
|
lowAltitude = true;
|
||||||
flying = true;
|
flying = true;
|
||||||
mineSpeed = 6.5f;
|
mineSpeed = 6.5f;
|
||||||
mineTier = 1;
|
mineTier = 1;
|
||||||
@@ -2366,6 +2364,7 @@ public class UnitTypes implements ContentList{
|
|||||||
defaultController = BuilderAI::new;
|
defaultController = BuilderAI::new;
|
||||||
isCounted = false;
|
isCounted = false;
|
||||||
|
|
||||||
|
lowAltitude = true;
|
||||||
flying = true;
|
flying = true;
|
||||||
mineSpeed = 8f;
|
mineSpeed = 8f;
|
||||||
mineTier = 2;
|
mineTier = 2;
|
||||||
|
|||||||
@@ -151,11 +151,6 @@ public class ContentLoader{
|
|||||||
ColorMapper.load();
|
ColorMapper.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose(){
|
|
||||||
initialize(Content::dispose);
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get last piece of content created for error-handling purposes. */
|
/** Get last piece of content created for error-handling purposes. */
|
||||||
public @Nullable Content getLastAdded(){
|
public @Nullable Content getLastAdded(){
|
||||||
return lastAdded;
|
return lastAdded;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.core;
|
package mindustry.core;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
|
import arc.assets.loaders.TextureLoader.*;
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.Texture.*;
|
import arc.graphics.Texture.*;
|
||||||
@@ -42,12 +43,14 @@ public class Renderer implements ApplicationListener{
|
|||||||
public PlanetRenderer planets;
|
public PlanetRenderer planets;
|
||||||
|
|
||||||
public @Nullable Bloom bloom;
|
public @Nullable Bloom bloom;
|
||||||
|
public @Nullable FrameBuffer backgroundBuffer;
|
||||||
public FrameBuffer effectBuffer = new FrameBuffer();
|
public FrameBuffer effectBuffer = new FrameBuffer();
|
||||||
public boolean animateShields, drawWeather = true, drawStatus;
|
public boolean animateShields, drawWeather = true, drawStatus;
|
||||||
public float weatherAlpha;
|
public float weatherAlpha;
|
||||||
/** minZoom = zooming out, maxZoom = zooming in */
|
/** minZoom = zooming out, maxZoom = zooming in */
|
||||||
public float minZoom = 1.5f, maxZoom = 6f;
|
public float minZoom = 1.5f, maxZoom = 6f;
|
||||||
public Seq<EnvRenderer> envRenderers = new Seq<>();
|
public Seq<EnvRenderer> envRenderers = new Seq<>();
|
||||||
|
public ObjectMap<String, Runnable> customBackgrounds = new ObjectMap<>();
|
||||||
public TextureRegion[] bubbles = new TextureRegion[16], splashes = new TextureRegion[12];
|
public TextureRegion[] bubbles = new TextureRegion[16], splashes = new TextureRegion[12];
|
||||||
|
|
||||||
private @Nullable CoreBuild landCore;
|
private @Nullable CoreBuild landCore;
|
||||||
@@ -88,6 +91,10 @@ public class Renderer implements ApplicationListener{
|
|||||||
envRenderers.add(new EnvRenderer(mask, render));
|
envRenderers.add(new EnvRenderer(mask, render));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addCustomBackground(String name, Runnable render){
|
||||||
|
customBackgrounds.put(name, render);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
planets = new PlanetRenderer();
|
planets = new PlanetRenderer();
|
||||||
@@ -108,6 +115,14 @@ public class Renderer implements ApplicationListener{
|
|||||||
t.setWrap(TextureWrap.repeat);
|
t.setWrap(TextureWrap.repeat);
|
||||||
t.setFilter(TextureFilter.linear);
|
t.setFilter(TextureFilter.linear);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Events.on(WorldLoadEvent.class, e -> {
|
||||||
|
//reset background buffer on every world load, so it can be re-cached first render
|
||||||
|
if(backgroundBuffer != null){
|
||||||
|
backgroundBuffer.dispose();
|
||||||
|
backgroundBuffer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -311,8 +326,81 @@ public class Renderer implements ApplicationListener{
|
|||||||
Events.fire(Trigger.postDraw);
|
Events.fire(Trigger.postDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawBackground(){
|
protected void drawBackground(){
|
||||||
//nothing to draw currently
|
//draw background only if there is no planet background with a skybox
|
||||||
|
if(state.rules.backgroundTexture != null && (state.rules.planetBackground == null || !state.rules.planetBackground.drawSkybox)){
|
||||||
|
if(!assets.isLoaded(state.rules.backgroundTexture, Texture.class)){
|
||||||
|
var file = assets.getFileHandleResolver().resolve(state.rules.backgroundTexture);
|
||||||
|
|
||||||
|
//don't draw invalid/non-existent backgrounds.
|
||||||
|
if(!file.exists() || !file.extEquals("png")){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var desc = assets.load(state.rules.backgroundTexture, Texture.class, new TextureParameter(){{
|
||||||
|
wrapU = wrapV = TextureWrap.mirroredRepeat;
|
||||||
|
magFilter = minFilter = TextureFilter.linear;
|
||||||
|
}});
|
||||||
|
|
||||||
|
assets.finishLoadingAsset(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture tex = assets.get(state.rules.backgroundTexture, Texture.class);
|
||||||
|
Tmp.tr1.set(tex);
|
||||||
|
Tmp.tr1.u = 0f;
|
||||||
|
Tmp.tr1.v = 0f;
|
||||||
|
|
||||||
|
float ratio = camera.width / camera.height;
|
||||||
|
float size = state.rules.backgroundScl;
|
||||||
|
|
||||||
|
Tmp.tr1.u2 = size;
|
||||||
|
Tmp.tr1.v2 = size / ratio;
|
||||||
|
|
||||||
|
float sx = 0f, sy = 0f;
|
||||||
|
|
||||||
|
if(!Mathf.zero(state.rules.backgroundSpeed)){
|
||||||
|
sx = (camera.position.x) / state.rules.backgroundSpeed;
|
||||||
|
sy = (camera.position.y) / state.rules.backgroundSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tmp.tr1.scroll(sx + state.rules.backgroundOffsetX, -sy + state.rules.backgroundOffsetY);
|
||||||
|
|
||||||
|
Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state.rules.planetBackground != null){
|
||||||
|
int size = Math.max(graphics.getWidth(), graphics.getHeight());
|
||||||
|
|
||||||
|
boolean resized = false;
|
||||||
|
if(backgroundBuffer == null){
|
||||||
|
resized = true;
|
||||||
|
backgroundBuffer = new FrameBuffer(size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(resized || backgroundBuffer.resizeCheck(size, size)){
|
||||||
|
backgroundBuffer.begin(Color.clear);
|
||||||
|
|
||||||
|
var params = state.rules.planetBackground;
|
||||||
|
|
||||||
|
//override some values
|
||||||
|
params.viewW = size;
|
||||||
|
params.viewH = size;
|
||||||
|
params.alwaysDrawAtmosphere = true;
|
||||||
|
params.drawUi = false;
|
||||||
|
|
||||||
|
planets.render(params);
|
||||||
|
|
||||||
|
backgroundBuffer.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
float drawSize = Math.max(camera.width, camera.height);
|
||||||
|
Draw.rect(Draw.wrap(backgroundBuffer.getTexture()), camera.position.x, camera.position.y, drawSize, -drawSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state.rules.customBackgroundCallback != null && customBackgrounds.containsKey(state.rules.customBackgroundCallback)){
|
||||||
|
customBackgrounds.get(state.rules.customBackgroundCallback).run();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateLandParticles(){
|
void updateLandParticles(){
|
||||||
|
|||||||
@@ -588,7 +588,7 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
if(mag >= 1_000_000_000){
|
if(mag >= 1_000_000_000){
|
||||||
return sign + Strings.fixed(mag / 1_000_000_000f, 1) + "[gray]" + billions+ "[]";
|
return sign + Strings.fixed(mag / 1_000_000_000f, 1) + "[gray]" + billions+ "[]";
|
||||||
}else if(mag >= 1_000_000){
|
}else if(mag >= 1_000_000){
|
||||||
return sign + Strings.fixed(mag / 1_000_000f, 1) + "[gray]" +millions + "[]";
|
return sign + Strings.fixed(mag / 1_000_000f, 1) + "[gray]" + millions + "[]";
|
||||||
}else if(mag >= 10_000){
|
}else if(mag >= 10_000){
|
||||||
return number / 1000 + "[gray]" + thousands + "[]";
|
return number / 1000 + "[gray]" + thousands + "[]";
|
||||||
}else if(mag >= 1000){
|
}else if(mag >= 1000){
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import arc.math.geom.Geometry.*;
|
|||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.noise.*;
|
import arc.util.noise.*;
|
||||||
|
import mindustry.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
@@ -246,15 +247,17 @@ public class World{
|
|||||||
if(sector.preset != null){
|
if(sector.preset != null){
|
||||||
sector.preset.generator.generate(tiles);
|
sector.preset.generator.generate(tiles);
|
||||||
sector.preset.rules.get(state.rules); //apply extra rules
|
sector.preset.rules.get(state.rules); //apply extra rules
|
||||||
}else{
|
}else if(sector.planet.generator != null){
|
||||||
sector.planet.generator.generate(tiles, sector);
|
sector.planet.generator.generate(tiles, sector);
|
||||||
|
}else{
|
||||||
|
throw new RuntimeException("Sector " + sector.id + " on planet " + sector.planet.name + " has no generator or preset defined. Provide a planet generator or preset map.");
|
||||||
}
|
}
|
||||||
//just in case
|
//just in case
|
||||||
state.rules.sector = sector;
|
state.rules.sector = sector;
|
||||||
});
|
});
|
||||||
|
|
||||||
//postgenerate for bases
|
//postgenerate for bases
|
||||||
if(sector.preset == null){
|
if(sector.preset == null && sector.planet.generator != null){
|
||||||
sector.planet.generator.postGenerate(tiles);
|
sector.planet.generator.postGenerate(tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,12 +480,14 @@ public class World{
|
|||||||
|
|
||||||
//TODO optimize; this is very slow and called too often!
|
//TODO optimize; this is very slow and called too often!
|
||||||
public float getDarkness(int x, int y){
|
public float getDarkness(int x, int y){
|
||||||
int edgeBlend = 2;
|
|
||||||
|
|
||||||
float dark = 0;
|
float dark = 0;
|
||||||
int edgeDst = Math.min(x, Math.min(y, Math.min(Math.abs(x - (tiles.width - 1)), Math.abs(y - (tiles.height - 1)))));
|
|
||||||
if(edgeDst <= edgeBlend){
|
if(Vars.state.rules.borderDarkness){
|
||||||
dark = Math.max((edgeBlend - edgeDst) * (4f / edgeBlend), dark);
|
int edgeBlend = 2;
|
||||||
|
int edgeDst = Math.min(x, Math.min(y, Math.min(Math.abs(x - (tiles.width - 1)), Math.abs(y - (tiles.height - 1)))));
|
||||||
|
if(edgeDst <= edgeBlend){
|
||||||
|
dark = Math.max((edgeBlend - edgeDst) * (4f / edgeBlend), dark);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.hasSector() && state.getSector().preset == null){
|
if(state.hasSector() && state.getSector().preset == null){
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import mindustry.*;
|
|||||||
import mindustry.mod.Mods.*;
|
import mindustry.mod.Mods.*;
|
||||||
|
|
||||||
/** Base class for a content type that is loaded in {@link mindustry.core.ContentLoader}. */
|
/** Base class for a content type that is loaded in {@link mindustry.core.ContentLoader}. */
|
||||||
public abstract class Content implements Comparable<Content>, Disposable{
|
public abstract class Content implements Comparable<Content>{
|
||||||
public short id;
|
public short id;
|
||||||
/** Info on which mod this content was loaded from. */
|
/** Info on which mod this content was loaded from. */
|
||||||
public ModContentInfo minfo = new ModContentInfo();
|
public ModContentInfo minfo = new ModContentInfo();
|
||||||
@@ -39,11 +39,6 @@ public abstract class Content implements Comparable<Content>, Disposable{
|
|||||||
return minfo.error != null;
|
return minfo.error != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose(){
|
|
||||||
//does nothing by default
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Content c){
|
public int compareTo(Content c){
|
||||||
return Integer.compare(id, c.id);
|
return Integer.compare(id, c.id);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public class Units{
|
|||||||
|
|
||||||
nearby(x, y, width, height, unit -> {
|
nearby(x, y, width, height, unit -> {
|
||||||
if(boolResult) return;
|
if(boolResult) return;
|
||||||
if((unit.isGrounded() && !unit.type.hovering) == ground){
|
if((unit.isGrounded() && !unit.hovering) == ground){
|
||||||
unit.hitboxTile(hitrect);
|
unit.hitboxTile(hitrect);
|
||||||
|
|
||||||
if(hitrect.overlaps(x, y, width, height)){
|
if(hitrect.overlaps(x, y, width, height)){
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import mindustry.gen.*;
|
|||||||
public abstract class Ability implements Cloneable{
|
public abstract class Ability implements Cloneable{
|
||||||
public void update(Unit unit){}
|
public void update(Unit unit){}
|
||||||
public void draw(Unit unit){}
|
public void draw(Unit unit){}
|
||||||
|
public void death(Unit unit){}
|
||||||
|
|
||||||
public Ability copy(){
|
public Ability copy(){
|
||||||
try{
|
try{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package mindustry.entities.comp;
|
package mindustry.entities.comp;
|
||||||
|
|
||||||
import arc.func.*;
|
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import mindustry.annotations.Annotations.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
import mindustry.world.blocks.environment.*;
|
import mindustry.world.blocks.environment.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -16,14 +17,16 @@ import static mindustry.Vars.*;
|
|||||||
abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
||||||
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
|
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
|
||||||
|
|
||||||
@Import float x, y, speedMultiplier;
|
@Import float x, y, speedMultiplier, hitSize;
|
||||||
@Import Vec2 vel;
|
@Import Vec2 vel;
|
||||||
|
@Import UnitType type;
|
||||||
|
|
||||||
@SyncLocal float elevation;
|
@SyncLocal float elevation;
|
||||||
private transient boolean wasFlying;
|
private transient boolean wasFlying;
|
||||||
transient boolean hovering;
|
transient boolean hovering;
|
||||||
transient float drownTime;
|
transient float drownTime;
|
||||||
transient float splashTimer;
|
transient float splashTimer;
|
||||||
|
transient @Nullable Floor lastDrownFloor;
|
||||||
|
|
||||||
boolean checkTarget(boolean targetAir, boolean targetGround){
|
boolean checkTarget(boolean targetAir, boolean targetGround){
|
||||||
return (isGrounded() && targetGround) || (isFlying() && targetAir);
|
return (isGrounded() && targetGround) || (isFlying() && targetAir);
|
||||||
@@ -41,6 +44,10 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
|||||||
return isGrounded() && !hovering;
|
return isGrounded() && !hovering;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable Floor drownFloor(){
|
||||||
|
return canDrown() ? floorOn() : null;
|
||||||
|
}
|
||||||
|
|
||||||
boolean emitWalkSound(){
|
boolean emitWalkSound(){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -90,20 +97,27 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(canDrown() && floor.isLiquid && floor.drownTime > 0){
|
updateDrowning();
|
||||||
drownTime += Time.delta / floor.drownTime;
|
}
|
||||||
drownTime = Mathf.clamp(drownTime);
|
|
||||||
|
public void updateDrowning(){
|
||||||
|
Floor floor = drownFloor();
|
||||||
|
|
||||||
|
if(floor != null && floor.isLiquid && floor.drownTime > 0){
|
||||||
|
lastDrownFloor = floor;
|
||||||
|
drownTime += Time.delta / floor.drownTime / type.drownTimeMultiplier;
|
||||||
if(Mathf.chanceDelta(0.05f)){
|
if(Mathf.chanceDelta(0.05f)){
|
||||||
floor.drownUpdateEffect.at(x, y, 1f, floor.mapColor);
|
floor.drownUpdateEffect.at(x, y, hitSize, floor.mapColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO is the netClient check necessary?
|
|
||||||
if(drownTime >= 0.999f && !net.client()){
|
if(drownTime >= 0.999f && !net.client()){
|
||||||
kill();
|
kill();
|
||||||
Events.fire(new UnitDrownEvent(self()));
|
Events.fire(new UnitDrownEvent(self()));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
drownTime -= Time.delta / 50f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drownTime = Mathf.clamp(drownTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import mindustry.annotations.Annotations.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.ui.*;
|
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
@EntityDef(value = LaunchCorec.class, serialize = false)
|
@EntityDef(value = LaunchCorec.class, serialize = false)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import mindustry.annotations.Annotations.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.EntityCollisions.*;
|
import mindustry.entities.EntityCollisions.*;
|
||||||
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
@@ -18,22 +19,30 @@ import mindustry.world.blocks.environment.*;
|
|||||||
abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
||||||
@Import float x, y;
|
@Import float x, y;
|
||||||
@Import UnitType type;
|
@Import UnitType type;
|
||||||
|
@Import Team team;
|
||||||
|
|
||||||
transient Leg[] legs = {};
|
transient Leg[] legs = {};
|
||||||
transient float totalLength;
|
transient float totalLength;
|
||||||
transient float moveSpace;
|
transient float moveSpace;
|
||||||
transient float baseRotation;
|
transient float baseRotation;
|
||||||
|
transient Floor lastDeepFloor;
|
||||||
|
|
||||||
@Replace
|
@Replace
|
||||||
@Override
|
@Override
|
||||||
public SolidPred solidity(){
|
public SolidPred solidity(){
|
||||||
return !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid;
|
return type.allowLegStep ? EntityCollisions::legsSolid : EntityCollisions::solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Replace
|
@Replace
|
||||||
public int pathType(){
|
public int pathType(){
|
||||||
return Pathfinder.costLegs;
|
return type.allowLegStep ? Pathfinder.costGround : Pathfinder.costLegs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Replace
|
||||||
|
public Floor drownFloor(){
|
||||||
|
return lastDeepFloor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -41,10 +50,18 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
|||||||
resetLegs();
|
resetLegs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unloaded(){
|
||||||
|
resetLegs(1f);
|
||||||
|
}
|
||||||
|
|
||||||
public void resetLegs(){
|
public void resetLegs(){
|
||||||
|
resetLegs(type.legLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetLegs(float legLength){
|
||||||
float rot = baseRotation;
|
float rot = baseRotation;
|
||||||
int count = type.legCount;
|
int count = type.legCount;
|
||||||
float legLength = type.legLength;
|
|
||||||
|
|
||||||
this.legs = new Leg[count];
|
this.legs = new Leg[count];
|
||||||
|
|
||||||
@@ -85,6 +102,9 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
|||||||
Vec2 moveOffset = Tmp.v4.trns(rot, trns);
|
Vec2 moveOffset = Tmp.v4.trns(rot, trns);
|
||||||
boolean moving = moving();
|
boolean moving = moving();
|
||||||
|
|
||||||
|
lastDeepFloor = null;
|
||||||
|
int deeps = 0;
|
||||||
|
|
||||||
for(int i = 0; i < legs.length; i++){
|
for(int i = 0; i < legs.length; i++){
|
||||||
float dstRot = legAngle(rot, i);
|
float dstRot = legAngle(rot, i);
|
||||||
Vec2 baseOffset = Tmp.v5.trns(dstRot, type.legBaseOffset).add(x, y);
|
Vec2 baseOffset = Tmp.v5.trns(dstRot, type.legBaseOffset).add(x, y);
|
||||||
@@ -105,11 +125,16 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
|||||||
l.moving = move;
|
l.moving = move;
|
||||||
l.stage = moving ? stageF % 1f : Mathf.lerpDelta(l.stage, 0f, 0.1f);
|
l.stage = moving ? stageF % 1f : Mathf.lerpDelta(l.stage, 0f, 0.1f);
|
||||||
|
|
||||||
|
Floor floor = Vars.world.floorWorld(l.base.x, l.base.y);
|
||||||
|
if(floor.isDeep()){
|
||||||
|
deeps ++;
|
||||||
|
lastDeepFloor = floor;
|
||||||
|
}
|
||||||
|
|
||||||
if(l.group != group){
|
if(l.group != group){
|
||||||
|
|
||||||
//create effect when transitioning to a group it can't move in
|
//create effect when transitioning to a group it can't move in
|
||||||
if(!move && i % div == l.group){
|
if(!move && i % div == l.group){
|
||||||
Floor floor = Vars.world.floorWorld(l.base.x, l.base.y);
|
|
||||||
if(floor.isLiquid){
|
if(floor.isLiquid){
|
||||||
floor.walkEffect.at(l.base.x, l.base.y, type.rippleScale, floor.mapColor);
|
floor.walkEffect.at(l.base.x, l.base.y, type.rippleScale, floor.mapColor);
|
||||||
floor.walkSound.at(x, y, 1f, floor.walkSoundVolume);
|
floor.walkSound.at(x, y, 1f, floor.walkSoundVolume);
|
||||||
@@ -123,7 +148,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(type.legSplashDamage > 0){
|
if(type.legSplashDamage > 0){
|
||||||
Damage.damage(team(), l.base.x, l.base.y, type.legSplashRange, type.legSplashDamage, false, true);
|
Damage.damage(team, l.base.x, l.base.y, type.legSplashRange, type.legSplashDamage, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +173,11 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
|
|||||||
|
|
||||||
l.joint.lerpDelta(jointDest, moveSpeed / 4f);
|
l.joint.lerpDelta(jointDest, moveSpeed / 4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//when at least 1 leg is touching land, it can't drown
|
||||||
|
if(deeps != legs.length){
|
||||||
|
lastDeepFloor = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return outwards facing angle of leg at the specified index. */
|
/** @return outwards facing angle of leg at the specified index. */
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import mindustry.entities.*;
|
|||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.environment.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -62,6 +63,21 @@ abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, Elevati
|
|||||||
walkExtension = extendScl;
|
walkExtension = extendScl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Replace
|
||||||
|
@Override
|
||||||
|
public @Nullable Floor drownFloor(){
|
||||||
|
//large mechs can only drown when all the nearby floors are deep
|
||||||
|
if(hitSize >= 12 && canDrown()){
|
||||||
|
for(Point2 p : Geometry.d8){
|
||||||
|
Floor f = world.floorWorld(x + p.x * tilesize, y + p.y * tilesize);
|
||||||
|
if(!f.isDeep()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return canDrown() ? floorOn() : null;
|
||||||
|
}
|
||||||
|
|
||||||
public float walkExtend(boolean scaled){
|
public float walkExtend(boolean scaled){
|
||||||
|
|
||||||
//now ranges from -maxExtension to maxExtension*3
|
//now ranges from -maxExtension to maxExtension*3
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import mindustry.entities.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.payloads.*;
|
import mindustry.world.blocks.payloads.*;
|
||||||
|
|
||||||
@@ -123,6 +122,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
|||||||
//decrement count to prevent double increment
|
//decrement count to prevent double increment
|
||||||
if(!u.isAdded()) u.team.data().updateCount(u.type, -1);
|
if(!u.isAdded()) u.team.data().updateCount(u.type, -1);
|
||||||
u.add();
|
u.add();
|
||||||
|
u.unloaded();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,12 +45,18 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
boolean spawnedByCore;
|
boolean spawnedByCore;
|
||||||
double flag;
|
double flag;
|
||||||
|
|
||||||
|
transient float shadowAlpha = -1f;
|
||||||
transient Seq<Ability> abilities = new Seq<>(0);
|
transient Seq<Ability> abilities = new Seq<>(0);
|
||||||
transient float healTime;
|
transient float healTime;
|
||||||
private transient float resupplyTime = Mathf.random(10f);
|
private transient float resupplyTime = Mathf.random(10f);
|
||||||
private transient boolean wasPlayer;
|
private transient boolean wasPlayer;
|
||||||
private transient boolean wasHealed;
|
private transient boolean wasHealed;
|
||||||
|
|
||||||
|
/** Called when this unit was unloaded from a factory or spawn point. */
|
||||||
|
public void unloaded(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** Move based on preferred unit movement type. */
|
/** Move based on preferred unit movement type. */
|
||||||
public void movePref(Vec2 movement){
|
public void movePref(Vec2 movement){
|
||||||
if(type.omniMovement){
|
if(type.omniMovement){
|
||||||
@@ -520,6 +526,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(abilities.size > 0){
|
||||||
|
for(Ability a : abilities){
|
||||||
|
a.death(self());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import arc.util.*;
|
|||||||
import arc.util.serialization.*;
|
import arc.util.serialization.*;
|
||||||
import arc.util.serialization.Json.*;
|
import arc.util.serialization.Json.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
import mindustry.graphics.g3d.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.type.Weather.*;
|
import mindustry.type.Weather.*;
|
||||||
@@ -117,8 +118,22 @@ public class Rules{
|
|||||||
public @Nullable String modeName;
|
public @Nullable String modeName;
|
||||||
/** Whether cores incinerate items when full, just like in the campaign. */
|
/** Whether cores incinerate items when full, just like in the campaign. */
|
||||||
public boolean coreIncinerates = false;
|
public boolean coreIncinerates = false;
|
||||||
|
/** If false, borders fade out into darkness. Only use with custom backgrounds!*/
|
||||||
|
public boolean borderDarkness = true;
|
||||||
/** special tags for additional info. */
|
/** special tags for additional info. */
|
||||||
public StringMap tags = new StringMap();
|
public StringMap tags = new StringMap();
|
||||||
|
/** Name of callback to call for background rendering in mods; see Renderer#addCustomBackground. Runs last. */
|
||||||
|
public @Nullable String customBackgroundCallback;
|
||||||
|
/** path to background texture with extension (e.g. "sprites/space.png")*/
|
||||||
|
public @Nullable String backgroundTexture;
|
||||||
|
/** background texture move speed scaling - bigger numbers mean slower movement. 0 to disable. */
|
||||||
|
public float backgroundSpeed = 27000f;
|
||||||
|
/** background texture scaling factor */
|
||||||
|
public float backgroundScl = 1f;
|
||||||
|
/** background UV offsets */
|
||||||
|
public float backgroundOffsetX = 0.1f, backgroundOffsetY = 0.1f;
|
||||||
|
/** Parameters for planet rendered in the background. Cannot be changed once a map is loaded. */
|
||||||
|
public @Nullable PlanetParams planetBackground;
|
||||||
|
|
||||||
/** Copies this ruleset exactly. Not efficient at all, do not use often. */
|
/** Copies this ruleset exactly. Not efficient at all, do not use often. */
|
||||||
public Rules copy(){
|
public Rules copy(){
|
||||||
@@ -140,6 +155,10 @@ public class Rules{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEnv(int env){
|
||||||
|
return (environment & env) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public float unitBuildSpeed(Team team){
|
public float unitBuildSpeed(Team team){
|
||||||
return unitBuildSpeedMultiplier * teams.get(team).unitBuildSpeedMultiplier;
|
return unitBuildSpeedMultiplier * teams.get(team).unitBuildSpeedMultiplier;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,10 +82,11 @@ public class Universe{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.hasSector()){
|
if(state.hasSector() && state.getSector().planet.updateLighting){
|
||||||
|
var planet = state.getSector().planet;
|
||||||
//update sector light
|
//update sector light
|
||||||
float light = state.getSector().getLight();
|
float light = state.getSector().getLight();
|
||||||
float alpha = Mathf.clamp(Mathf.map(light, 0f, 0.8f, 0.3f, 1f));
|
float alpha = Mathf.clamp(Mathf.map(light, planet.lightSrcFrom, planet.lightSrcTo, planet.lightDstFrom, planet.lightDstTo));
|
||||||
|
|
||||||
//assign and map so darkness is not 100% dark
|
//assign and map so darkness is not 100% dark
|
||||||
state.rules.ambientLight.a = 1f - alpha;
|
state.rules.ambientLight.a = 1f - alpha;
|
||||||
|
|||||||
@@ -10,27 +10,29 @@ public class IndexedRenderer implements Disposable{
|
|||||||
private static final int vsize = 5;
|
private static final int vsize = 5;
|
||||||
|
|
||||||
private final Shader program = new Shader(
|
private final Shader program = new Shader(
|
||||||
"attribute vec4 a_position;\n" +
|
"""
|
||||||
"attribute vec4 a_color;\n" +
|
attribute vec4 a_position;
|
||||||
"attribute vec2 a_texCoord0;\n" +
|
attribute vec4 a_color;
|
||||||
"uniform mat4 u_projTrans;\n" +
|
attribute vec2 a_texCoord0;
|
||||||
"varying vec4 v_color;\n" +
|
uniform mat4 u_projTrans;
|
||||||
"varying vec2 v_texCoords;\n" +
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
void main(){
|
||||||
|
v_color = a_color;
|
||||||
|
v_color.a = v_color.a * (255.0/254.0);
|
||||||
|
v_texCoords = a_texCoord0;
|
||||||
|
gl_Position = u_projTrans * a_position;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
|
||||||
"void main(){\n" +
|
"""
|
||||||
" v_color = a_color;\n" +
|
varying lowp vec4 v_color;
|
||||||
" v_color.a = v_color.a * (255.0/254.0);\n" +
|
varying vec2 v_texCoords;
|
||||||
" v_texCoords = a_texCoord0;\n" +
|
uniform sampler2D u_texture;
|
||||||
" gl_Position = u_projTrans * a_position;\n" +
|
void main(){
|
||||||
"}",
|
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
|
||||||
|
}
|
||||||
"varying lowp vec4 v_color;\n" +
|
"""
|
||||||
"varying vec2 v_texCoords;\n" +
|
|
||||||
"uniform sampler2D u_texture;\n" +
|
|
||||||
|
|
||||||
"void main(){\n" +
|
|
||||||
" gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n" +
|
|
||||||
"}"
|
|
||||||
);
|
);
|
||||||
private Mesh mesh;
|
private Mesh mesh;
|
||||||
private float[] tmpVerts = new float[vsize * 6];
|
private float[] tmpVerts = new float[vsize * 6];
|
||||||
|
|||||||
@@ -191,7 +191,10 @@ public class LightRenderer{
|
|||||||
|
|
||||||
Draw.color();
|
Draw.color();
|
||||||
buffer.begin(Color.clear);
|
buffer.begin(Color.clear);
|
||||||
|
Draw.sort(false);
|
||||||
Gl.blendEquationSeparate(Gl.funcAdd, Gl.max);
|
Gl.blendEquationSeparate(Gl.funcAdd, Gl.max);
|
||||||
|
//apparently necessary
|
||||||
|
Blending.normal.apply();
|
||||||
|
|
||||||
for(Runnable run : lights){
|
for(Runnable run : lights){
|
||||||
run.run();
|
run.run();
|
||||||
@@ -202,6 +205,7 @@ public class LightRenderer{
|
|||||||
Draw.rect(circleRegion, cir.x, cir.y, cir.radius * 2, cir.radius * 2);
|
Draw.rect(circleRegion, cir.x, cir.y, cir.radius * 2, cir.radius * 2);
|
||||||
}
|
}
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
|
Draw.sort(true);
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Gl.blendEquationSeparate(Gl.funcAdd, Gl.funcAdd);
|
Gl.blendEquationSeparate(Gl.funcAdd, Gl.funcAdd);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class Shaders{
|
|||||||
public static LightShader light;
|
public static LightShader light;
|
||||||
public static SurfaceShader water, mud, tar, slag, cryofluid, space, caustics;
|
public static SurfaceShader water, mud, tar, slag, cryofluid, space, caustics;
|
||||||
public static PlanetShader planet;
|
public static PlanetShader planet;
|
||||||
|
public static CloudShader clouds;
|
||||||
public static PlanetGridShader planetGrid;
|
public static PlanetGridShader planetGrid;
|
||||||
public static AtmosphereShader atmosphere;
|
public static AtmosphereShader atmosphere;
|
||||||
public static MeshShader mesh;
|
public static MeshShader mesh;
|
||||||
@@ -56,6 +57,7 @@ public class Shaders{
|
|||||||
// }
|
// }
|
||||||
//};
|
//};
|
||||||
planet = new PlanetShader();
|
planet = new PlanetShader();
|
||||||
|
clouds = new CloudShader();
|
||||||
planetGrid = new PlanetGridShader();
|
planetGrid = new PlanetGridShader();
|
||||||
atmosphere = new AtmosphereShader();
|
atmosphere = new AtmosphereShader();
|
||||||
unlit = new LoadShader("planet", "unlit");
|
unlit = new LoadShader("planet", "unlit");
|
||||||
@@ -94,6 +96,7 @@ public class Shaders{
|
|||||||
public Vec3 lightDir = new Vec3(1, 1, 1).nor();
|
public Vec3 lightDir = new Vec3(1, 1, 1).nor();
|
||||||
public Color ambientColor = Color.white.cpy();
|
public Color ambientColor = Color.white.cpy();
|
||||||
public Vec3 camDir = new Vec3();
|
public Vec3 camDir = new Vec3();
|
||||||
|
public Planet planet;
|
||||||
|
|
||||||
public PlanetShader(){
|
public PlanetShader(){
|
||||||
super("planet", "planet");
|
super("planet", "planet");
|
||||||
@@ -101,7 +104,7 @@ public class Shaders{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(){
|
public void apply(){
|
||||||
camDir.set(renderer.planets.cam.direction).rotate(Vec3.Y, renderer.planets.planet.getRotation());
|
camDir.set(renderer.planets.cam.direction).rotate(Vec3.Y, planet.getRotation());
|
||||||
|
|
||||||
setUniformf("u_lightdir", lightDir);
|
setUniformf("u_lightdir", lightDir);
|
||||||
setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b);
|
setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b);
|
||||||
@@ -109,6 +112,27 @@ public class Shaders{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CloudShader extends LoadShader{
|
||||||
|
public Vec3 lightDir = new Vec3(1, 1, 1).nor();
|
||||||
|
public Color ambientColor = Color.white.cpy();
|
||||||
|
public Vec3 camDir = new Vec3();
|
||||||
|
public float alpha = 1f;
|
||||||
|
public Planet planet;
|
||||||
|
|
||||||
|
public CloudShader(){
|
||||||
|
super("planet", "clouds");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(){
|
||||||
|
camDir.set(renderer.planets.cam.direction).rotate(Vec3.Y, planet.getRotation());
|
||||||
|
|
||||||
|
setUniformf("u_alpha", alpha);
|
||||||
|
setUniformf("u_lightdir", lightDir);
|
||||||
|
setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class MeshShader extends LoadShader{
|
public static class MeshShader extends LoadShader{
|
||||||
|
|
||||||
public MeshShader(){
|
public MeshShader(){
|
||||||
@@ -176,6 +200,7 @@ public class Shaders{
|
|||||||
public static class BlockBuildShader extends LoadShader{
|
public static class BlockBuildShader extends LoadShader{
|
||||||
public float progress;
|
public float progress;
|
||||||
public TextureRegion region = new TextureRegion();
|
public TextureRegion region = new TextureRegion();
|
||||||
|
public float time;
|
||||||
|
|
||||||
public BlockBuildShader(){
|
public BlockBuildShader(){
|
||||||
super("blockbuild", "default");
|
super("blockbuild", "default");
|
||||||
@@ -186,7 +211,7 @@ public class Shaders{
|
|||||||
setUniformf("u_progress", progress);
|
setUniformf("u_progress", progress);
|
||||||
setUniformf("u_uv", region.u, region.v);
|
setUniformf("u_uv", region.u, region.v);
|
||||||
setUniformf("u_uv2", region.u2, region.v2);
|
setUniformf("u_uv2", region.u2, region.v2);
|
||||||
setUniformf("u_time", Time.time);
|
setUniformf("u_time", time);
|
||||||
setUniformf("u_texsize", region.texture.width, region.texture.height);
|
setUniformf("u_texsize", region.texture.width, region.texture.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ public class Voronoi{
|
|||||||
private void clipLine(Edge e){
|
private void clipLine(Edge e){
|
||||||
float pxmin, pxmax, pymin, pymax;
|
float pxmin, pxmax, pymin, pymax;
|
||||||
Site s1, s2;
|
Site s1, s2;
|
||||||
float x1 = 0, x2 = 0, y1 = 0, y2 = 0;
|
float x1, x2, y1, y2;
|
||||||
|
|
||||||
x1 = e.reg[0].coord.x;
|
x1 = e.reg[0].coord.x;
|
||||||
x2 = e.reg[1].coord.x;
|
x2 = e.reg[1].coord.x;
|
||||||
|
|||||||
7
core/src/mindustry/graphics/g3d/GenericMesh.java
Normal file
7
core/src/mindustry/graphics/g3d/GenericMesh.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package mindustry.graphics.g3d;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
|
||||||
|
public interface GenericMesh{
|
||||||
|
void render(PlanetParams params, Mat3D projection, Mat3D transform);
|
||||||
|
}
|
||||||
@@ -15,8 +15,12 @@ public class HexMesh extends PlanetMesh{
|
|||||||
super(planet, MeshBuilder.buildHex(mesher, divisions, false, planet.radius, 0.2f), shader);
|
super(planet, MeshBuilder.buildHex(mesher, divisions, false, planet.radius, 0.2f), shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HexMesh(){
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preRender(){
|
public void preRender(PlanetParams params){
|
||||||
|
Shaders.planet.planet = planet;
|
||||||
Shaders.planet.lightDir.set(planet.solarSystem.position).sub(planet.position).rotate(Vec3.Y, planet.getRotation()).nor();
|
Shaders.planet.lightDir.set(planet.solarSystem.position).sub(planet.position).rotate(Vec3.Y, planet.getRotation()).nor();
|
||||||
Shaders.planet.ambientColor.set(planet.solarSystem.lightColor);
|
Shaders.planet.ambientColor.set(planet.solarSystem.lightColor);
|
||||||
}
|
}
|
||||||
|
|||||||
60
core/src/mindustry/graphics/g3d/HexSkyMesh.java
Normal file
60
core/src/mindustry/graphics/g3d/HexSkyMesh.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package mindustry.graphics.g3d;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.noise.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
public class HexSkyMesh extends PlanetMesh{
|
||||||
|
static Mat3D mat = new Mat3D();
|
||||||
|
|
||||||
|
public float speed = 0f;
|
||||||
|
|
||||||
|
public HexSkyMesh(Planet planet, int seed, float speed, float radius, int divisions, Color color, int octaves, float persistence, float scl, float thresh){
|
||||||
|
super(planet, MeshBuilder.buildHex(new HexMesher(){
|
||||||
|
@Override
|
||||||
|
public float getHeight(Vec3 position){
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getColor(Vec3 position){
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean skip(Vec3 position){
|
||||||
|
return Simplex.noise3d(planet.id + seed, octaves, persistence, scl, position.x, position.y * 3f, position.z) >= thresh;
|
||||||
|
}
|
||||||
|
}, divisions, false, planet.radius, radius), Shaders.clouds);
|
||||||
|
|
||||||
|
this.speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HexSkyMesh(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public float relRot(){
|
||||||
|
return Time.globalTime * speed / 40f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PlanetParams params, Mat3D projection, Mat3D transform){
|
||||||
|
preRender(params);
|
||||||
|
shader.bind();
|
||||||
|
shader.setUniformMatrix4("u_proj", projection.val);
|
||||||
|
shader.setUniformMatrix4("u_trans", mat.setToTranslation(planet.position).rotate(Vec3.Y, planet.getRotation() + relRot()).val);
|
||||||
|
shader.apply();
|
||||||
|
mesh.render(shader, Gl.triangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preRender(PlanetParams params){
|
||||||
|
Shaders.clouds.planet = planet;
|
||||||
|
Shaders.clouds.lightDir.set(planet.solarSystem.position).sub(planet.position).rotate(Vec3.Y, planet.getRotation() + relRot()).nor();
|
||||||
|
Shaders.clouds.ambientColor.set(planet.solarSystem.lightColor);
|
||||||
|
Shaders.clouds.alpha = 1f - params.uiAlpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
core/src/mindustry/graphics/g3d/MatMesh.java
Normal file
22
core/src/mindustry/graphics/g3d/MatMesh.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package mindustry.graphics.g3d;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
|
||||||
|
//TODO maybe this is a bad idea
|
||||||
|
/** A GenericMesh that wraps and applies an additional transform to a generic mesh. */
|
||||||
|
public class MatMesh implements GenericMesh{
|
||||||
|
private static final Mat3D tmp = new Mat3D();
|
||||||
|
|
||||||
|
GenericMesh mesh;
|
||||||
|
Mat3D mat;
|
||||||
|
|
||||||
|
public MatMesh(GenericMesh mesh, Mat3D mat){
|
||||||
|
this.mesh = mesh;
|
||||||
|
this.mat = mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PlanetParams params, Mat3D projection, Mat3D transform){
|
||||||
|
mesh.render(params, projection, tmp.set(transform).mul(mat));
|
||||||
|
}
|
||||||
|
}
|
||||||
18
core/src/mindustry/graphics/g3d/MultiMesh.java
Normal file
18
core/src/mindustry/graphics/g3d/MultiMesh.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package mindustry.graphics.g3d;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
|
||||||
|
public class MultiMesh implements GenericMesh{
|
||||||
|
GenericMesh[] meshes;
|
||||||
|
|
||||||
|
public MultiMesh(GenericMesh... meshes){
|
||||||
|
this.meshes = meshes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PlanetParams params, Mat3D projection, Mat3D transform){
|
||||||
|
for(var v : meshes){
|
||||||
|
v.render(params, projection, transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
core/src/mindustry/graphics/g3d/NoiseMesh.java
Normal file
43
core/src/mindustry/graphics/g3d/NoiseMesh.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package mindustry.graphics.g3d;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.util.noise.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
public class NoiseMesh extends HexMesh{
|
||||||
|
|
||||||
|
public NoiseMesh(Planet planet, int seed, int divisions, Color color, float radius, int octaves, float persistence, float scale, float mag){
|
||||||
|
this.planet = planet;
|
||||||
|
this.shader = Shaders.planet;
|
||||||
|
this.mesh = MeshBuilder.buildHex(new HexMesher(){
|
||||||
|
@Override
|
||||||
|
public float getHeight(Vec3 position){
|
||||||
|
return Simplex.noise3d(planet.id + seed, octaves, persistence, scale, 5f + position.x, 5f + position.y, 5f + position.z) * mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getColor(Vec3 position){
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}, divisions, false, radius, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Two-color variant. */
|
||||||
|
public NoiseMesh(Planet planet, int seed, int divisions, float radius, int octaves, float persistence, float scale, float mag, Color color1, Color color2, int coct, float cper, float cscl, float cthresh){
|
||||||
|
this.planet = planet;
|
||||||
|
this.shader = Shaders.planet;
|
||||||
|
this.mesh = MeshBuilder.buildHex(new HexMesher(){
|
||||||
|
@Override
|
||||||
|
public float getHeight(Vec3 position){
|
||||||
|
return Simplex.noise3d(planet.id + seed, octaves, persistence, scale, 5f + position.x, 5f + position.y, 5f + position.z) * mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getColor(Vec3 position){
|
||||||
|
return Simplex.noise3d(planet.id + seed + 1, coct, cper, cscl, 5f + position.x, 5f + position.y, 5f + position.z) > cthresh ? color2 : color1;
|
||||||
|
}
|
||||||
|
}, divisions, false, radius, 0.2f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -221,6 +221,8 @@ public class PlanetGrid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Ptile{
|
public static class Ptile{
|
||||||
|
public static final Ptile empty = new Ptile(0, 0);
|
||||||
|
|
||||||
public int id;
|
public int id;
|
||||||
public int edgeCount;
|
public int edgeCount;
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ package mindustry.graphics.g3d;
|
|||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.gl.*;
|
import arc.graphics.gl.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.util.*;
|
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
|
|
||||||
/** Defines a mesh that is rendered for a planet. Subclasses provide a mesh and a shader. */
|
/** Defines a mesh that is rendered for a planet. Subclasses provide a mesh and a shader. */
|
||||||
public abstract class PlanetMesh implements Disposable{
|
public abstract class PlanetMesh implements GenericMesh{
|
||||||
protected final Mesh mesh;
|
protected Mesh mesh;
|
||||||
protected final Planet planet;
|
protected Planet planet;
|
||||||
protected final Shader shader;
|
protected Shader shader;
|
||||||
|
|
||||||
public PlanetMesh(Planet planet, Mesh mesh, Shader shader){
|
public PlanetMesh(Planet planet, Mesh mesh, Shader shader){
|
||||||
this.planet = planet;
|
this.planet = planet;
|
||||||
@@ -18,20 +17,21 @@ public abstract class PlanetMesh implements Disposable{
|
|||||||
this.shader = shader;
|
this.shader = shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Should be overridden to set up any shader parameters such as planet position, normals, etc. */
|
public PlanetMesh(){}
|
||||||
public abstract void preRender();
|
|
||||||
|
|
||||||
public void render(Mat3D projection, Mat3D transform){
|
/** Should be overridden to set up any shader parameters such as planet position, normals, etc.
|
||||||
preRender();
|
* @param params*/
|
||||||
|
public void preRender(PlanetParams params){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PlanetParams params, Mat3D projection, Mat3D transform){
|
||||||
|
preRender(params);
|
||||||
shader.bind();
|
shader.bind();
|
||||||
shader.setUniformMatrix4("u_proj", projection.val);
|
shader.setUniformMatrix4("u_proj", projection.val);
|
||||||
shader.setUniformMatrix4("u_trans", transform.val);
|
shader.setUniformMatrix4("u_trans", transform.val);
|
||||||
shader.apply();
|
shader.apply();
|
||||||
mesh.render(shader, Gl.triangles);
|
mesh.render(shader, Gl.triangles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose(){
|
|
||||||
mesh.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
40
core/src/mindustry/graphics/g3d/PlanetParams.java
Normal file
40
core/src/mindustry/graphics/g3d/PlanetParams.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package mindustry.graphics.g3d;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.graphics.g3d.PlanetRenderer.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
/** Parameters for rendering a solar system. */
|
||||||
|
public class PlanetParams{
|
||||||
|
/** Camera direction relative to the planet. Length is determined by zoom. */
|
||||||
|
public Vec3 camPos = new Vec3(0f, 0f, 4f);
|
||||||
|
/** Camera up vector. */
|
||||||
|
public Vec3 camUp = new Vec3(0f, 1f, 0f);
|
||||||
|
/** the unit length direction vector of the camera **/
|
||||||
|
public Vec3 camDir = new Vec3(0, 0, -1);
|
||||||
|
/** The sun/main planet of the solar system from which everything is rendered. */
|
||||||
|
public Planet solarSystem = Planets.sun;
|
||||||
|
/** Planet being looked at. */
|
||||||
|
public Planet planet = Planets.serpulo;
|
||||||
|
/** Zoom relative to planet. */
|
||||||
|
public float zoom = 1f;
|
||||||
|
/** Alpha of orbit rings and other UI elements. */
|
||||||
|
public float uiAlpha = 1f;
|
||||||
|
/** If false, orbit and sector grid are not drawn. */
|
||||||
|
public boolean drawUi = false;
|
||||||
|
/** If true, a space skybox is drawn. */
|
||||||
|
public boolean drawSkybox = true;
|
||||||
|
|
||||||
|
/** Handles drawing details. */
|
||||||
|
public @Nullable transient PlanetInterfaceRenderer renderer;
|
||||||
|
/** Viewport size. <=0 to use screen size. Do not change in rules. */
|
||||||
|
public transient int viewW = -1, viewH = -1;
|
||||||
|
/** If true, atmosphere will be drawn regardless of player options. */
|
||||||
|
public transient boolean alwaysDrawAtmosphere = false;
|
||||||
|
|
||||||
|
//TODO:
|
||||||
|
//- blur
|
||||||
|
//- darken
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ import arc.math.*;
|
|||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.graphics.g3d.PlanetGrid.*;
|
import mindustry.graphics.g3d.PlanetGrid.*;
|
||||||
@@ -25,25 +24,15 @@ public class PlanetRenderer implements Disposable{
|
|||||||
|
|
||||||
private static final Seq<Vec3> points = new Seq<>();
|
private static final Seq<Vec3> points = new Seq<>();
|
||||||
|
|
||||||
/** Camera direction relative to the planet. Length is determined by zoom. */
|
|
||||||
public final Vec3 camPos = new Vec3();
|
|
||||||
/** The sun/main planet of the solar system from which everything is rendered. */
|
|
||||||
public final Planet solarSystem = Planets.sun;
|
|
||||||
/** Planet being looked at. */
|
|
||||||
public Planet planet = Planets.serpulo;
|
|
||||||
/** Camera used for rendering. */
|
/** Camera used for rendering. */
|
||||||
public Camera3D cam = new Camera3D();
|
public final Camera3D cam = new Camera3D();
|
||||||
/** Raw vertex batch. */
|
/** Raw vertex batch. */
|
||||||
public final VertexBatch3D batch = new VertexBatch3D(20000, false, true, 0);
|
public final VertexBatch3D batch = new VertexBatch3D(20000, false, true, 0);
|
||||||
|
|
||||||
public float zoom = 1f;
|
|
||||||
public float orbitAlpha = 1f;
|
|
||||||
|
|
||||||
private final Mesh[] outlines = new Mesh[10];
|
private final Mesh[] outlines = new Mesh[10];
|
||||||
public final PlaneBatch3D projector = new PlaneBatch3D();
|
public final PlaneBatch3D projector = new PlaneBatch3D();
|
||||||
public final Mat3D mat = new Mat3D();
|
public final Mat3D mat = new Mat3D();
|
||||||
public final FrameBuffer buffer = new FrameBuffer(2, 2, true);
|
public final FrameBuffer buffer = new FrameBuffer(2, 2, true);
|
||||||
public PlanetInterfaceRenderer irenderer;
|
|
||||||
|
|
||||||
public final Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false){{
|
public final Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false){{
|
||||||
setThreshold(0.8f);
|
setThreshold(0.8f);
|
||||||
@@ -55,16 +44,13 @@ public class PlanetRenderer implements Disposable{
|
|||||||
public final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/"));
|
public final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/"));
|
||||||
|
|
||||||
public PlanetRenderer(){
|
public PlanetRenderer(){
|
||||||
camPos.set(0, 0f, camLength);
|
|
||||||
projector.setScaling(1f / 150f);
|
projector.setScaling(1f / 150f);
|
||||||
cam.fov = 60f;
|
cam.fov = 60f;
|
||||||
cam.far = 150f;
|
cam.far = 150f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Render the entire planet scene to the screen. */
|
/** Render the entire planet scene to the screen. */
|
||||||
public void render(PlanetInterfaceRenderer irenderer){
|
public void render(PlanetParams params){
|
||||||
this.irenderer = irenderer;
|
|
||||||
|
|
||||||
Draw.flush();
|
Draw.flush();
|
||||||
Gl.clear(Gl.depthBufferBit);
|
Gl.clear(Gl.depthBufferBit);
|
||||||
Gl.enable(Gl.depthTest);
|
Gl.enable(Gl.depthTest);
|
||||||
@@ -73,49 +59,63 @@ public class PlanetRenderer implements Disposable{
|
|||||||
Gl.enable(Gl.cullFace);
|
Gl.enable(Gl.cullFace);
|
||||||
Gl.cullFace(Gl.back);
|
Gl.cullFace(Gl.back);
|
||||||
|
|
||||||
|
int w = params.viewW <= 0 ? Core.graphics.getWidth() : params.viewW;
|
||||||
|
int h = params.viewH <= 0 ? Core.graphics.getHeight() : params.viewH;
|
||||||
|
|
||||||
|
bloom.blending = !params.drawSkybox;
|
||||||
|
|
||||||
//lock to up vector so it doesn't get confusing
|
//lock to up vector so it doesn't get confusing
|
||||||
cam.up.set(Vec3.Y);
|
cam.up.set(Vec3.Y);
|
||||||
|
|
||||||
cam.resize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
cam.resize(w, h);
|
||||||
camPos.setLength(planet.radius * camLength + (zoom-1f) * planet.radius * 2);
|
params.camPos.setLength((params.planet.radius + params.planet.camRadius) * camLength + (params.zoom-1f) * (params.planet.radius + params.planet.camRadius) * 2);
|
||||||
cam.position.set(planet.position).add(camPos);
|
cam.position.set(params.planet.position).add(params.camPos);
|
||||||
cam.lookAt(planet.position);
|
//cam.up.set(params.camUp); //TODO broken
|
||||||
|
cam.lookAt(params.planet.position);
|
||||||
cam.update();
|
cam.update();
|
||||||
|
//write back once it changes.
|
||||||
|
params.camUp.set(cam.up);
|
||||||
|
params.camDir.set(cam.direction);
|
||||||
|
|
||||||
projector.proj(cam.combined);
|
projector.proj(cam.combined);
|
||||||
batch.proj(cam.combined);
|
batch.proj(cam.combined);
|
||||||
|
|
||||||
Events.fire(Trigger.universeDrawBegin);
|
Events.fire(Trigger.universeDrawBegin);
|
||||||
|
|
||||||
beginBloom();
|
//begin bloom
|
||||||
|
bloom.resize(w, h);
|
||||||
|
bloom.capture();
|
||||||
|
|
||||||
//render skybox at 0,0,0
|
if(params.drawSkybox){
|
||||||
Vec3 lastPos = Tmp.v31.set(cam.position);
|
//render skybox at 0,0,0
|
||||||
cam.position.setZero();
|
Vec3 lastPos = Tmp.v31.set(cam.position);
|
||||||
cam.update();
|
cam.position.setZero();
|
||||||
|
cam.update();
|
||||||
|
|
||||||
Gl.depthMask(false);
|
Gl.depthMask(false);
|
||||||
|
|
||||||
skybox.render(cam.combined);
|
skybox.render(cam.combined);
|
||||||
|
|
||||||
Gl.depthMask(true);
|
Gl.depthMask(true);
|
||||||
|
|
||||||
cam.position.set(lastPos);
|
cam.position.set(lastPos);
|
||||||
cam.update();
|
cam.update();
|
||||||
|
}
|
||||||
|
|
||||||
Events.fire(Trigger.universeDraw);
|
Events.fire(Trigger.universeDraw);
|
||||||
|
|
||||||
renderPlanet(solarSystem);
|
renderPlanet(params.solarSystem, params);
|
||||||
|
renderTransparent(params.solarSystem, params);
|
||||||
|
|
||||||
renderTransparent(solarSystem);
|
bloom.render();
|
||||||
|
|
||||||
endBloom();
|
|
||||||
|
|
||||||
Events.fire(Trigger.universeDrawEnd);
|
Events.fire(Trigger.universeDrawEnd);
|
||||||
|
|
||||||
Gl.enable(Gl.blend);
|
Gl.enable(Gl.blend);
|
||||||
|
|
||||||
irenderer.renderProjections(planet);
|
if(params.renderer != null){
|
||||||
|
params.renderer.renderProjections(params.planet);
|
||||||
|
}
|
||||||
|
|
||||||
Gl.disable(Gl.cullFace);
|
Gl.disable(Gl.cullFace);
|
||||||
Gl.disable(Gl.depthTest);
|
Gl.disable(Gl.depthTest);
|
||||||
@@ -123,68 +123,64 @@ public class PlanetRenderer implements Disposable{
|
|||||||
cam.update();
|
cam.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginBloom(){
|
public void renderPlanet(Planet planet, PlanetParams params){
|
||||||
bloom.resize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
|
||||||
bloom.capture();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endBloom(){
|
|
||||||
bloom.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void renderPlanet(Planet planet){
|
|
||||||
if(!planet.visible()) return;
|
if(!planet.visible()) return;
|
||||||
|
|
||||||
cam.update();
|
cam.update();
|
||||||
|
|
||||||
if(cam.frustum.containsSphere(planet.position, planet.clipRadius)){
|
if(cam.frustum.containsSphere(planet.position, planet.clipRadius)){
|
||||||
//render planet at offsetted position in the world
|
//render planet at offsetted position in the world
|
||||||
planet.draw(cam.combined, planet.getTransform(mat));
|
planet.draw(params, cam.combined, planet.getTransform(mat));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderOrbit(planet);
|
|
||||||
|
|
||||||
for(Planet child : planet.children){
|
for(Planet child : planet.children){
|
||||||
renderPlanet(child);
|
renderPlanet(child, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderTransparent(Planet planet){
|
public void renderTransparent(Planet planet, PlanetParams params){
|
||||||
if(!planet.visible()) return;
|
if(!planet.visible()) return;
|
||||||
|
|
||||||
if(planet.hasGrid() && planet == this.planet){
|
planet.drawClouds(params, cam.combined, planet.getTransform(mat));
|
||||||
renderSectors(planet);
|
|
||||||
|
if(planet.hasGrid() && planet == params.planet && params.drawUi){
|
||||||
|
renderSectors(planet, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cam.frustum.containsSphere(planet.position, planet.clipRadius) && planet.parent != null && planet.hasAtmosphere && Core.settings.getBool("atmosphere")){
|
if(cam.frustum.containsSphere(planet.position, planet.clipRadius) && planet.parent != null && planet.hasAtmosphere && (params.alwaysDrawAtmosphere || Core.settings.getBool("atmosphere"))){
|
||||||
planet.drawAtmosphere(atmosphere, cam);
|
planet.drawAtmosphere(atmosphere, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
planet.drawClouds(cam.combined, planet.getTransform(mat));
|
|
||||||
|
|
||||||
for(Planet child : planet.children){
|
for(Planet child : planet.children){
|
||||||
renderTransparent(child);
|
renderTransparent(child, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.proj(cam.combined);
|
||||||
|
|
||||||
|
if(params.drawUi){
|
||||||
|
renderOrbit(planet, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderOrbit(Planet planet){
|
public void renderOrbit(Planet planet, PlanetParams params){
|
||||||
if(planet.parent == null || !planet.visible() || orbitAlpha <= 0.02f) return;
|
if(planet.parent == null || !planet.visible() || params.uiAlpha <= 0.02f || !planet.drawOrbit) return;
|
||||||
|
|
||||||
Vec3 center = planet.parent.position;
|
Vec3 center = planet.parent.position;
|
||||||
float radius = planet.orbitRadius;
|
float radius = planet.orbitRadius;
|
||||||
int points = (int)(radius * 10);
|
int points = (int)(radius * 10);
|
||||||
Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray.write(Tmp.c1).a(orbitAlpha)));
|
Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray.write(Tmp.c1).a(params.uiAlpha)));
|
||||||
batch.flush(Gl.lineLoop);
|
batch.flush(Gl.lineLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderSectors(Planet planet){
|
public void renderSectors(Planet planet, PlanetParams params){
|
||||||
if(orbitAlpha <= 0.02f) return;
|
if(params.uiAlpha <= 0.02f) return;
|
||||||
|
|
||||||
//apply transformed position
|
//apply transformed position
|
||||||
batch.proj().mul(planet.getTransform(mat));
|
batch.proj().mul(planet.getTransform(mat));
|
||||||
|
|
||||||
irenderer.renderSectors(planet);
|
if(params.renderer != null){
|
||||||
|
params.renderer.renderSectors(planet);
|
||||||
|
}
|
||||||
|
|
||||||
//render sector grid
|
//render sector grid
|
||||||
Mesh mesh = outline(planet.grid.size);
|
Mesh mesh = outline(planet.grid.size);
|
||||||
@@ -262,12 +258,12 @@ public class PlanetRenderer implements Disposable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPlane(Sector sector){
|
public void setPlane(Sector sector){
|
||||||
float rotation = -planet.getRotation();
|
float rotation = -sector.planet.getRotation();
|
||||||
float length = 0.01f;
|
float length = 0.01f;
|
||||||
|
|
||||||
projector.setPlane(
|
projector.setPlane(
|
||||||
//origin on sector position
|
//origin on sector position
|
||||||
Tmp.v33.set(sector.tile.v).setLength(outlineRad + length).rotate(Vec3.Y, rotation).add(planet.position),
|
Tmp.v33.set(sector.tile.v).setLength(outlineRad + length).rotate(Vec3.Y, rotation).add(sector.planet.position),
|
||||||
//face up
|
//face up
|
||||||
sector.plane.project(Tmp.v32.set(sector.tile.v).add(Vec3.Y)).sub(sector.tile.v).rotate(Vec3.Y, rotation).nor(),
|
sector.plane.project(Tmp.v32.set(sector.tile.v).add(Vec3.Y)).sub(sector.tile.v).rotate(Vec3.Y, rotation).nor(),
|
||||||
//right vector
|
//right vector
|
||||||
|
|||||||
@@ -8,9 +8,4 @@ public class ShaderSphereMesh extends PlanetMesh{
|
|||||||
public ShaderSphereMesh(Planet planet, Shader shader, int divisions){
|
public ShaderSphereMesh(Planet planet, Shader shader, int divisions){
|
||||||
super(planet, MeshBuilder.buildIcosphere(divisions, planet.radius), shader);
|
super(planet, MeshBuilder.buildIcosphere(divisions, planet.radius), shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preRender(){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,4 @@ public class SunMesh extends HexMesh{
|
|||||||
}
|
}
|
||||||
}, divisions, Shaders.unlit);
|
}, divisions, Shaders.unlit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preRender(){
|
|
||||||
//do absolutely nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,6 +163,19 @@ public class JsonIO{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
json.setSerializer(Planet.class, new Serializer<>(){
|
||||||
|
@Override
|
||||||
|
public void write(Json json, Planet object, Class knownType){
|
||||||
|
json.writeValue(object.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Planet read(Json json, JsonValue jsonData, Class type){
|
||||||
|
Planet block = Vars.content.getByName(ContentType.planet, jsonData.asString());
|
||||||
|
return block == null ? Planets.serpulo : block;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
json.setSerializer(Weather.class, new Serializer<>(){
|
json.setSerializer(Weather.class, new Serializer<>(){
|
||||||
@Override
|
@Override
|
||||||
public void write(Json json, Weather object, Class knownType){
|
public void write(Json json, Weather object, Class knownType){
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ public abstract class SaveFileReader{
|
|||||||
"water", "shallow-water",
|
"water", "shallow-water",
|
||||||
"slag", "molten-slag",
|
"slag", "molten-slag",
|
||||||
|
|
||||||
"cryofluidmixer", "cryofluid-mixer"
|
"cryofluidmixer", "cryofluid-mixer",
|
||||||
|
"block-forge", "constructor",
|
||||||
|
"block-unloader", "payload-unloader",
|
||||||
|
"block-loader", "payload-loader"
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final ObjectMap<String, String> modContentNameMap = ObjectMap.of(
|
public static final ObjectMap<String, String> modContentNameMap = ObjectMap.of(
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
|
|||||||
return 3200;
|
return 3200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSectorSize(Sector sector){
|
||||||
|
int res = (int)(sector.rect.radius * getSizeScl());
|
||||||
|
return res % 2 == 0 ? res : res + 1;
|
||||||
|
}
|
||||||
|
|
||||||
public void generate(Tiles tiles, Sector sec){
|
public void generate(Tiles tiles, Sector sec){
|
||||||
this.tiles = tiles;
|
this.tiles = tiles;
|
||||||
this.sector = sec;
|
this.sector = sec;
|
||||||
|
|||||||
@@ -218,14 +218,8 @@ public class ClassMap{
|
|||||||
classes.put("SwitchBuild", mindustry.world.blocks.logic.SwitchBlock.SwitchBuild.class);
|
classes.put("SwitchBuild", mindustry.world.blocks.logic.SwitchBlock.SwitchBuild.class);
|
||||||
classes.put("BallisticSilo", mindustry.world.blocks.payloads.BallisticSilo.class);
|
classes.put("BallisticSilo", mindustry.world.blocks.payloads.BallisticSilo.class);
|
||||||
classes.put("BallisticSiloBuild", mindustry.world.blocks.payloads.BallisticSilo.BallisticSiloBuild.class);
|
classes.put("BallisticSiloBuild", mindustry.world.blocks.payloads.BallisticSilo.BallisticSiloBuild.class);
|
||||||
classes.put("BlockForge", mindustry.world.blocks.payloads.BlockForge.class);
|
|
||||||
classes.put("BlockForgeBuild", mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild.class);
|
|
||||||
classes.put("BlockLoader", mindustry.world.blocks.payloads.BlockLoader.class);
|
|
||||||
classes.put("BlockLoaderBuild", mindustry.world.blocks.payloads.BlockLoader.BlockLoaderBuild.class);
|
|
||||||
classes.put("BlockProducer", mindustry.world.blocks.payloads.BlockProducer.class);
|
classes.put("BlockProducer", mindustry.world.blocks.payloads.BlockProducer.class);
|
||||||
classes.put("BlockProducerBuild", mindustry.world.blocks.payloads.BlockProducer.BlockProducerBuild.class);
|
classes.put("BlockProducerBuild", mindustry.world.blocks.payloads.BlockProducer.BlockProducerBuild.class);
|
||||||
classes.put("BlockUnloader", mindustry.world.blocks.payloads.BlockUnloader.class);
|
|
||||||
classes.put("BlockUnloaderBuild", mindustry.world.blocks.payloads.BlockUnloader.BlockUnloaderBuild.class);
|
|
||||||
classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class);
|
classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class);
|
||||||
classes.put("NuclearWarhead", mindustry.world.blocks.payloads.NuclearWarhead.class);
|
classes.put("NuclearWarhead", mindustry.world.blocks.payloads.NuclearWarhead.class);
|
||||||
classes.put("NuclearWarheadBuild", mindustry.world.blocks.payloads.NuclearWarhead.NuclearWarheadBuild.class);
|
classes.put("NuclearWarheadBuild", mindustry.world.blocks.payloads.NuclearWarhead.NuclearWarheadBuild.class);
|
||||||
|
|||||||
@@ -55,6 +55,21 @@ public class ItemSeq implements Iterable<ItemStack>, JsonSerializable{
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemStack[] toArray(){
|
||||||
|
int count = 0;
|
||||||
|
for(int value : values){
|
||||||
|
if(value != 0) count++;
|
||||||
|
}
|
||||||
|
ItemStack[] result = new ItemStack[count];
|
||||||
|
int index = 0;
|
||||||
|
for(int i = 0; i < values.length; i++){
|
||||||
|
if(values[i] != 0){
|
||||||
|
result[index ++] = new ItemStack(Vars.content.item(i), values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public void min(int number){
|
public void min(int number){
|
||||||
for(Item item : Vars.content.items()){
|
for(Item item : Vars.content.items()){
|
||||||
set(item, Math.min(get(item), number));
|
set(item, Math.min(get(item), number));
|
||||||
@@ -90,6 +105,12 @@ public class ItemSeq implements Iterable<ItemStack>, JsonSerializable{
|
|||||||
itemModule.each(this::add);
|
itemModule.each(this::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void add(ItemStack[] stacks){
|
||||||
|
for(var s : stacks){
|
||||||
|
add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void add(ItemSeq seq){
|
public void add(ItemSeq seq){
|
||||||
seq.each(this::add);
|
seq.each(this::add);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,12 @@ import mindustry.maps.generators.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class Planet extends UnlockableContent{
|
public class Planet extends UnlockableContent{
|
||||||
/** Default spacing between planet orbits in world units. */
|
|
||||||
private static final float orbitSpacing = 11f;
|
|
||||||
/** intersect() temp var. */
|
/** intersect() temp var. */
|
||||||
private static final Vec3 intersectResult = new Vec3();
|
private static final Vec3 intersectResult = new Vec3();
|
||||||
/** Mesh used for rendering. Created on load() - will be null on the server! */
|
/** Mesh used for rendering. Created on load() - will be null on the server! */
|
||||||
public @Nullable PlanetMesh mesh;
|
public @Nullable GenericMesh mesh;
|
||||||
/** Mesh used for rendering planet clouds. Null if no clouds are present. */
|
/** Mesh used for rendering planet clouds. Null if no clouds are present. */
|
||||||
public @Nullable PlanetMesh cloudMesh;
|
public @Nullable GenericMesh cloudMesh;
|
||||||
/** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */
|
/** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */
|
||||||
public Vec3 position = new Vec3();
|
public Vec3 position = new Vec3();
|
||||||
/** Grid used for the sectors on the planet. Null if this planet can't be landed on. */
|
/** Grid used for the sectors on the planet. Null if this planet can't be landed on. */
|
||||||
@@ -33,9 +31,17 @@ public class Planet extends UnlockableContent{
|
|||||||
/** Generator that will make the planet. Can be null for planets that don't need to be landed on. */
|
/** Generator that will make the planet. Can be null for planets that don't need to be landed on. */
|
||||||
public @Nullable PlanetGenerator generator;
|
public @Nullable PlanetGenerator generator;
|
||||||
/** Array of sectors; directly maps to tiles in the grid. */
|
/** Array of sectors; directly maps to tiles in the grid. */
|
||||||
public Seq<Sector> sectors;
|
public Seq<Sector> sectors = new Seq<>();
|
||||||
|
/** Default spacing between planet orbits in world units. This is defined per-parent! */
|
||||||
|
public float orbitSpacing = 12f;
|
||||||
/** Radius of this planet's sphere. Does not take into account satellites. */
|
/** Radius of this planet's sphere. Does not take into account satellites. */
|
||||||
public float radius;
|
public float radius;
|
||||||
|
/** Camera radius offset. */
|
||||||
|
public float camRadius;
|
||||||
|
/** Minimum camera zoom value. */
|
||||||
|
public float minZoom = 0.5f;
|
||||||
|
/** Whether to draw the orbital circle. */
|
||||||
|
public boolean drawOrbit = true;
|
||||||
/** Atmosphere radius adjustment parameters. */
|
/** Atmosphere radius adjustment parameters. */
|
||||||
public float atmosphereRadIn = 0, atmosphereRadOut = 0.3f;
|
public float atmosphereRadIn = 0, atmosphereRadOut = 0.3f;
|
||||||
/** Frustrum sphere clip radius. */
|
/** Frustrum sphere clip radius. */
|
||||||
@@ -48,12 +54,18 @@ public class Planet extends UnlockableContent{
|
|||||||
public float orbitTime;
|
public float orbitTime;
|
||||||
/** Time for the planet to perform a full revolution, in seconds. One day. */
|
/** Time for the planet to perform a full revolution, in seconds. One day. */
|
||||||
public float rotateTime = 24f * 60f;
|
public float rotateTime = 24f * 60f;
|
||||||
|
/** Random orbit angle offset to prevent planets from starting out in a line. */
|
||||||
|
public float orbitOffset;
|
||||||
/** Approx. radius of one sector. */
|
/** Approx. radius of one sector. */
|
||||||
public float sectorApproxRadius;
|
public float sectorApproxRadius;
|
||||||
/** Whether this planet is tidally locked relative to its parent - see https://en.wikipedia.org/wiki/Tidal_locking */
|
/** Whether this planet is tidally locked relative to its parent - see https://en.wikipedia.org/wiki/Tidal_locking */
|
||||||
public boolean tidalLock = false;
|
public boolean tidalLock = false;
|
||||||
/** Whether this planet is listed in the planet access UI. **/
|
/** Whether this planet is listed in the planet access UI. **/
|
||||||
public boolean accessible = true;
|
public boolean accessible = true;
|
||||||
|
/** If true, a day/night cycle is simulated. */
|
||||||
|
public boolean updateLighting = true;
|
||||||
|
/** Day/night cycle parameters. */
|
||||||
|
public float lightSrcFrom = 0f, lightSrcTo = 0.8f, lightDstFrom = 0.2f, lightDstTo = 1f;
|
||||||
/** The default starting sector displayed to the map dialog. */
|
/** The default starting sector displayed to the map dialog. */
|
||||||
public int startSector = 0;
|
public int startSector = 0;
|
||||||
/** Whether the bloom render effect is enabled. */
|
/** Whether the bloom render effect is enabled. */
|
||||||
@@ -77,32 +89,20 @@ public class Planet extends UnlockableContent{
|
|||||||
/** Satellites orbiting this planet. */
|
/** Satellites orbiting this planet. */
|
||||||
public Seq<Satellite> satellites = new Seq<>();
|
public Seq<Satellite> satellites = new Seq<>();
|
||||||
/** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */
|
/** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */
|
||||||
protected Prov<PlanetMesh> meshLoader = () -> new ShaderSphereMesh(this, Shaders.unlit, 2), cloudMeshLoader = () -> null;
|
protected Prov<GenericMesh> meshLoader = () -> new ShaderSphereMesh(this, Shaders.unlit, 2), cloudMeshLoader = () -> null;
|
||||||
|
|
||||||
public Planet(String name, Planet parent, int sectorSize, float radius){
|
public Planet(String name, Planet parent, float radius){
|
||||||
super(name);
|
super(name);
|
||||||
|
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
this.orbitOffset = Mathf.randomSeed(id, 360);
|
||||||
if(sectorSize > 0){
|
|
||||||
grid = PlanetGrid.create(sectorSize);
|
|
||||||
|
|
||||||
sectors = new Seq<>(grid.tiles.length);
|
|
||||||
for(int i = 0; i < grid.tiles.length; i++){
|
|
||||||
sectors.add(new Sector(this, grid.tiles[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
sectorApproxRadius = sectors.first().tile.v.dst(sectors.first().tile.corners[0].v);
|
|
||||||
}else{
|
|
||||||
sectors = new Seq<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//total radius is initially just the radius
|
//total radius is initially just the radius
|
||||||
totalRadius += radius;
|
totalRadius = radius;
|
||||||
|
|
||||||
//get orbit radius by extending past the parent's total radius
|
//get orbit radius by extending past the parent's total radius
|
||||||
orbitRadius = parent == null ? 0f : (parent.totalRadius + orbitSpacing + totalRadius);
|
orbitRadius = parent == null ? 0f : (parent.totalRadius + parent.orbitSpacing + totalRadius);
|
||||||
|
|
||||||
//orbit time is based on radius [kepler's third law]
|
//orbit time is based on radius [kepler's third law]
|
||||||
orbitTime = Mathf.pow(orbitRadius, 1.5f) * 1000;
|
orbitTime = Mathf.pow(orbitRadius, 1.5f) * 1000;
|
||||||
@@ -117,6 +117,21 @@ public class Planet extends UnlockableContent{
|
|||||||
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
|
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Planet(String name, Planet parent, float radius, int sectorSize){
|
||||||
|
this(name, parent, radius);
|
||||||
|
|
||||||
|
if(sectorSize > 0){
|
||||||
|
grid = PlanetGrid.create(sectorSize);
|
||||||
|
|
||||||
|
sectors.ensureCapacity(grid.tiles.length);
|
||||||
|
for(int i = 0; i < grid.tiles.length; i++){
|
||||||
|
sectors.add(new Sector(this, grid.tiles[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
sectorApproxRadius = sectors.first().tile.v.dst(sectors.first().tile.corners[0].v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public @Nullable Sector getLastSector(){
|
public @Nullable Sector getLastSector(){
|
||||||
if(sectors.isEmpty()){
|
if(sectors.isEmpty()){
|
||||||
return null;
|
return null;
|
||||||
@@ -137,6 +152,11 @@ public class Planet extends UnlockableContent{
|
|||||||
return grid != null && generator != null && sectors.size > 0;
|
return grid != null && generator != null && sectors.size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return whether this planet has any sectors to land on. */
|
||||||
|
public boolean isLandable(){
|
||||||
|
return sectors.size > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateTotalRadius(){
|
public void updateTotalRadius(){
|
||||||
totalRadius = radius;
|
totalRadius = radius;
|
||||||
for(Planet planet : children){
|
for(Planet planet : children){
|
||||||
@@ -151,9 +171,7 @@ public class Planet extends UnlockableContent{
|
|||||||
|
|
||||||
/** Calculates orbital rotation based on universe time.*/
|
/** Calculates orbital rotation based on universe time.*/
|
||||||
public float getOrbitAngle(){
|
public float getOrbitAngle(){
|
||||||
//applies random offset to prevent planets from starting out in a line
|
return (orbitOffset + universe.secondsf() / (orbitTime / 360f)) % 360f;
|
||||||
float offset = Mathf.randomSeed(id, 360);
|
|
||||||
return (offset + universe.secondsf() / (orbitTime / 360f)) % 360f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calulates rotation on own axis based on universe time.*/
|
/** Calulates rotation on own axis based on universe time.*/
|
||||||
@@ -212,9 +230,6 @@ public class Planet extends UnlockableContent{
|
|||||||
|
|
||||||
/** Regenerates the planet mesh. For debugging only. */
|
/** Regenerates the planet mesh. For debugging only. */
|
||||||
public void reloadMesh(){
|
public void reloadMesh(){
|
||||||
if(mesh != null){
|
|
||||||
mesh.dispose();
|
|
||||||
}
|
|
||||||
mesh = meshLoader.get();
|
mesh = meshLoader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,14 +261,6 @@ public class Planet extends UnlockableContent{
|
|||||||
clipRadius = Math.max(clipRadius, radius + atmosphereRadOut + 0.5f);
|
clipRadius = Math.max(clipRadius, radius + atmosphereRadOut + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose(){
|
|
||||||
if(mesh != null){
|
|
||||||
mesh.dispose();
|
|
||||||
mesh = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a sector a tile position. */
|
/** Gets a sector a tile position. */
|
||||||
public Sector getSector(Ptile tile){
|
public Sector getSector(Ptile tile){
|
||||||
return sectors.get(tile.id);
|
return sectors.get(tile.id);
|
||||||
@@ -294,8 +301,8 @@ public class Planet extends UnlockableContent{
|
|||||||
return visible;
|
return visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw(Mat3D projection, Mat3D transform){
|
public void draw(PlanetParams params, Mat3D projection, Mat3D transform){
|
||||||
mesh.render(projection, transform);
|
mesh.render(params, projection, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawAtmosphere(Mesh atmosphere, Camera3D cam){
|
public void drawAtmosphere(Mesh atmosphere, Camera3D cam){
|
||||||
@@ -316,9 +323,9 @@ public class Planet extends UnlockableContent{
|
|||||||
Gl.depthMask(true);
|
Gl.depthMask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawClouds(Mat3D projection, Mat3D transform){
|
public void drawClouds(PlanetParams params, Mat3D projection, Mat3D transform){
|
||||||
if(cloudMesh != null){
|
if(cloudMesh != null){
|
||||||
cloudMesh.render(projection, transform);
|
cloudMesh.render(params, projection, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ public class Sector{
|
|||||||
this.planet = planet;
|
this.planet = planet;
|
||||||
this.tile = tile;
|
this.tile = tile;
|
||||||
this.plane = new Plane();
|
this.plane = new Plane();
|
||||||
this.rect = makeRect();
|
//empty sector tile needs a special rect
|
||||||
|
if(tile.corners.length == 0){
|
||||||
|
rect = new SectorRect(1f, Vec3.Zero.cpy(), Vec3.Y.cpy(), Vec3.X.cpy(), 0f);
|
||||||
|
}else{
|
||||||
|
this.rect = makeRect();
|
||||||
|
}
|
||||||
this.id = tile.id;
|
this.id = tile.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,9 +161,7 @@ public class Sector{
|
|||||||
|
|
||||||
/** @return the sector size, in tiles */
|
/** @return the sector size, in tiles */
|
||||||
public int getSize(){
|
public int getSize(){
|
||||||
if(planet.generator == null) return 1;
|
return planet.generator == null ? 1 : planet.generator.getSectorSize(this);
|
||||||
int res = (int)(rect.radius * planet.generator.getSizeScl());
|
|
||||||
return res % 2 == 0 ? res : res + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeItems(ItemSeq items){
|
public void removeItems(ItemSeq items){
|
||||||
|
|||||||
@@ -71,9 +71,13 @@ public class UnitType extends UnlockableContent{
|
|||||||
public int commandLimit = 8;
|
public int commandLimit = 8;
|
||||||
public float commandRadius = 150f;
|
public float commandRadius = 150f;
|
||||||
public float visualElevation = -1f;
|
public float visualElevation = -1f;
|
||||||
|
/** If true and this is a legged unit, this unit can walk over blocks. */
|
||||||
public boolean allowLegStep = false;
|
public boolean allowLegStep = false;
|
||||||
|
/** If true, this unit cannot drown, and will not be affected by the floor under it. */
|
||||||
public boolean hovering = false;
|
public boolean hovering = false;
|
||||||
public boolean omniMovement = true;
|
public boolean omniMovement = true;
|
||||||
|
public boolean showHeal = true;
|
||||||
|
public Color healColor = Pal.heal;
|
||||||
public Effect fallEffect = Fx.fallSmoke;
|
public Effect fallEffect = Fx.fallSmoke;
|
||||||
public Effect fallThrusterEffect = Fx.fallSmoke;
|
public Effect fallThrusterEffect = Fx.fallSmoke;
|
||||||
public Effect deathExplosionEffect = Fx.dynamicExplosion;
|
public Effect deathExplosionEffect = Fx.dynamicExplosion;
|
||||||
@@ -112,13 +116,14 @@ public class UnitType extends UnlockableContent{
|
|||||||
public float dpsEstimate = -1;
|
public float dpsEstimate = -1;
|
||||||
public float clipSize = -1;
|
public float clipSize = -1;
|
||||||
public boolean canDrown = true, naval = false;
|
public boolean canDrown = true, naval = false;
|
||||||
|
public float drownTimeMultiplier = 1f;
|
||||||
public float engineOffset = 5f, engineSize = 2.5f;
|
public float engineOffset = 5f, engineSize = 2.5f;
|
||||||
public float strafePenalty = 0.5f;
|
public float strafePenalty = 0.5f;
|
||||||
public float hitSize = 6f;
|
public float hitSize = 6f;
|
||||||
public float itemOffsetY = 3f;
|
public float itemOffsetY = 3f;
|
||||||
public float lightRadius = -1f, lightOpacity = 0.6f;
|
public float lightRadius = -1f, lightOpacity = 0.6f;
|
||||||
public Color lightColor = Pal.powerLight;
|
public Color lightColor = Pal.powerLight;
|
||||||
public boolean drawCell = true, drawItems = true, drawShields = true;
|
public boolean drawCell = true, drawItems = true, drawShields = true, drawBody = true;
|
||||||
public int trailLength = 3;
|
public int trailLength = 3;
|
||||||
public float trailX = 4f, trailY = -3f, trailScl = 1f;
|
public float trailX = 4f, trailY = -3f, trailScl = 1f;
|
||||||
/** Whether the unit can heal blocks. Initialized in init() */
|
/** Whether the unit can heal blocks. Initialized in init() */
|
||||||
@@ -135,7 +140,9 @@ public class UnitType extends UnlockableContent{
|
|||||||
softShadowRegion, jointRegion, footRegion, legBaseRegion, baseJointRegion, outlineRegion;
|
softShadowRegion, jointRegion, footRegion, legBaseRegion, baseJointRegion, outlineRegion;
|
||||||
public TextureRegion[] wreckRegions;
|
public TextureRegion[] wreckRegions;
|
||||||
|
|
||||||
|
protected float buildTime = -1f;
|
||||||
protected @Nullable ItemStack[] cachedRequirements;
|
protected @Nullable ItemStack[] cachedRequirements;
|
||||||
|
protected @Nullable ItemStack[] totalRequirements;
|
||||||
|
|
||||||
public UnitType(String name){
|
public UnitType(String name){
|
||||||
super(name);
|
super(name);
|
||||||
@@ -312,6 +319,8 @@ public class UnitType extends UnlockableContent{
|
|||||||
|
|
||||||
Unit example = constructor.get();
|
Unit example = constructor.get();
|
||||||
|
|
||||||
|
allowLegStep = example instanceof Legsc;
|
||||||
|
|
||||||
//water preset
|
//water preset
|
||||||
if(example instanceof WaterMovec){
|
if(example instanceof WaterMovec){
|
||||||
naval = true;
|
naval = true;
|
||||||
@@ -323,6 +332,10 @@ public class UnitType extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(flying){
|
||||||
|
envEnabled |= Env.space;
|
||||||
|
}
|
||||||
|
|
||||||
if(lightRadius == -1){
|
if(lightRadius == -1){
|
||||||
lightRadius = Math.max(60f, hitSize * 2.3f);
|
lightRadius = Math.max(60f, hitSize * 2.3f);
|
||||||
}
|
}
|
||||||
@@ -475,25 +488,72 @@ public class UnitType extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the time required to build this unit, as a value that takes into account reconstructors */
|
||||||
|
public float getBuildTime(){
|
||||||
|
getTotalRequirements();
|
||||||
|
return buildTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all items needed to build this unit, including reconstructor steps. */
|
||||||
|
public ItemStack[] getTotalRequirements(){
|
||||||
|
if(totalRequirements == null){
|
||||||
|
UnitType[] ret = {null};
|
||||||
|
float[] timeret = {0f};
|
||||||
|
ItemStack[] result = getRequirements(ret, timeret);
|
||||||
|
|
||||||
|
//prevents stack overflow if requirements are circular and result != null
|
||||||
|
totalRequirements = ItemStack.empty;
|
||||||
|
|
||||||
|
if(result != null){
|
||||||
|
ItemSeq total = new ItemSeq();
|
||||||
|
|
||||||
|
total.add(result);
|
||||||
|
if(ret[0] != null){
|
||||||
|
total.add(ret[0].getTotalRequirements());
|
||||||
|
}
|
||||||
|
totalRequirements = total.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var stack : totalRequirements){
|
||||||
|
buildTime += stack.item.cost * stack.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalRequirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return item requirements based on reconstructors or factories found; returns previous unit in array if provided */
|
||||||
|
public @Nullable ItemStack[] getRequirements(@Nullable UnitType[] prevReturn, @Nullable float[] timeReturn){
|
||||||
|
var rec = (Reconstructor)content.blocks().find(b -> b instanceof Reconstructor re && re.upgrades.contains(u -> u[1] == this));
|
||||||
|
|
||||||
|
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems ci){
|
||||||
|
if(prevReturn != null){
|
||||||
|
prevReturn[0] = rec.upgrades.find(u -> u[1] == this)[0];
|
||||||
|
}
|
||||||
|
if(timeReturn != null){
|
||||||
|
timeReturn[0] = rec.constructTime;
|
||||||
|
}
|
||||||
|
return ci.items;
|
||||||
|
}else{
|
||||||
|
var factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory uf && uf.plans.contains(p -> p.unit == this));
|
||||||
|
if(factory != null){
|
||||||
|
|
||||||
|
var plan = factory.plans.find(p -> p.unit == this);
|
||||||
|
if(timeReturn != null){
|
||||||
|
timeReturn[0] = plan.time;
|
||||||
|
}
|
||||||
|
return plan.requirements;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack[] researchRequirements(){
|
public ItemStack[] researchRequirements(){
|
||||||
if(cachedRequirements != null){
|
if(cachedRequirements != null){
|
||||||
return cachedRequirements;
|
return cachedRequirements;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack[] stacks = null;
|
ItemStack[] stacks = getRequirements(null, null);
|
||||||
|
|
||||||
//calculate costs based on reconstructors or factories found
|
|
||||||
Block rec = content.blocks().find(b -> b instanceof Reconstructor re && re.upgrades.contains(u -> u[1] == this));
|
|
||||||
|
|
||||||
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems ci){
|
|
||||||
stacks = ci.items;
|
|
||||||
}else{
|
|
||||||
UnitFactory factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory uf && uf.plans.contains(p -> p.unit == this));
|
|
||||||
if(factory != null){
|
|
||||||
stacks = factory.plans.find(p -> p.unit == this).requirements;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(stacks != null){
|
if(stacks != null){
|
||||||
ItemStack[] out = new ItemStack[stacks.length];
|
ItemStack[] out = new ItemStack[stacks.length];
|
||||||
@@ -557,10 +617,10 @@ public class UnitType extends UnlockableContent{
|
|||||||
|
|
||||||
Draw.z(z);
|
Draw.z(z);
|
||||||
|
|
||||||
drawOutline(unit);
|
if(drawBody) drawOutline(unit);
|
||||||
drawWeaponOutlines(unit);
|
drawWeaponOutlines(unit);
|
||||||
if(engineSize > 0) drawEngine(unit);
|
if(engineSize > 0) drawEngine(unit);
|
||||||
drawBody(unit);
|
if(drawBody) drawBody(unit);
|
||||||
if(drawCell) drawCell(unit);
|
if(drawCell) drawCell(unit);
|
||||||
drawWeapons(unit);
|
drawWeapons(unit);
|
||||||
if(drawItems) drawItems(unit);
|
if(drawItems) drawItems(unit);
|
||||||
@@ -623,14 +683,25 @@ public class UnitType extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawShadow(Unit unit){
|
public void drawShadow(Unit unit){
|
||||||
Draw.color(Pal.shadow);
|
float e = Math.max(unit.elevation, visualElevation) * (1f - unit.drownTime);
|
||||||
float e = Math.max(unit.elevation, visualElevation);
|
float x = unit.x + shadowTX * e, y = unit.y + shadowTY * e;
|
||||||
|
Floor floor = world.floorWorld(x, y);
|
||||||
|
|
||||||
|
float dest = floor.canShadow ? 1f : 0f;
|
||||||
|
//yes, this updates state in draw()... which isn't a problem, because I don't want it to be obvious anyway
|
||||||
|
unit.shadowAlpha = unit.shadowAlpha < 0 ? dest : Mathf.approachDelta(unit.shadowAlpha, dest, 0.11f);
|
||||||
|
Draw.color(Pal.shadow, Pal.shadow.a * unit.shadowAlpha);
|
||||||
|
|
||||||
Draw.rect(shadowRegion, unit.x + shadowTX * e, unit.y + shadowTY * e, unit.rotation - 90);
|
Draw.rect(shadowRegion, unit.x + shadowTX * e, unit.y + shadowTY * e, unit.rotation - 90);
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawSoftShadow(Unit unit){
|
public void drawSoftShadow(Unit unit){
|
||||||
Draw.color(0, 0, 0, 0.4f);
|
drawSoftShadow(unit, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawSoftShadow(Unit unit, float alpha){
|
||||||
|
Draw.color(0, 0, 0, 0.4f * alpha);
|
||||||
float rad = 1.6f;
|
float rad = 1.6f;
|
||||||
float size = Math.max(region.width, region.height) * Draw.scl;
|
float size = Math.max(region.width, region.height) * Draw.scl;
|
||||||
Draw.rect(softShadowRegion, unit, size * rad * Draw.xscl, size * rad * Draw.yscl, unit.rotation - 90);
|
Draw.rect(softShadowRegion, unit, size * rad * Draw.xscl, size * rad * Draw.yscl, unit.rotation - 90);
|
||||||
@@ -719,16 +790,11 @@ public class UnitType extends UnlockableContent{
|
|||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyOutlineColor(Unit unit){
|
|
||||||
if(unit.isBoss()){
|
|
||||||
Draw.mixcol(unit.team.color, Mathf.absin(7f, 1f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void drawOutline(Unit unit){
|
public void drawOutline(Unit unit){
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
|
|
||||||
if(Core.atlas.isFound(outlineRegion)){
|
if(Core.atlas.isFound(outlineRegion)){
|
||||||
|
applyColor(unit);
|
||||||
applyOutlineColor(unit);
|
applyOutlineColor(unit);
|
||||||
Draw.rect(outlineRegion, unit.x, unit.y, unit.rotation - 90);
|
Draw.rect(outlineRegion, unit.x, unit.y, unit.rotation - 90);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
@@ -764,14 +830,16 @@ public class UnitType extends UnlockableContent{
|
|||||||
|
|
||||||
public <T extends Unit & Legsc> void drawLegs(T unit){
|
public <T extends Unit & Legsc> void drawLegs(T unit){
|
||||||
applyColor(unit);
|
applyColor(unit);
|
||||||
|
Tmp.c3.set(Draw.getMixColor());
|
||||||
|
|
||||||
Leg[] legs = unit.legs();
|
Leg[] legs = unit.legs();
|
||||||
|
|
||||||
float ssize = footRegion.width * Draw.scl * 1.5f;
|
float ssize = footRegion.width * Draw.scl * 1.5f;
|
||||||
float rotation = unit.baseRotation();
|
float rotation = unit.baseRotation();
|
||||||
|
float invDrown = 1f - unit.drownTime;
|
||||||
|
|
||||||
for(Leg leg : legs){
|
for(Leg leg : legs){
|
||||||
Drawf.shadow(leg.base.x, leg.base.y, ssize);
|
Drawf.shadow(leg.base.x, leg.base.y, ssize, invDrown);
|
||||||
}
|
}
|
||||||
|
|
||||||
//legs are drawn front first
|
//legs are drawn front first
|
||||||
@@ -787,13 +855,15 @@ public class UnitType extends UnlockableContent{
|
|||||||
Tmp.v1.set(leg.base).sub(leg.joint).inv().setLength(legExtension);
|
Tmp.v1.set(leg.base).sub(leg.joint).inv().setLength(legExtension);
|
||||||
|
|
||||||
if(leg.moving && visualElevation > 0){
|
if(leg.moving && visualElevation > 0){
|
||||||
float scl = visualElevation;
|
float scl = visualElevation * invDrown;
|
||||||
float elev = Mathf.slope(1f - leg.stage) * scl;
|
float elev = Mathf.slope(1f - leg.stage) * scl;
|
||||||
Draw.color(Pal.shadow);
|
Draw.color(Pal.shadow);
|
||||||
Draw.rect(footRegion, leg.base.x + shadowTX * elev, leg.base.y + shadowTY * elev, position.angleTo(leg.base));
|
Draw.rect(footRegion, leg.base.x + shadowTX * elev, leg.base.y + shadowTY * elev, position.angleTo(leg.base));
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Draw.mixcol(Tmp.c3, Tmp.c3.a);
|
||||||
|
|
||||||
Draw.rect(footRegion, leg.base.x, leg.base.y, position.angleTo(leg.base));
|
Draw.rect(footRegion, leg.base.x, leg.base.y, position.angleTo(leg.base));
|
||||||
|
|
||||||
Lines.stroke(legRegion.height * Draw.scl * flips);
|
Lines.stroke(legRegion.height * Draw.scl * flips);
|
||||||
@@ -848,8 +918,8 @@ public class UnitType extends UnlockableContent{
|
|||||||
|
|
||||||
Draw.mixcol(Color.white, unit.hitTime);
|
Draw.mixcol(Color.white, unit.hitTime);
|
||||||
|
|
||||||
if(floor.isLiquid){
|
if(unit.lastDrownFloor != null){
|
||||||
Draw.color(Color.white, floor.mapColor, unit.drownTime() * 0.4f);
|
Draw.color(Color.white, Tmp.c1.set(unit.lastDrownFloor.mapColor).mul(0.83f), unit.drownTime * 0.9f);
|
||||||
}else{
|
}else{
|
||||||
Draw.color(Color.white);
|
Draw.color(Color.white);
|
||||||
}
|
}
|
||||||
@@ -859,13 +929,25 @@ public class UnitType extends UnlockableContent{
|
|||||||
Draw.mixcol();
|
Draw.mixcol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void applyOutlineColor(Unit unit){
|
||||||
|
if(unit.isBoss()){
|
||||||
|
Draw.mixcol(unit.team.color, Mathf.absin(7f, 1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unit.drownTime > 0 && unit.lastDrownFloor != null){
|
||||||
|
Draw.color(Color.white, Tmp.c1.set(unit.lastDrownFloor.mapColor).mul(0.8f), unit.drownTime * 0.9f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void applyColor(Unit unit){
|
public void applyColor(Unit unit){
|
||||||
Draw.color();
|
Draw.color();
|
||||||
Tmp.c1.set(Color.white).lerp(Pal.heal, Mathf.clamp(unit.healTime - unit.hitTime));
|
if(showHeal){
|
||||||
|
Tmp.c1.set(Color.white).lerp(healColor, Mathf.clamp(unit.healTime - unit.hitTime));
|
||||||
|
}
|
||||||
Draw.mixcol(Tmp.c1, Math.max(unit.hitTime, Mathf.clamp(unit.healTime)));
|
Draw.mixcol(Tmp.c1, Math.max(unit.hitTime, Mathf.clamp(unit.healTime)));
|
||||||
|
|
||||||
if(unit.drownTime > 0 && unit.floorOn().isDeep()){
|
if(unit.drownTime > 0 && unit.lastDrownFloor != null){
|
||||||
Draw.mixcol(unit.floorOn().mapColor, unit.drownTime * 0.8f);
|
Draw.mixcol(Tmp.c1.set(unit.lastDrownFloor.mapColor).mul(0.83f), unit.drownTime * 0.9f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class Weapon implements Cloneable{
|
|||||||
static int sequenceNum = 0;
|
static int sequenceNum = 0;
|
||||||
|
|
||||||
/** displayed weapon region */
|
/** displayed weapon region */
|
||||||
public String name = "";
|
public String name;
|
||||||
/** bullet shot */
|
/** bullet shot */
|
||||||
public BulletType bullet = Bullets.standardCopper;
|
public BulletType bullet = Bullets.standardCopper;
|
||||||
/** shell ejection effect */
|
/** shell ejection effect */
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ public class Weather extends UnlockableContent{
|
|||||||
Draw.rect(region, x, y, size, size, rotation);
|
Draw.rect(region, x, y, size, size, rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawRain(float sizeMin, float sizeMax, float xspeed, float yspeed, float density, float intensity, float stroke, Color color){
|
public static void drawRain(float sizeMin, float sizeMax, float xspeed, float yspeed, float density, float intensity, float stroke, Color color){
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
/** Class for handling menus and notifications across the network. Unstable API! */
|
/** Class for handling menus and notifications across the network. Unstable API! */
|
||||||
public class Menus{
|
public class Menus{
|
||||||
private static IntMap<MenuListener> menuListeners = new IntMap<>();
|
private static final Seq<MenuListener> menuListeners = new Seq<>();
|
||||||
|
|
||||||
/** Register a *global* menu listener. If no option is chosen, the option is returned as -1. */
|
/** Register a *global* menu listener. If no option is chosen, the option is returned as -1. */
|
||||||
public static void registerMenu(int id, MenuListener listener){
|
public static int registerMenu(MenuListener listener){
|
||||||
menuListeners.put(id, listener);
|
menuListeners.add(listener);
|
||||||
|
return menuListeners.size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//do not invoke any of the methods below directly, use Call
|
//do not invoke any of the methods below directly, use Call
|
||||||
@@ -30,7 +31,7 @@ public class Menus{
|
|||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.both)
|
@Remote(targets = Loc.both, called = Loc.both)
|
||||||
public static void menuChoose(@Nullable Player player, int menuId, int option){
|
public static void menuChoose(@Nullable Player player, int menuId, int option){
|
||||||
if(player != null && menuListeners.containsKey(menuId)){
|
if(player != null && menuId >= 0 && menuId < menuListeners.size){
|
||||||
Events.fire(new MenuOptionChooseEvent(player, menuId, option));
|
Events.fire(new MenuOptionChooseEvent(player, menuId, option));
|
||||||
menuListeners.get(menuId).get(player, option);
|
menuListeners.get(menuId).get(player, option);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ public class JoinDialog extends BaseDialog{
|
|||||||
|
|
||||||
void safeConnect(String ip, int port, int version){
|
void safeConnect(String ip, int port, int version){
|
||||||
if(version != Version.build && Version.build != -1 && version != -1){
|
if(version != Version.build && Version.build != -1 && version != -1){
|
||||||
ui.showInfo("[scarlet]" + (version > Version.build ? KickReason.clientOutdated : KickReason.serverOutdated).toString() + "\n[]" +
|
ui.showInfo("[scarlet]" + (version > Version.build ? KickReason.clientOutdated : KickReason.serverOutdated) + "\n[]" +
|
||||||
Core.bundle.format("server.versions", Version.build, version));
|
Core.bundle.format("server.versions", Version.build, version));
|
||||||
}else{
|
}else{
|
||||||
connect(ip, port);
|
connect(ip, port);
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public class MapPlayDialog extends BaseDialog{
|
|||||||
table.row();
|
table.row();
|
||||||
for(Gamemode mode : Gamemode.values()){
|
for(Gamemode mode : Gamemode.values()){
|
||||||
if(mode.hidden) continue;
|
if(mode.hidden) continue;
|
||||||
table.labelWrap("[accent]" + mode.toString() + ":[] [lightgray]" + mode.description()).width(400f);
|
table.labelWrap("[accent]" + mode + ":[] [lightgray]" + mode.description()).width(400f);
|
||||||
table.row();
|
table.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import arc.scene.ui.*;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.content.TechTree.*;
|
import mindustry.content.TechTree.*;
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
@@ -24,6 +25,7 @@ import mindustry.game.SectorInfo.*;
|
|||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.graphics.g3d.PlanetGrid.*;
|
||||||
import mindustry.graphics.g3d.*;
|
import mindustry.graphics.g3d.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.maps.*;
|
import mindustry.maps.*;
|
||||||
@@ -49,10 +51,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
public static float sectorShowDuration = 60f * 2.4f;
|
public static float sectorShowDuration = 60f * 2.4f;
|
||||||
|
|
||||||
public final FrameBuffer buffer = new FrameBuffer(2, 2, true);
|
public final FrameBuffer buffer = new FrameBuffer(2, 2, true);
|
||||||
public final PlanetRenderer planets = renderer.planets;
|
|
||||||
public final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
|
public final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
|
||||||
|
public final PlanetRenderer planets = renderer.planets;
|
||||||
|
|
||||||
public float zoom = 1f, selectAlpha = 1f;
|
public PlanetParams state = new PlanetParams();
|
||||||
|
public float zoom = 1f;
|
||||||
public @Nullable Sector selected, hovered, launchSector;
|
public @Nullable Sector selected, hovered, launchSector;
|
||||||
public Mode mode = look;
|
public Mode mode = look;
|
||||||
public boolean launching;
|
public boolean launching;
|
||||||
@@ -68,10 +71,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
public PlanetDialog(){
|
public PlanetDialog(){
|
||||||
super("", Styles.fullDialog);
|
super("", Styles.fullDialog);
|
||||||
|
|
||||||
|
state.renderer = this;
|
||||||
|
state.drawUi = true;
|
||||||
|
|
||||||
shouldPause = true;
|
shouldPause = true;
|
||||||
planets.planet = content.getByName(ContentType.planet, Core.settings.getString("lastplanet", "serpulo"));
|
state.planet = content.getByName(ContentType.planet, Core.settings.getString("lastplanet", "serpulo"));
|
||||||
if(planets.planet == null) planets.planet = Planets.serpulo;
|
if(state.planet == null) state.planet = Planets.serpulo;
|
||||||
|
|
||||||
addListener(new InputListener(){
|
addListener(new InputListener(){
|
||||||
@Override
|
@Override
|
||||||
@@ -107,7 +113,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
newPresets.clear();
|
newPresets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 pos = planets.camPos;
|
Vec3 pos = state.camPos;
|
||||||
|
|
||||||
float upV = pos.angle(Vec3.Y);
|
float upV = pos.angle(Vec3.Y);
|
||||||
float xscale = 9f, yscale = 10f;
|
float xscale = 9f, yscale = 10f;
|
||||||
@@ -116,20 +122,20 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
//scale X speed depending on polar coordinate
|
//scale X speed depending on polar coordinate
|
||||||
float speed = 1f - Math.abs(upV - 90) / 90f;
|
float speed = 1f - Math.abs(upV - 90) / 90f;
|
||||||
|
|
||||||
pos.rotate(planets.cam.up, cx / xscale * speed);
|
pos.rotate(state.camUp, cx / xscale * speed);
|
||||||
|
|
||||||
//prevent user from scrolling all the way up and glitching it out
|
//prevent user from scrolling all the way up and glitching it out
|
||||||
float amount = cy / yscale;
|
float amount = cy / yscale;
|
||||||
amount = Mathf.clamp(upV + amount, margin, 180f - margin) - upV;
|
amount = Mathf.clamp(upV + amount, margin, 180f - margin) - upV;
|
||||||
|
|
||||||
pos.rotate(Tmp.v31.set(planets.cam.up).rotate(planets.cam.direction, 90), amount);
|
pos.rotate(Tmp.v31.set(state.camUp).rotate(state.camDir, 90), amount);
|
||||||
});
|
});
|
||||||
|
|
||||||
addListener(new InputListener(){
|
addListener(new InputListener(){
|
||||||
@Override
|
@Override
|
||||||
public boolean scrolled(InputEvent event, float x, float y, float amountX, float amountY){
|
public boolean scrolled(InputEvent event, float x, float y, float amountX, float amountY){
|
||||||
if(event.targetActor == PlanetDialog.this){
|
if(event.targetActor == PlanetDialog.this){
|
||||||
zoom = Mathf.clamp(zoom + amountY / 10f, 0.5f, 2f);
|
zoom = Mathf.clamp(zoom + amountY / 10f, state.planet.minZoom, 2f);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -144,7 +150,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
lastZoom = zoom;
|
lastZoom = zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
zoom = (Mathf.clamp(initialDistance / distance * lastZoom, 0.5f, 2f));
|
zoom = (Mathf.clamp(initialDistance / distance * lastZoom, state.planet.minZoom, 2f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -170,9 +176,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
launching = false;
|
launching = false;
|
||||||
|
|
||||||
zoom = 1f;
|
zoom = 1f;
|
||||||
planets.zoom = 1f;
|
state.zoom = 1f;
|
||||||
selectAlpha = 0f;
|
state.uiAlpha = 0f;
|
||||||
launchSector = state.getSector();
|
launchSector = Vars.state.getSector();
|
||||||
presetShow = 0f;
|
presetShow = 0f;
|
||||||
showed = false;
|
showed = false;
|
||||||
listener = s -> {};
|
listener = s -> {};
|
||||||
@@ -181,7 +187,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
//announce new presets
|
//announce new presets
|
||||||
for(SectorPreset preset : content.sectors()){
|
for(SectorPreset preset : content.sectors()){
|
||||||
if(preset.unlocked() && !preset.alwaysUnlocked && !preset.sector.info.shown && !preset.sector.hasBase() && preset.planet == planets.planet){
|
if(preset.unlocked() && !preset.alwaysUnlocked && !preset.sector.info.shown && !preset.sector.hasBase() && preset.planet == state.planet){
|
||||||
newPresets.add(preset.sector);
|
newPresets.add(preset.sector);
|
||||||
preset.sector.info.shown = true;
|
preset.sector.info.shown = true;
|
||||||
preset.sector.saveInfo();
|
preset.sector.saveInfo();
|
||||||
@@ -189,14 +195,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(newPresets.any()){
|
if(newPresets.any()){
|
||||||
newPresets.add(planets.planet.getLastSector());
|
newPresets.add(state.planet.getLastSector());
|
||||||
}
|
}
|
||||||
|
|
||||||
newPresets.reverse();
|
newPresets.reverse();
|
||||||
updateSelected();
|
updateSelected();
|
||||||
|
|
||||||
if(planets.planet.getLastSector() != null){
|
if(state.planet.getLastSector() != null){
|
||||||
lookAt(planets.planet.getLastSector());
|
lookAt(state.planet.getLastSector());
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.show();
|
return super.show();
|
||||||
@@ -252,8 +258,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
//update view to sector
|
//update view to sector
|
||||||
zoom = 1f;
|
zoom = 1f;
|
||||||
planets.zoom = 1f;
|
state.zoom = 1f;
|
||||||
selectAlpha = 0f;
|
state.uiAlpha = 0f;
|
||||||
|
|
||||||
mode = planetLaunch;
|
mode = planetLaunch;
|
||||||
|
|
||||||
@@ -269,8 +275,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
//update view to sector
|
//update view to sector
|
||||||
lookAt(sector);
|
lookAt(sector);
|
||||||
zoom = 1f;
|
zoom = 1f;
|
||||||
planets.zoom = 1f;
|
state.zoom = 1f;
|
||||||
selectAlpha = 0f;
|
state.uiAlpha = 0f;
|
||||||
launchSector = sector;
|
launchSector = sector;
|
||||||
|
|
||||||
mode = select;
|
mode = select;
|
||||||
@@ -279,7 +285,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lookAt(Sector sector){
|
void lookAt(Sector sector){
|
||||||
planets.camPos.set(Tmp.v33.set(sector.tile.v).rotate(Vec3.Y, -sector.planet.getRotation()));
|
if(sector.tile == Ptile.empty) return;
|
||||||
|
|
||||||
|
state.camPos.set(Tmp.v33.set(sector.tile.v).rotate(Vec3.Y, -sector.planet.getRotation()));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean canSelect(Sector sector){
|
boolean canSelect(Sector sector){
|
||||||
@@ -307,7 +315,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
launchFrom = to.near().find(Sector::hasBase);
|
launchFrom = to.near().find(Sector::hasBase);
|
||||||
if(launchFrom == null && to.preset != null){
|
if(launchFrom == null && to.preset != null){
|
||||||
if(launchSector != null) return launchSector;
|
if(launchSector != null) return launchSector;
|
||||||
launchFrom = planets.planet.sectors.min(s -> !s.hasBase() ? Float.MAX_VALUE : s.tile.v.dst2(to.tile.v));
|
launchFrom = state.planet.sectors.min(s -> !s.hasBase() ? Float.MAX_VALUE : s.tile.v.dst2(to.tile.v));
|
||||||
if(!launchFrom.hasBase()) launchFrom = null;
|
if(!launchFrom.hasBase()) launchFrom = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,7 +331,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
public void renderSectors(Planet planet){
|
public void renderSectors(Planet planet){
|
||||||
|
|
||||||
//draw all sector stuff
|
//draw all sector stuff
|
||||||
if(selectAlpha > 0.01f){
|
if(state.uiAlpha > 0.01f){
|
||||||
for(Sector sec : planet.sectors){
|
for(Sector sec : planet.sectors){
|
||||||
if(canSelect(sec) || sec.unlocked() || debugSelect){
|
if(canSelect(sec) || sec.unlocked() || debugSelect){
|
||||||
|
|
||||||
@@ -336,15 +344,15 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
null;
|
null;
|
||||||
|
|
||||||
if(color != null){
|
if(color != null){
|
||||||
planets.drawSelection(sec, Tmp.c1.set(color).mul(0.8f).a(selectAlpha), 0.026f, -0.001f);
|
planets.drawSelection(sec, Tmp.c1.set(color).mul(0.8f).a(state.uiAlpha), 0.026f, -0.001f);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
planets.fill(sec, Tmp.c1.set(shadowColor).mul(1, 1, 1, selectAlpha), -0.001f);
|
planets.fill(sec, Tmp.c1.set(shadowColor).mul(1, 1, 1, state.uiAlpha), -0.001f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sector current = state.getSector() != null && state.getSector().isBeingPlayed() && state.getSector().planet == planets.planet ? state.getSector() : null;
|
Sector current = Vars.state.getSector() != null && Vars.state.getSector().isBeingPlayed() && Vars.state.getSector().planet == state.planet ? Vars.state.getSector() : null;
|
||||||
|
|
||||||
if(current != null){
|
if(current != null){
|
||||||
planets.fill(current, hoverColor, -0.001f);
|
planets.fill(current, hoverColor, -0.001f);
|
||||||
@@ -371,12 +379,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectAlpha > 0.001f){
|
if(state.uiAlpha > 0.001f){
|
||||||
for(Sector sec : planet.sectors){
|
for(Sector sec : planet.sectors){
|
||||||
if(sec.hasBase()){
|
if(sec.hasBase()){
|
||||||
for(Sector enemy : sec.near()){
|
for(Sector enemy : sec.near()){
|
||||||
if(enemy.hasEnemyBase()){
|
if(enemy.hasEnemyBase()){
|
||||||
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(selectAlpha), Color.clear, 0.24f, 110f, 25);
|
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,11 +392,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
if(selected != null && selected != sec && selected.hasBase()){
|
if(selected != null && selected != sec && selected.hasBase()){
|
||||||
//imports
|
//imports
|
||||||
if(sec.info.getRealDestination() == selected && sec.info.anyExports()){
|
if(sec.info.getRealDestination() == selected && sec.info.anyExports()){
|
||||||
planets.drawArc(planet, sec.tile.v, selected.tile.v, Color.gray.write(Tmp.c2).a(selectAlpha), Pal.accent.write(Tmp.c3).a(selectAlpha), 0.4f, 90f, 25);
|
planets.drawArc(planet, sec.tile.v, selected.tile.v, Color.gray.write(Tmp.c2).a(state.uiAlpha), Pal.accent.write(Tmp.c3).a(state.uiAlpha), 0.4f, 90f, 25);
|
||||||
}
|
}
|
||||||
//exports
|
//exports
|
||||||
if(selected.info.getRealDestination() == sec && selected.info.anyExports()){
|
if(selected.info.getRealDestination() == sec && selected.info.anyExports()){
|
||||||
planets.drawArc(planet, selected.tile.v, sec.tile.v, Pal.place.write(Tmp.c2).a(selectAlpha), Pal.accent.write(Tmp.c3).a(selectAlpha), 0.4f, 90f, 25);
|
planets.drawArc(planet, selected.tile.v, sec.tile.v, Pal.place.write(Tmp.c2).a(state.uiAlpha), Pal.accent.write(Tmp.c3).a(state.uiAlpha), 0.4f, 90f, 25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,7 +423,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
if(icon != null){
|
if(icon != null){
|
||||||
planets.drawPlane(sec, () -> {
|
planets.drawPlane(sec, () -> {
|
||||||
//use white for content icons
|
//use white for content icons
|
||||||
Draw.color(preficon == icon && sec.info.contentIcon != null ? Color.white : color, selectAlpha);
|
Draw.color(preficon == icon && sec.info.contentIcon != null ? Color.white : color, state.uiAlpha);
|
||||||
Draw.rect(icon, 0, 0, iw, iw * icon.height / icon.width);
|
Draw.rect(icon, 0, 0, iw, iw * icon.height / icon.width);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -444,13 +452,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
boolean selectable(Planet planet){
|
boolean selectable(Planet planet){
|
||||||
//TODO what if any sector is selectable?
|
//TODO what if any sector is selectable?
|
||||||
if(mode == planetLaunch) return launchSector != null && planet != launchSector.planet;
|
if(mode == planetLaunch) return launchSector != null && planet != launchSector.planet;
|
||||||
return planet == planets.planet || planet.alwaysUnlocked || planet.sectors.contains(Sector::hasBase);
|
return planet == state.planet || (planet.alwaysUnlocked && planet.isLandable()) || planet.sectors.contains(Sector::hasBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
searchText = "";
|
searchText = "";
|
||||||
zoom = planets.zoom = 1f;
|
zoom = state.zoom = 1f;
|
||||||
selectAlpha = 1f;
|
state.uiAlpha = 1f;
|
||||||
ui.minimapfrag.hide();
|
ui.minimapfrag.hide();
|
||||||
|
|
||||||
clearChildren();
|
clearChildren();
|
||||||
@@ -492,8 +500,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
planets.orbitAlpha = selectAlpha;
|
planets.render(state);
|
||||||
planets.render(PlanetDialog.this);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//info text
|
//info text
|
||||||
@@ -518,12 +525,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
pt.button(planet.localizedName, Styles.clearTogglet, () -> {
|
pt.button(planet.localizedName, Styles.clearTogglet, () -> {
|
||||||
selected = null;
|
selected = null;
|
||||||
launchSector = null;
|
launchSector = null;
|
||||||
if(renderer.planets.planet != planet){
|
if(state.planet != planet){
|
||||||
renderer.planets.planet = planet;
|
state.planet = planet;
|
||||||
rebuildList();
|
rebuildList();
|
||||||
}
|
}
|
||||||
settings.put("lastplanet", planet.name);
|
settings.put("lastplanet", planet.name);
|
||||||
}).width(200).height(40).growX().update(bb -> bb.setChecked(renderer.planets.planet == planet));
|
}).width(200).height(40).growX().update(bb -> bb.setChecked(state.planet == planet));
|
||||||
pt.row();
|
pt.row();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,8 +540,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
new Table(c -> {
|
new Table(c -> {
|
||||||
c.visible(() -> !(graphics.isPortrait() && mobile));
|
c.visible(() -> !(graphics.isPortrait() && mobile));
|
||||||
if(planets.planet.sectors.contains(Sector::hasBase)){
|
if(state.planet.sectors.contains(Sector::hasBase)){
|
||||||
int attacked = planets.planet.sectors.count(Sector::isAttacked);
|
int attacked = state.planet.sectors.count(Sector::isAttacked);
|
||||||
|
|
||||||
//sector notifications & search
|
//sector notifications & search
|
||||||
c.top().right();
|
c.top().right();
|
||||||
@@ -564,7 +571,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
notifs.clear();
|
notifs.clear();
|
||||||
|
|
||||||
var all = planets.planet.sectors.select(Sector::hasBase);
|
var all = state.planet.sectors.select(Sector::hasBase);
|
||||||
all.sort(Structs.comps(Structs.comparingBool(s -> !s.isAttacked()), Structs.comparingInt(s -> s.save == null ? 0 : -(int)s.save.meta.timePlayed)));
|
all.sort(Structs.comps(Structs.comparingBool(s -> !s.isAttacked()), Structs.comparingInt(s -> s.save == null ? 0 : -(int)s.save.meta.timePlayed)));
|
||||||
|
|
||||||
notifs.pane(p -> {
|
notifs.pane(p -> {
|
||||||
@@ -646,20 +653,20 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void lookAt(Sector sector, float alpha){
|
public void lookAt(Sector sector, float alpha){
|
||||||
float len = planets.camPos.len();
|
float len = state.camPos.len();
|
||||||
planets.camPos.slerp(Tmp.v31.set(sector.tile.v).rotate(Vec3.Y, -sector.planet.getRotation()).setLength(len), alpha);
|
state.camPos.slerp(Tmp.v31.set(sector.tile.v).rotate(Vec3.Y, -sector.planet.getRotation()).setLength(len), alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void act(float delta){
|
public void act(float delta){
|
||||||
super.act(delta);
|
super.act(delta);
|
||||||
|
|
||||||
if(hovered != null && !mobile){
|
if(hovered != null && !mobile && state.planet.hasGrid()){
|
||||||
addChild(hoverLabel);
|
addChild(hoverLabel);
|
||||||
hoverLabel.toFront();
|
hoverLabel.toFront();
|
||||||
hoverLabel.touchable = Touchable.disabled;
|
hoverLabel.touchable = Touchable.disabled;
|
||||||
|
|
||||||
Vec3 pos = planets.cam.project(Tmp.v31.set(hovered.tile.v).setLength(PlanetRenderer.outlineRad).rotate(Vec3.Y, -planets.planet.getRotation()).add(planets.planet.position));
|
Vec3 pos = planets.cam.project(Tmp.v31.set(hovered.tile.v).setLength(PlanetRenderer.outlineRad).rotate(Vec3.Y, -state.planet.getRotation()).add(state.planet.position));
|
||||||
hoverLabel.setPosition(pos.x - Core.scene.marginLeft, pos.y - Core.scene.marginBottom, Align.center);
|
hoverLabel.setPosition(pos.x - Core.scene.marginLeft, pos.y - Core.scene.marginBottom, Align.center);
|
||||||
|
|
||||||
hoverLabel.getText().setLength(0);
|
hoverLabel.getText().setLength(0);
|
||||||
@@ -704,14 +711,24 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(planets.planet.hasGrid()){
|
if(state.planet.hasGrid()){
|
||||||
hovered = planets.planet.getSector(planets.cam.getMouseRay(), PlanetRenderer.outlineRad);
|
hovered = state.planet.getSector(planets.cam.getMouseRay(), PlanetRenderer.outlineRad);
|
||||||
|
}else if(state.planet.isLandable()){
|
||||||
|
boolean wasNull = selected == null;
|
||||||
|
//always have the first sector selected.
|
||||||
|
//TODO better support for multiple sectors in gridless planets?
|
||||||
|
hovered = selected = state.planet.sectors.first();
|
||||||
|
|
||||||
|
//autoshow
|
||||||
|
if(wasNull){
|
||||||
|
updateSelected();
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
hovered = selected = null;
|
hovered = selected = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
planets.zoom = Mathf.lerpDelta(planets.zoom, zoom, 0.4f);
|
state.zoom = Mathf.lerpDelta(state.zoom, zoom, 0.4f);
|
||||||
selectAlpha = Mathf.lerpDelta(selectAlpha, Mathf.num(planets.zoom < 1.9f), 0.1f);
|
state.uiAlpha = Mathf.lerpDelta(state.uiAlpha, Mathf.num(state.zoom < 1.9f), 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayItems(Table c, float scl, ObjectMap<Item, ExportStat> stats, String name){
|
void displayItems(Table c, float scl, ObjectMap<Item, ExportStat> stats, String name){
|
||||||
@@ -996,13 +1013,17 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
if(launching){
|
if(launching){
|
||||||
stable.color.sub(0, 0, 0, 0.05f * Time.delta);
|
stable.color.sub(0, 0, 0, 0.05f * Time.delta);
|
||||||
}else{
|
}else{
|
||||||
//fade out UI when not facing selected sector
|
if(!state.planet.hasGrid()){
|
||||||
Tmp.v31.set(selected.tile.v).rotate(Vec3.Y, -planets.planet.getRotation()).scl(-1f).nor();
|
stable.color.a = 1f;
|
||||||
float dot = planets.cam.direction.dot(Tmp.v31);
|
}else{
|
||||||
stable.color.a = Math.max(dot, 0f)*2f;
|
//fade out UI when not facing selected sector
|
||||||
if(dot*2f <= -0.1f){
|
Tmp.v31.set(selected.tile.v).rotate(Vec3.Y, -state.planet.getRotation()).scl(-1f).nor();
|
||||||
selected = null;
|
float dot = planets.cam.direction.dot(Tmp.v31);
|
||||||
updateSelected();
|
stable.color.a = Math.max(dot, 0f)*2f;
|
||||||
|
if(dot*2f <= -0.1f){
|
||||||
|
selected = null;
|
||||||
|
updateSelected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1029,7 +1050,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
boolean shouldHide = true;
|
boolean shouldHide = true;
|
||||||
|
|
||||||
//save before launch.
|
//save before launch.
|
||||||
if(control.saves.getCurrent() != null && state.isGame() && mode != select){
|
if(control.saves.getCurrent() != null && Vars.state.isGame() && mode != select){
|
||||||
try{
|
try{
|
||||||
control.saves.getCurrent().save();
|
control.saves.getCurrent().save();
|
||||||
}catch(Throwable e){
|
}catch(Throwable e){
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import mindustry.graphics.*;
|
|||||||
import mindustry.graphics.MultiPacker.*;
|
import mindustry.graphics.MultiPacker.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
import mindustry.world.blocks.environment.*;
|
import mindustry.world.blocks.environment.*;
|
||||||
import mindustry.world.blocks.power.*;
|
import mindustry.world.blocks.power.*;
|
||||||
import mindustry.world.consumers.*;
|
import mindustry.world.consumers.*;
|
||||||
@@ -122,6 +123,8 @@ public class Block extends UnlockableContent{
|
|||||||
public boolean useColor = true;
|
public boolean useColor = true;
|
||||||
/** item that drops from this block, used for drills */
|
/** item that drops from this block, used for drills */
|
||||||
public @Nullable Item itemDrop = null;
|
public @Nullable Item itemDrop = null;
|
||||||
|
/** Array of affinities to certain things. */
|
||||||
|
public Attributes attributes = new Attributes();
|
||||||
/** tile entity health */
|
/** tile entity health */
|
||||||
public int health = -1;
|
public int health = -1;
|
||||||
/** base block explosiveness */
|
/** base block explosiveness */
|
||||||
@@ -384,10 +387,16 @@ public class Block extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether or not this block can be place on the specified */
|
/** Returns whether or not this block can be place on the specified */
|
||||||
|
public boolean canPlaceOn(Tile tile, Team team, int rotation){
|
||||||
|
return canPlaceOn(tile, team);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Legacy canPlaceOn implementation, override {@link #canPlaceOn(Tile, Team, int)} instead.*/
|
||||||
public boolean canPlaceOn(Tile tile, Team team){
|
public boolean canPlaceOn(Tile tile, Team team){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean canBreak(Tile tile){
|
public boolean canBreak(Tile tile){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!type.canPlaceOn(tile, team)){
|
if(!type.canPlaceOn(tile, team, rotation)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ public class ConstructBlock extends Block{
|
|||||||
|
|
||||||
for(TextureRegion region : current.getGeneratedIcons()){
|
for(TextureRegion region : current.getGeneratedIcons()){
|
||||||
Shaders.blockbuild.region = region;
|
Shaders.blockbuild.region = region;
|
||||||
|
Shaders.blockbuild.time = Time.time;
|
||||||
Shaders.blockbuild.progress = progress;
|
Shaders.blockbuild.progress = progress;
|
||||||
|
|
||||||
Draw.rect(region, x, y, current.rotate ? rotdeg() : 0);
|
Draw.rect(region, x, y, current.rotate ? rotdeg() : 0);
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public class ForceProjector extends Block{
|
|||||||
ambientSound = Sounds.shield;
|
ambientSound = Sounds.shield;
|
||||||
ambientSoundVolume = 0.08f;
|
ambientSoundVolume = 0.08f;
|
||||||
consumes.add(new ConsumeCoolant(0.1f)).boost().update(false);
|
consumes.add(new ConsumeCoolant(0.1f)).boost().update(false);
|
||||||
|
envEnabled |= Env.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public class MendProjector extends Block{
|
|||||||
hasItems = true;
|
hasItems = true;
|
||||||
emitLight = true;
|
emitLight = true;
|
||||||
lightRadius = 50f;
|
lightRadius = 50f;
|
||||||
|
envEnabled |= Env.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class OverdriveProjector extends Block{
|
|||||||
canOverdrive = false;
|
canOverdrive = false;
|
||||||
emitLight = true;
|
emitLight = true;
|
||||||
lightRadius = 50f;
|
lightRadius = 50f;
|
||||||
|
envEnabled |= Env.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public class Wall extends Block{
|
|||||||
buildCostMultiplier = 6f;
|
buildCostMultiplier = 6f;
|
||||||
canOverdrive = false;
|
canOverdrive = false;
|
||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
|
|
||||||
|
//it's a wall of course it's supported everywhere
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class PowerTurret extends Turret{
|
|||||||
public PowerTurret(String name){
|
public PowerTurret(String name){
|
||||||
super(name);
|
super(name);
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
|
envEnabled |= Env.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -410,7 +410,7 @@ public class ItemBridge extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean checkAccept(Building source, Tile other){
|
protected boolean checkAccept(Building source, Tile other){
|
||||||
if(linked(source)) return true;
|
if(tile == null || linked(source)) return true;
|
||||||
|
|
||||||
if(linkValid(tile, other)){
|
if(linkValid(tile, other)){
|
||||||
int rel = relativeTo(other);
|
int rel = relativeTo(other);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class MassDriver extends Block{
|
|||||||
hasPower = true;
|
hasPower = true;
|
||||||
outlineIcon = true;
|
outlineIcon = true;
|
||||||
sync = true;
|
sync = true;
|
||||||
|
envEnabled |= Env.space;
|
||||||
|
|
||||||
//point2 is relative
|
//point2 is relative
|
||||||
config(Point2.class, (MassDriverBuild tile, Point2 point) -> tile.link = Point2.pack(point.x + tile.tileX(), point.y + tile.tileY()));
|
config(Point2.class, (MassDriverBuild tile, Point2 point) -> tile.link = Point2.pack(point.x + tile.tileX(), point.y + tile.tileY()));
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class PayloadConveyor extends Block{
|
|||||||
update = true;
|
update = true;
|
||||||
outputsPayload = true;
|
outputsPayload = true;
|
||||||
noUpdateDisabled = true;
|
noUpdateDisabled = true;
|
||||||
|
envEnabled |= Env.space;
|
||||||
sync = true;
|
sync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public class AirBlock extends Floor{
|
|||||||
useColor = false;
|
useColor = false;
|
||||||
wall = this;
|
wall = this;
|
||||||
needsSurface = false;
|
needsSurface = false;
|
||||||
|
canShadow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
24
core/src/mindustry/world/blocks/environment/EmptyFloor.java
Normal file
24
core/src/mindustry/world/blocks/environment/EmptyFloor.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package mindustry.world.blocks.environment;
|
||||||
|
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
public class EmptyFloor extends Floor{
|
||||||
|
|
||||||
|
public EmptyFloor(String name){
|
||||||
|
super(name);
|
||||||
|
variants = 0;
|
||||||
|
canShadow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawBase(Tile tile){
|
||||||
|
//draws only edges, never itself
|
||||||
|
drawEdges(tile);
|
||||||
|
|
||||||
|
Floor floor = tile.overlay();
|
||||||
|
if(floor != Blocks.air && floor != this){
|
||||||
|
floor.drawBase(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ import mindustry.graphics.*;
|
|||||||
import mindustry.graphics.MultiPacker.*;
|
import mindustry.graphics.MultiPacker.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -54,8 +53,6 @@ public class Floor extends Block{
|
|||||||
public boolean playerUnmineable = false;
|
public boolean playerUnmineable = false;
|
||||||
/** Group of blocks that this block does not draw edges on. */
|
/** Group of blocks that this block does not draw edges on. */
|
||||||
public Block blendGroup = this;
|
public Block blendGroup = this;
|
||||||
/** Array of affinities to certain things. */
|
|
||||||
public Attributes attributes = new Attributes();
|
|
||||||
/** Whether this ore generates in maps by default. */
|
/** Whether this ore generates in maps by default. */
|
||||||
public boolean oreDefault = false;
|
public boolean oreDefault = false;
|
||||||
/** Ore generation params. */
|
/** Ore generation params. */
|
||||||
@@ -64,6 +61,8 @@ public class Floor extends Block{
|
|||||||
public Block wall = Blocks.air;
|
public Block wall = Blocks.air;
|
||||||
/** Decoration block. Usually a rock. May be air. */
|
/** Decoration block. Usually a rock. May be air. */
|
||||||
public Block decoration = Blocks.air;
|
public Block decoration = Blocks.air;
|
||||||
|
/** Whether units can draw shadows over this. */
|
||||||
|
public boolean canShadow = true;
|
||||||
/** Whether this overlay needs a surface to be on. False for floating blocks, like spawns. */
|
/** Whether this overlay needs a surface to be on. False for floating blocks, like spawns. */
|
||||||
public boolean needsSurface = true;
|
public boolean needsSurface = true;
|
||||||
|
|
||||||
@@ -116,10 +115,6 @@ public class Floor extends Block{
|
|||||||
//keep default value if not found...
|
//keep default value if not found...
|
||||||
if(wall == null) wall = Blocks.air;
|
if(wall == null) wall = Blocks.air;
|
||||||
|
|
||||||
if(decoration == Blocks.air){
|
|
||||||
decoration = content.blocks().min(b -> b instanceof Prop && b.minfo.mod == null && b.breakable ? mapColor.diff(b.mapColor) : Float.POSITIVE_INFINITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isLiquid && walkEffect == Fx.none){
|
if(isLiquid && walkEffect == Fx.none){
|
||||||
walkEffect = Fx.ripple;
|
walkEffect = Fx.ripple;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
package mindustry.world.blocks.experimental;
|
package mindustry.world.blocks.experimental;
|
||||||
|
|
||||||
|
import mindustry.world.blocks.payloads.*;
|
||||||
|
|
||||||
|
/** @deprecated use Constructor instead. */
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BlockForge extends mindustry.world.blocks.payloads.BlockForge{
|
public class BlockForge extends Constructor{
|
||||||
|
|
||||||
public BlockForge(String name){
|
public BlockForge(String name){
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BlockForgeBuild extends mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild{
|
public class BlockForgeBuild extends Constructor.ConstructorBuild{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package mindustry.world.blocks.experimental;
|
package mindustry.world.blocks.experimental;
|
||||||
|
|
||||||
|
import mindustry.world.blocks.payloads.*;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BlockLoader extends mindustry.world.blocks.payloads.BlockLoader{
|
public class BlockLoader extends PayloadLoader{
|
||||||
|
|
||||||
public BlockLoader(String name){
|
public BlockLoader(String name){
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BlockLoaderBuild extends mindustry.world.blocks.payloads.BlockLoader.BlockLoaderBuild{
|
public class BlockLoaderBuild extends PayloadLoaderBuild{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package mindustry.world.blocks.experimental;
|
package mindustry.world.blocks.experimental;
|
||||||
|
|
||||||
|
import mindustry.world.blocks.payloads.*;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BlockUnloader extends mindustry.world.blocks.payloads.BlockUnloader{
|
public class BlockUnloader extends PayloadUnloader{
|
||||||
|
|
||||||
public BlockUnloader(String name){
|
public BlockUnloader(String name){
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class BlockUnloaderBuild extends mindustry.world.blocks.payloads.BlockUnloader.BlockUnloaderBuild{
|
public class BlockUnloaderBuild extends PayloadUnloaderBuild{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class ArmoredConduit extends Conduit{
|
|||||||
public class ArmoredConduitBuild extends ConduitBuild{
|
public class ArmoredConduitBuild extends ConduitBuild{
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptLiquid(Building source, Liquid liquid){
|
public boolean acceptLiquid(Building source, Liquid liquid){
|
||||||
return super.acceptLiquid(source, liquid) && (source.block instanceof Conduit ||
|
return super.acceptLiquid(source, liquid) && (tile == null || source.block instanceof Conduit ||
|
||||||
source.tile.absoluteRelativeTo(tile.x, tile.y) == rotation);
|
source.tile.absoluteRelativeTo(tile.x, tile.y) == rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
|||||||
public boolean acceptLiquid(Building source, Liquid liquid){
|
public boolean acceptLiquid(Building source, Liquid liquid){
|
||||||
noSleep();
|
noSleep();
|
||||||
return (liquids.current() == liquid || liquids.currentAmount() < 0.2f)
|
return (liquids.current() == liquid || liquids.currentAmount() < 0.2f)
|
||||||
&& ((source.relativeTo(tile.x, tile.y) + 2) % 4 != rotation);
|
&& (tile == null || (source.relativeTo(tile.x, tile.y) + 2) % 4 != rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class LiquidBlock extends Block{
|
|||||||
hasLiquids = true;
|
hasLiquids = true;
|
||||||
group = BlockGroup.liquids;
|
group = BlockGroup.liquids;
|
||||||
outputsLiquid = true;
|
outputsLiquid = true;
|
||||||
|
envEnabled |= Env.space | Env.underwater;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public class LiquidBridge extends ItemBridge{
|
|||||||
outputsLiquid = true;
|
outputsLiquid = true;
|
||||||
canOverdrive = false;
|
canOverdrive = false;
|
||||||
group = BlockGroup.liquids;
|
group = BlockGroup.liquids;
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LiquidBridgeBuild extends ItemBridgeBuild{
|
public class LiquidBridgeBuild extends ItemBridgeBuild{
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ public class LogicBlock extends Block{
|
|||||||
group = BlockGroup.logic;
|
group = BlockGroup.logic;
|
||||||
schematicPriority = 5;
|
schematicPriority = 5;
|
||||||
|
|
||||||
|
//universal, no real requirements
|
||||||
|
envEnabled = Env.any;
|
||||||
|
|
||||||
config(byte[].class, (LogicBuild build, byte[] data) -> build.readCompressed(data, true));
|
config(byte[].class, (LogicBuild build, byte[] data) -> build.readCompressed(data, true));
|
||||||
|
|
||||||
config(Integer.class, (LogicBuild entity, Integer pos) -> {
|
config(Integer.class, (LogicBuild entity, Integer pos) -> {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public class LogicDisplay extends Block{
|
|||||||
solid = true;
|
solid = true;
|
||||||
group = BlockGroup.logic;
|
group = BlockGroup.logic;
|
||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public class MemoryBlock extends Block{
|
|||||||
solid = true;
|
solid = true;
|
||||||
group = BlockGroup.logic;
|
group = BlockGroup.logic;
|
||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class MessageBlock extends Block{
|
|||||||
destructible = true;
|
destructible = true;
|
||||||
group = BlockGroup.logic;
|
group = BlockGroup.logic;
|
||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
|
envEnabled = Env.any;
|
||||||
|
|
||||||
config(String.class, (MessageBuild tile, String text) -> {
|
config(String.class, (MessageBuild tile, String text) -> {
|
||||||
if(text.length() > maxTextLength){
|
if(text.length() > maxTextLength){
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class SwitchBlock extends Block{
|
|||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
autoResetEnabled = false;
|
autoResetEnabled = false;
|
||||||
group = BlockGroup.logic;
|
group = BlockGroup.logic;
|
||||||
|
envEnabled = Env.any;
|
||||||
|
|
||||||
config(Boolean.class, (SwitchBuild entity, Boolean b) -> entity.enabled = b);
|
config(Boolean.class, (SwitchBuild entity, Boolean b) -> entity.enabled = b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,16 +80,16 @@ public class PayloadBlock extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canControlSelect(Player player){
|
public boolean canControlSelect(Unit player){
|
||||||
return !player.unit().spawnedByCore && this.payload == null && acceptUnitPayload(player.unit()) && player.tileOn() != null && player.tileOn().build == this;
|
return !player.spawnedByCore && this.payload == null && acceptUnitPayload(player) && player.tileOn() != null && player.tileOn().build == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onControlSelect(Player player){
|
public void onControlSelect(Unit player){
|
||||||
float x = player.x, y = player.y;
|
float x = player.x, y = player.y;
|
||||||
acceptPlayerPayload(player, p -> payload = (T)p);
|
handleUnitPayload(player, p -> payload = (T)p);
|
||||||
this.payVector.set(x, y).sub(this).clamp(-size * tilesize / 2f, -size * tilesize / 2f, size * tilesize / 2f, size * tilesize / 2f);
|
this.payVector.set(x, y).sub(this).clamp(-size * tilesize / 2f, -size * tilesize / 2f, size * tilesize / 2f, size * tilesize / 2f);
|
||||||
this.payRotation = player.unit().rotation;
|
this.payRotation = player.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ public class Battery extends PowerDistributor{
|
|||||||
outputsPower = true;
|
outputsPower = true;
|
||||||
consumesPower = true;
|
consumesPower = true;
|
||||||
flags = EnumSet.of(BlockFlag.battery);
|
flags = EnumSet.of(BlockFlag.battery);
|
||||||
|
//TODO could be supported everywhere...
|
||||||
|
envEnabled |= Env.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BatteryBuild extends Building{
|
public class BatteryBuild extends Building{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.world.blocks.power;
|
package mindustry.world.blocks.power;
|
||||||
|
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
public class DecayGenerator extends ItemLiquidGenerator{
|
public class DecayGenerator extends ItemLiquidGenerator{
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ public class DecayGenerator extends ItemLiquidGenerator{
|
|||||||
super(true, false, name);
|
super(true, false, name);
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
hasLiquids = false;
|
hasLiquids = false;
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class ImpactReactor extends PowerGenerator{
|
|||||||
flags = EnumSet.of(BlockFlag.reactor, BlockFlag.generator);
|
flags = EnumSet.of(BlockFlag.reactor, BlockFlag.generator);
|
||||||
lightRadius = 115f;
|
lightRadius = 115f;
|
||||||
emitLight = true;
|
emitLight = true;
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import mindustry.graphics.*;
|
|||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.logic.*;
|
import mindustry.logic.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ public class LightBlock extends Block{
|
|||||||
update = true;
|
update = true;
|
||||||
configurable = true;
|
configurable = true;
|
||||||
saveConfig = true;
|
saveConfig = true;
|
||||||
|
envEnabled |= Env.space;
|
||||||
swapDiagonalPlacement = true;
|
swapDiagonalPlacement = true;
|
||||||
|
|
||||||
config(Integer.class, (LightBuild tile, Integer value) -> tile.color = value);
|
config(Integer.class, (LightBuild tile, Integer value) -> tile.color = value);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public class NuclearReactor extends PowerGenerator{
|
|||||||
rebuildable = false;
|
rebuildable = false;
|
||||||
flags = EnumSet.of(BlockFlag.reactor, BlockFlag.generator);
|
flags = EnumSet.of(BlockFlag.reactor, BlockFlag.generator);
|
||||||
schematicPriority = -5;
|
schematicPriority = -5;
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class PowerDiode extends Block{
|
|||||||
group = BlockGroup.power;
|
group = BlockGroup.power;
|
||||||
noUpdateDisabled = true;
|
noUpdateDisabled = true;
|
||||||
schematicPriority = 10;
|
schematicPriority = 10;
|
||||||
|
envEnabled |= Env.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class PowerNode extends PowerBlock{
|
|||||||
swapDiagonalPlacement = true;
|
swapDiagonalPlacement = true;
|
||||||
schematicPriority = -10;
|
schematicPriority = -10;
|
||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
|
envEnabled |= Env.space;
|
||||||
|
|
||||||
config(Integer.class, (entity, value) -> {
|
config(Integer.class, (entity, value) -> {
|
||||||
PowerModule power = entity.power;
|
PowerModule power = entity.power;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class SolarGenerator extends PowerGenerator{
|
|||||||
super(name);
|
super(name);
|
||||||
//remove the BlockFlag.generator flag to make this a lower priority target than other generators.
|
//remove the BlockFlag.generator flag to make this a lower priority target than other generators.
|
||||||
flags = EnumSet.of();
|
flags = EnumSet.of();
|
||||||
|
envEnabled = Env.any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class ThermalGenerator extends PowerGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceOn(Tile tile, Team team){
|
public boolean canPlaceOn(Tile tile, Team team, int rotation){
|
||||||
//make sure there's heat at this location
|
//make sure there's heat at this location
|
||||||
return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(attribute)) > 0.01f;
|
return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(attribute)) > 0.01f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class Drill extends Block{
|
|||||||
/** How many times faster the drill will progress when boosted by liquid. */
|
/** How many times faster the drill will progress when boosted by liquid. */
|
||||||
public float liquidBoostIntensity = 1.6f;
|
public float liquidBoostIntensity = 1.6f;
|
||||||
/** Speed at which the drill speeds up. */
|
/** Speed at which the drill speeds up. */
|
||||||
public float warmupSpeed = 0.02f;
|
public float warmupSpeed = 0.015f;
|
||||||
|
|
||||||
//return variables for countOre
|
//return variables for countOre
|
||||||
protected @Nullable Item returnItem;
|
protected @Nullable Item returnItem;
|
||||||
@@ -108,7 +108,7 @@ public class Drill extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceOn(Tile tile, Team team){
|
public boolean canPlaceOn(Tile tile, Team team, int rotation){
|
||||||
if(isMultiblock()){
|
if(isMultiblock()){
|
||||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||||
if(canMine(other)){
|
if(canMine(other)){
|
||||||
@@ -275,14 +275,14 @@ public class Drill extends Block{
|
|||||||
speed *= efficiency(); // Drill slower when not at full power
|
speed *= efficiency(); // Drill slower when not at full power
|
||||||
|
|
||||||
lastDrillSpeed = (speed * dominantItems * warmup) / (drillTime + hardnessDrillMultiplier * dominantItem.hardness);
|
lastDrillSpeed = (speed * dominantItems * warmup) / (drillTime + hardnessDrillMultiplier * dominantItem.hardness);
|
||||||
warmup = Mathf.lerpDelta(warmup, speed, warmupSpeed);
|
warmup = Mathf.approachDelta(warmup, speed, warmupSpeed);
|
||||||
progress += delta() * dominantItems * speed * warmup;
|
progress += delta() * dominantItems * speed * warmup;
|
||||||
|
|
||||||
if(Mathf.chanceDelta(updateEffectChance * warmup))
|
if(Mathf.chanceDelta(updateEffectChance * warmup))
|
||||||
updateEffect.at(x + Mathf.range(size * 2f), y + Mathf.range(size * 2f));
|
updateEffect.at(x + Mathf.range(size * 2f), y + Mathf.range(size * 2f));
|
||||||
}else{
|
}else{
|
||||||
lastDrillSpeed = 0f;
|
lastDrillSpeed = 0f;
|
||||||
warmup = Mathf.lerpDelta(warmup, 0f, warmupSpeed);
|
warmup = Mathf.approachDelta(warmup, 0f, warmupSpeed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,7 @@ public class Incinerator extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
if(consValid() && efficiency() > 0.9f){
|
heat = Mathf.approachDelta(heat, consValid() && efficiency() > 0.9f ? 1f : 0f, 0.04f);
|
||||||
heat = Mathf.lerpDelta(heat, 1f, 0.04f);
|
|
||||||
}else{
|
|
||||||
heat = Mathf.lerpDelta(heat, 0f, 0.02f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class Pump extends LiquidBlock{
|
|||||||
super(name);
|
super(name);
|
||||||
group = BlockGroup.liquids;
|
group = BlockGroup.liquids;
|
||||||
floating = true;
|
floating = true;
|
||||||
|
envEnabled = Env.terrestrial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,7 +62,7 @@ public class Pump extends LiquidBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceOn(Tile tile, Team team){
|
public boolean canPlaceOn(Tile tile, Team team, int rotation){
|
||||||
if(isMultiblock()){
|
if(isMultiblock()){
|
||||||
Liquid last = null;
|
Liquid last = null;
|
||||||
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ public class SolidPump extends Pump{
|
|||||||
public SolidPump(String name){
|
public SolidPump(String name){
|
||||||
super(name);
|
super(name);
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
|
//only supports ground by default
|
||||||
|
envEnabled = Env.terrestrial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,7 +65,7 @@ public class SolidPump extends Pump{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPlaceOn(Tile tile, Team team){
|
public boolean canPlaceOn(Tile tile, Team team, int rotation){
|
||||||
float sum = tile.getLinkedTilesAs(this, tempTiles).sumf(t -> canPump(t) ? baseEfficiency + (attribute != null ? t.floor().attributes.get(attribute) : 0f) : 0f);
|
float sum = tile.getLinkedTilesAs(this, tempTiles).sumf(t -> canPump(t) ? baseEfficiency + (attribute != null ? t.floor().attributes.get(attribute) : 0f) : 0f);
|
||||||
return sum > 0.00001f;
|
return sum > 0.00001f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class LiquidSource extends Block{
|
|||||||
noUpdateDisabled = true;
|
noUpdateDisabled = true;
|
||||||
displayFlow = false;
|
displayFlow = false;
|
||||||
group = BlockGroup.liquids;
|
group = BlockGroup.liquids;
|
||||||
|
envEnabled = Env.any;
|
||||||
|
|
||||||
config(Liquid.class, (LiquidSourceBuild tile, Liquid l) -> tile.source = l);
|
config(Liquid.class, (LiquidSourceBuild tile, Liquid l) -> tile.source = l);
|
||||||
configClear((LiquidSourceBuild tile) -> tile.source = null);
|
configClear((LiquidSourceBuild tile) -> tile.source = null);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user