Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b1c60c24f | ||
|
|
8b8d990852 | ||
|
|
6583cc0b5d | ||
|
|
5c3ae425ae | ||
|
|
744b1b2037 | ||
|
|
a313ca8a26 | ||
|
|
87204df3ee | ||
|
|
bc70c08820 | ||
|
|
2c2828617f | ||
|
|
a451ad895c | ||
|
|
d13b69c36f | ||
|
|
d64f603e08 | ||
|
|
3d2c094056 | ||
|
|
64e99f613e | ||
|
|
51b4078288 | ||
|
|
db8d099fcc | ||
|
|
002be46915 | ||
|
|
9fa2691b02 | ||
|
|
6686584003 | ||
|
|
78c8c57649 | ||
|
|
ca65fd31e5 | ||
|
|
e2109f2f56 | ||
|
|
6b63cd7a46 | ||
|
|
e19c857d74 | ||
|
|
b18f418c61 | ||
|
|
12ee38476c | ||
|
|
48c8357ff7 | ||
|
|
a0702559f3 | ||
|
|
55db91e53e | ||
|
|
a333fa3722 | ||
|
|
5284750c6a | ||
|
|
9c616fd03b | ||
|
|
d4bee41103 | ||
|
|
2e586c4403 | ||
|
|
129f21e3a9 | ||
|
|
435f15a450 | ||
|
|
3eac8cb6ad | ||
|
|
ea96bf2675 | ||
|
|
e4c3664cc6 | ||
|
|
664cd6a3a0 | ||
|
|
c26a9bd123 | ||
|
|
5008573aa5 | ||
|
|
395f7193ea | ||
|
|
775e17a726 | ||
|
|
900ec8db6a | ||
|
|
e23a7c213c | ||
|
|
96513e4967 | ||
|
|
b64df565a4 | ||
|
|
382e27e1e4 | ||
|
|
0dd95e736d | ||
|
|
0ae6a33971 | ||
|
|
380c9ab113 | ||
|
|
1028ade80d | ||
|
|
a8e34381ef | ||
|
|
5f5987cef2 | ||
|
|
430538ea7e | ||
|
|
ee966d1198 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -21,7 +21,7 @@ assignees: ''
|
|||||||
|
|
||||||
If you remove the line above without reading it properly and understanding what it means, I will reap your soul. Even if you're playing on someone's server, you can still save the game to a slot.
|
If you remove the line above without reading it properly and understanding what it means, I will reap your soul. Even if you're playing on someone's server, you can still save the game to a slot.
|
||||||
|
|
||||||
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
|
**(Crash) logs**: *Either crash reports from the crash folder, or the file you get when you go into Settings -> Game Data -> Export Crash logs. REQUIRED if you are reporting a crash.*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/push.yml
vendored
2
.github/workflows/push.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
java-version: 14
|
java-version: 14
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
run: ./gradlew test
|
run: ./gradlew clean cleanTest test
|
||||||
- name: Trigger BE build
|
- name: Trigger BE build
|
||||||
if: ${{ github.repository == 'Anuken/Mindustry' }}
|
if: ${{ github.repository == 'Anuken/Mindustry' }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
52
ISSUES.md
Normal file
52
ISSUES.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Why was my issue closed?
|
||||||
|
|
||||||
|
This document goes over some common causes for issue closures.
|
||||||
|
|
||||||
|
## You did not fill in the template
|
||||||
|
|
||||||
|
I can't debug the problem unless you provide the information the template asks for.
|
||||||
|
If you cannot put in the effort to fill out a template, then don't expect me to put in the effort to fix it.
|
||||||
|
|
||||||
|
## Your issue was already reported
|
||||||
|
|
||||||
|
If the problem in your issue has already been encountered before, it will be closed - especially if your report doesn't provide any new information.
|
||||||
|
Make sure you search the *closed* issues before making an issue.
|
||||||
|
|
||||||
|
I do not link the specific issue(s) that report the same problem, because searching takes time - if you're interested in finding them, you should be able to do so without my help.
|
||||||
|
|
||||||
|
To be clear: I do **not** expect users to look at *all* previous issues, or do a comprehensive stack trace analysis to see if their crash was already reported.
|
||||||
|
|
||||||
|
## Your issue was already fixed
|
||||||
|
|
||||||
|
The problem you reported has been addressed. Note that this does **not** mean that the latest stable version of Mindustry has the fix!
|
||||||
|
It simply means that I have committed (or am about to commit) a patch that fixes it *on the current development branch*.
|
||||||
|
|
||||||
|
## Your issue is missing a crash report or log
|
||||||
|
|
||||||
|
If the game crashes without a specific cause, and you don't send me a log, I can't fix it. There is no way for me to know what went wrong.
|
||||||
|
|
||||||
|
During a normal crash, the game should tell you where the log is saved. If not, you should still be able to look in the game's crash folder on most operating systems, or export the logs in *Settings -> Game Data -> Export Crash Logs*.
|
||||||
|
|
||||||
|
## Your issue is missing saves or screenshots
|
||||||
|
|
||||||
|
Even if you think your problem happens everywhere and saves/screenshots are redundant, this is frequently not the case.
|
||||||
|
If I cannot reproduce the problem on my own saves and you have not linked any of your own, then the problem is likely to be save-specific. If you do not send me any, the problem cannot be investigated further.
|
||||||
|
|
||||||
|
## Your issue is related to an external program
|
||||||
|
|
||||||
|
If Mindustry causes something else to crash or misbehave, I am very unlikely to fix it. Unless the problem is serious, widespread and/or clearly a bug *in Mindustry*, it is not my responsibility.
|
||||||
|
|
||||||
|
Similarly, if you use another (invasive) program to change how Mindustry works, and something goes wrong, that is not my problem. Don't do it.
|
||||||
|
|
||||||
|
## Your issue is caused by mods
|
||||||
|
|
||||||
|
Crashes and bugs related to installed mods should be reported in the relevant mod repository, not here.
|
||||||
|
*Note that problems with the Mindustry modding API are a separate problem, and do not apply.*
|
||||||
|
|
||||||
|
## I cannot reproduce your issue
|
||||||
|
|
||||||
|
If I follow your instructions and am repeatedly unable to reproduce the problem you've reported, then it is very unlikely to be fixed.
|
||||||
|
Either the problem is device-specific, or there is not enough information given for me to be able to reproduce it.
|
||||||
|
|
||||||
|
I may attempt to change some code if I think it will make the issue less likely to occur, but without knowing for sure, the issue cannot be considered truly "fixed".
|
||||||
|
As I cannot make any further progress on the problem, there is no reason to keep it open. If it is a common bug/crash, other people will come along with information that may shed some light on the issue.
|
||||||
@@ -253,18 +253,22 @@ project(":ios"){
|
|||||||
|
|
||||||
task incrementConfig{
|
task incrementConfig{
|
||||||
def vfile = file('robovm.properties')
|
def vfile = file('robovm.properties')
|
||||||
|
def bversion = getBuildVersion()
|
||||||
def props = new Properties()
|
def props = new Properties()
|
||||||
if(vfile.exists()){
|
if(vfile.exists()){
|
||||||
props.load(new FileInputStream(vfile))
|
props.load(new FileInputStream(vfile))
|
||||||
}else{
|
}else{
|
||||||
props['app.id'] = 'io.anuke.mindustry'
|
props['app.id'] = 'io.anuke.mindustry'
|
||||||
props['app.version'] = '5.0'
|
props['app.version'] = '6.0'
|
||||||
props['app.mainclass'] = 'mindustry.IOSLauncher'
|
props['app.mainclass'] = 'mindustry.IOSLauncher'
|
||||||
props['app.executable'] = 'IOSLauncher'
|
props['app.executable'] = 'IOSLauncher'
|
||||||
props['app.name'] = 'Mindustry'
|
props['app.name'] = 'Mindustry'
|
||||||
}
|
}
|
||||||
|
|
||||||
props['app.build'] = (!props.containsKey("app.build") ? 40 : props['app.build'].toInteger() + 1) + ""
|
props['app.build'] = (!props.containsKey("app.build") ? 40 : props['app.build'].toInteger() + 1) + ""
|
||||||
|
if(bversion != "custom build"){
|
||||||
|
props['app.version'] = versionNumber + "." + bversion + (bversion.contains(".") ? "" : ".0")
|
||||||
|
}
|
||||||
props.store(vfile.newWriter(), null)
|
props.store(vfile.newWriter(), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ stat.delivered = Resources Launched:
|
|||||||
stat.playtime = Time Played:[accent] {0}
|
stat.playtime = Time Played:[accent] {0}
|
||||||
stat.rank = Final Rank: [accent]{0}
|
stat.rank = Final Rank: [accent]{0}
|
||||||
|
|
||||||
globalitems = [accent]Global Items
|
globalitems = [accent]Total Items
|
||||||
map.delete = Are you sure you want to delete the map "[accent]{0}[]"?
|
map.delete = Are you sure you want to delete the map "[accent]{0}[]"?
|
||||||
level.highscore = High Score: [accent]{0}
|
level.highscore = High Score: [accent]{0}
|
||||||
level.select = Level Select
|
level.select = Level Select
|
||||||
@@ -196,6 +196,7 @@ servers.local = Local Servers
|
|||||||
servers.remote = Remote Servers
|
servers.remote = Remote Servers
|
||||||
servers.global = Community Servers
|
servers.global = Community Servers
|
||||||
|
|
||||||
|
servers.disclaimer = Community servers are [accent]not[] owned or controlled by the developer.\n\nServers may contain user-generated content that is not appropriate for all ages.
|
||||||
servers.showhidden = Show Hidden Servers
|
servers.showhidden = Show Hidden Servers
|
||||||
server.shown = Shown
|
server.shown = Shown
|
||||||
server.hidden = Hidden
|
server.hidden = Hidden
|
||||||
@@ -1279,6 +1280,9 @@ hint.payloadDrop.mobile = [accent]Tap and hold[] an empty location to drop a pay
|
|||||||
hint.waveFire = [accent]Wave[] turrets with water as ammunition will automatically put out nearby fires.
|
hint.waveFire = [accent]Wave[] turrets with water as ammunition will automatically put out nearby fires.
|
||||||
hint.generator = \uf879 [accent]Combustion Generators[] burn coal and transmit power to adjacent blocks.\n\nPower transmission range can be extended with \uf87f [accent]Power Nodes[].
|
hint.generator = \uf879 [accent]Combustion Generators[] burn coal and transmit power to adjacent blocks.\n\nPower transmission range can be extended with \uf87f [accent]Power Nodes[].
|
||||||
hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]Copper[] and [accent]Lead[] is [scarlet]not effective[].\n\nUse higher tier turrets or \uf835 [accent]Graphite[] \uf861Duo/\uf859Salvo ammunition to take Guardians down.
|
hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]Copper[] and [accent]Lead[] is [scarlet]not effective[].\n\nUse higher tier turrets or \uf835 [accent]Graphite[] \uf861Duo/\uf859Salvo ammunition to take Guardians down.
|
||||||
|
hint.coreUpgrade = Cores can be upgraded by [accent]placing higher-tier cores over them[].\n\nPlace a [accent]Foundation[] core over the [accent]Shard[] core. Make sure it is free from nearby obstructions.
|
||||||
|
hint.presetLaunch = Gray [accent]landing zone sectors[], such as [accent]Frozen Forest[], can be launched to from anywhere. They do not require capture of nearby territory.\n\n[accent]Numbered sectors[], such as this one, are [accent]optional[].
|
||||||
|
hint.coreIncinerate = After the core is filled to capacity with an item, any extra items of that type it receives will be [accent]incinerated[].
|
||||||
|
|
||||||
item.copper.description = Used in all types of construction and ammunition.
|
item.copper.description = Used in all types of construction and ammunition.
|
||||||
item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced.
|
item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced.
|
||||||
@@ -1473,7 +1477,7 @@ unit.zenith.description = Fires salvos of missiles at all nearby enemies.
|
|||||||
unit.antumbra.description = Fires a barrage of bullets at all nearby enemies.
|
unit.antumbra.description = Fires a barrage of bullets at all nearby enemies.
|
||||||
unit.eclipse.description = Fires two piercing lasers and a barrage of flak at all nearby enemies.
|
unit.eclipse.description = Fires two piercing lasers and a barrage of flak at all nearby enemies.
|
||||||
unit.mono.description = Automatically mines copper and lead, depositing it into the core.
|
unit.mono.description = Automatically mines copper and lead, depositing it into the core.
|
||||||
unit.poly.description = Automatically rebuilds damaged structures and assists other units in construction.
|
unit.poly.description = Automatically rebuilds destroyed structures and assists other units in construction.
|
||||||
unit.mega.description = Automatically repairs damaged structures. Capable of carrying blocks and small ground units.
|
unit.mega.description = Automatically repairs damaged structures. Capable of carrying blocks and small ground units.
|
||||||
unit.quad.description = Drops large bombs on ground targets, repairing allied structures and damaging enemies. Capable of carrying medium-sized ground units.
|
unit.quad.description = Drops large bombs on ground targets, repairing allied structures and damaging enemies. Capable of carrying medium-sized ground units.
|
||||||
unit.oct.description = Protects nearby allies with its regenerating shield. Capable of carrying most ground units.
|
unit.oct.description = Protects nearby allies with its regenerating shield. Capable of carrying most ground units.
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class Liquids implements ContentList{
|
|||||||
|
|
||||||
water = new Liquid("water", Color.valueOf("596ab8")){{
|
water = new Liquid("water", Color.valueOf("596ab8")){{
|
||||||
heatCapacity = 0.4f;
|
heatCapacity = 0.4f;
|
||||||
|
alwaysUnlocked = true;
|
||||||
effect = StatusEffects.wet;
|
effect = StatusEffects.wet;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
|
|
||||||
node(kiln, Seq.with(new SectorComplete(craters)), () -> {
|
node(kiln, Seq.with(new SectorComplete(craters)), () -> {
|
||||||
|
node(pulverizer, () -> {
|
||||||
node(incinerator, () -> {
|
node(incinerator, () -> {
|
||||||
node(melter, () -> {
|
node(melter, () -> {
|
||||||
node(surgeSmelter, () -> {
|
node(surgeSmelter, () -> {
|
||||||
@@ -161,12 +162,10 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
|
|
||||||
node(separator, () -> {
|
node(separator, () -> {
|
||||||
node(pulverizer, () -> {
|
|
||||||
node(disassembler, () -> {
|
node(disassembler, () -> {
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
node(cryofluidMixer, () -> {
|
node(cryofluidMixer, () -> {
|
||||||
|
|
||||||
@@ -174,6 +173,7 @@ public class TechTree implements ContentList{
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
node(microProcessor, () -> {
|
node(microProcessor, () -> {
|
||||||
node(switchBlock, () -> {
|
node(switchBlock, () -> {
|
||||||
@@ -714,8 +714,14 @@ public class TechTree implements ContentList{
|
|||||||
finishedRequirements[i] = new ItemStack(requirements[i].item, Core.settings == null ? 0 : Core.settings.getInt("req-" + content.name + "-" + requirements[i].item.name));
|
finishedRequirements[i] = new ItemStack(requirements[i].item, Core.settings == null ? 0 : Core.settings.getInt("req-" + content.name + "-" + requirements[i].item.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var used = new ObjectSet<Content>();
|
||||||
|
|
||||||
//add dependencies as objectives.
|
//add dependencies as objectives.
|
||||||
content.getDependencies(d -> objectives.add(new Research(d)));
|
content.getDependencies(d -> {
|
||||||
|
if(used.add(d)){
|
||||||
|
objectives.add(new Research(d));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
map.put(content, this);
|
map.put(content, this);
|
||||||
all.add(this);
|
all.add(this);
|
||||||
|
|||||||
@@ -1624,7 +1624,7 @@ public class UnitTypes implements ContentList{
|
|||||||
xRand = 8f;
|
xRand = 8f;
|
||||||
shotDelay = 1f;
|
shotDelay = 1f;
|
||||||
|
|
||||||
bullet = new MissileBulletType(4.2f, 40){{
|
bullet = new MissileBulletType(4.2f, 42){{
|
||||||
homingPower = 0.12f;
|
homingPower = 0.12f;
|
||||||
width = 8f;
|
width = 8f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
@@ -1634,7 +1634,7 @@ public class UnitTypes implements ContentList{
|
|||||||
keepVelocity = false;
|
keepVelocity = false;
|
||||||
splashDamageRadius = 35f;
|
splashDamageRadius = 35f;
|
||||||
splashDamage = 45f;
|
splashDamage = 45f;
|
||||||
lifetime = 56f;
|
lifetime = 62f;
|
||||||
trailColor = Pal.bulletYellowBack;
|
trailColor = Pal.bulletYellowBack;
|
||||||
backColor = Pal.bulletYellowBack;
|
backColor = Pal.bulletYellowBack;
|
||||||
frontColor = Pal.bulletYellow;
|
frontColor = Pal.bulletYellow;
|
||||||
@@ -1662,11 +1662,11 @@ public class UnitTypes implements ContentList{
|
|||||||
shots = 3;
|
shots = 3;
|
||||||
shotDelay = 4f;
|
shotDelay = 4f;
|
||||||
inaccuracy = 1f;
|
inaccuracy = 1f;
|
||||||
bullet = new BasicBulletType(7f, 55){{
|
bullet = new BasicBulletType(7f, 57){{
|
||||||
width = 13f;
|
width = 13f;
|
||||||
height = 19f;
|
height = 19f;
|
||||||
shootEffect = Fx.shootBig;
|
shootEffect = Fx.shootBig;
|
||||||
lifetime = 30f;
|
lifetime = 35f;
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class Weathers implements ContentList{
|
|||||||
attrs.set(Attribute.spores, 1f);
|
attrs.set(Attribute.spores, 1f);
|
||||||
attrs.set(Attribute.light, -0.15f);
|
attrs.set(Attribute.light, -0.15f);
|
||||||
status = StatusEffects.sporeSlowed;
|
status = StatusEffects.sporeSlowed;
|
||||||
opacityMultiplier = 0.75f;
|
opacityMultiplier = 0.5f;
|
||||||
force = 0.1f;
|
force = 0.1f;
|
||||||
sound = Sounds.wind;
|
sound = Sounds.wind;
|
||||||
soundVol = 0.7f;
|
soundVol = 0.7f;
|
||||||
|
|||||||
@@ -10,21 +10,22 @@ import arc.scene.style.*;
|
|||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.*;
|
||||||
import mindustry.audio.*;
|
import mindustry.audio.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.content.TechTree.*;
|
import mindustry.content.TechTree.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.game.Objectives.*;
|
import mindustry.game.Objectives.*;
|
||||||
|
import mindustry.game.*;
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
import mindustry.io.SaveIO.*;
|
import mindustry.io.SaveIO.*;
|
||||||
import mindustry.maps.*;
|
|
||||||
import mindustry.maps.Map;
|
import mindustry.maps.Map;
|
||||||
|
import mindustry.maps.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
@@ -506,6 +507,13 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
settings.put("fullscreen", !full);
|
settings.put("fullscreen", !full);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Float.isNaN(Vars.player.x) || Float.isNaN(Vars.player.y)){
|
||||||
|
player.set(0, 0);
|
||||||
|
if(!player.dead()) player.unit().kill();
|
||||||
|
}
|
||||||
|
if(Float.isNaN(camera.position.x)) camera.position.x = world.unitWidth()/2f;
|
||||||
|
if(Float.isNaN(camera.position.y)) camera.position.y = world.unitHeight()/2f;
|
||||||
|
|
||||||
if(state.isGame()){
|
if(state.isGame()){
|
||||||
input.update();
|
input.update();
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
Core.scene = new Scene();
|
Core.scene = new Scene();
|
||||||
Core.input.addProcessor(Core.scene);
|
Core.input.addProcessor(Core.scene);
|
||||||
|
|
||||||
|
int[] insets = Core.graphics.getSafeInsets();
|
||||||
|
Core.scene.marginLeft = insets[0];
|
||||||
|
Core.scene.marginRight = insets[1];
|
||||||
|
Core.scene.marginTop = insets[2];
|
||||||
|
Core.scene.marginBottom = insets[3];
|
||||||
|
|
||||||
Tex.load();
|
Tex.load();
|
||||||
Icon.load();
|
Icon.load();
|
||||||
Styles.load();
|
Styles.load();
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import arc.graphics.g2d.*;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.content.TechTree.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
@@ -42,6 +44,11 @@ public abstract class UnlockableContent extends MappableContent{
|
|||||||
this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false);
|
this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the tech node for this content. may be null. */
|
||||||
|
public @Nullable TechNode node(){
|
||||||
|
return TechTree.get(this);
|
||||||
|
}
|
||||||
|
|
||||||
public String displayDescription(){
|
public String displayDescription(){
|
||||||
return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName());
|
return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ public class ContinuousLaserBulletType extends BulletType{
|
|||||||
@Override
|
@Override
|
||||||
public float estimateDPS(){
|
public float estimateDPS(){
|
||||||
//assume firing duration is about 100 by default, may not be accurate there's no way of knowing in this method
|
//assume firing duration is about 100 by default, may not be accurate there's no way of knowing in this method
|
||||||
return damage * 100f / 5f;
|
//assume it pierces 3 blocks/units
|
||||||
|
return damage * 100f / 5f * 3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import mindustry.gen.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
|
||||||
public class LaserBoltBulletType extends BasicBulletType{
|
public class LaserBoltBulletType extends BasicBulletType{
|
||||||
protected float height = 7f, width = 2f;
|
public float width = 2f, height = 7f;
|
||||||
|
|
||||||
public LaserBoltBulletType(float speed, float damage){
|
public LaserBoltBulletType(float speed, float damage){
|
||||||
super(speed, damage);
|
super(speed, damage);
|
||||||
|
|||||||
@@ -40,9 +40,10 @@ public class LaserBulletType extends BulletType{
|
|||||||
this(1f);
|
this(1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//assume it pierces at least 3 blocks
|
||||||
@Override
|
@Override
|
||||||
public float estimateDPS(){
|
public float estimateDPS(){
|
||||||
return super.estimateDPS() * 2f;
|
return super.estimateDPS() * 3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
|||||||
plans.removeFirst();
|
plans.removeFirst();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}else if(tile.team() != team){
|
}else if(tile.team() != team && tile.team() != Team.derelict){
|
||||||
plans.removeFirst();
|
plans.removeFirst();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
//region utility methods
|
//region utility methods
|
||||||
|
|
||||||
public void addPlan(boolean checkPrevious){
|
public void addPlan(boolean checkPrevious){
|
||||||
if(!block.rebuildable) return;
|
if(!block.rebuildable || (team == state.rules.defaultTeam && state.isCampaign() && !block.isVisible())) return;
|
||||||
|
|
||||||
if(self() instanceof ConstructBuild entity){
|
if(self() instanceof ConstructBuild entity){
|
||||||
//update block to reflect the fact that something was being constructed
|
//update block to reflect the fact that something was being constructed
|
||||||
@@ -1099,8 +1099,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
public void displayBars(Table table){
|
public void displayBars(Table table){
|
||||||
for(Func<Building, Bar> bar : block.bars.list()){
|
for(Func<Building, Bar> bar : block.bars.list()){
|
||||||
|
//TODO fix conclusively
|
||||||
|
try{
|
||||||
table.add(bar.get(self())).growX();
|
table.add(bar.get(self())).growX();
|
||||||
table.row();
|
table.row();
|
||||||
|
}catch(ClassCastException e){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,13 +68,12 @@ public class Schematics implements Loadable{
|
|||||||
shadowBuffer.dispose();
|
shadowBuffer.dispose();
|
||||||
if(errorTexture != null){
|
if(errorTexture != null){
|
||||||
errorTexture.dispose();
|
errorTexture.dispose();
|
||||||
|
errorTexture = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(ClientLoadEvent.class, event -> {
|
Events.on(ClientLoadEvent.class, event -> {
|
||||||
Pixmap pixmap = Core.atlas.getPixmap("error").crop();
|
errorTexture = new Texture("sprites/error.png");
|
||||||
errorTexture = new Texture(pixmap);
|
|
||||||
pixmap.dispose();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class SectorInfo{
|
|||||||
public boolean shown = false;
|
public boolean shown = false;
|
||||||
|
|
||||||
/** Special variables for simulation. */
|
/** Special variables for simulation. */
|
||||||
public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps;
|
public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps, curEnemyHealth, curEnemyDps;
|
||||||
/** Wave where first boss shows up. */
|
/** Wave where first boss shows up. */
|
||||||
public int bossWave = -1;
|
public int bossWave = -1;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import mindustry.type.*;
|
|||||||
import static mindustry.content.UnitTypes.*;
|
import static mindustry.content.UnitTypes.*;
|
||||||
|
|
||||||
public class Waves{
|
public class Waves{
|
||||||
public static final int waveVersion = 4;
|
public static final int waveVersion = 5;
|
||||||
|
|
||||||
private Seq<SpawnGroup> spawns;
|
private Seq<SpawnGroup> spawns;
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ public class Waves{
|
|||||||
int cap = 150;
|
int cap = 150;
|
||||||
|
|
||||||
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
|
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
|
||||||
float[] scaling = {1, 1.5f, 3f, 4f, 5f};
|
float[] scaling = {1, 2f, 3f, 4f, 5f};
|
||||||
|
|
||||||
Intc createProgression = start -> {
|
Intc createProgression = start -> {
|
||||||
//main sequence
|
//main sequence
|
||||||
|
|||||||
@@ -35,11 +35,18 @@ public class LoadRenderer implements Disposable{
|
|||||||
private Mesh mesh = MeshBuilder.buildHex(colorRed, 2, true, 1f);
|
private Mesh mesh = MeshBuilder.buildHex(colorRed, 2, true, 1f);
|
||||||
private Camera3D cam = new Camera3D();
|
private Camera3D cam = new Camera3D();
|
||||||
private int lastLength = -1;
|
private int lastLength = -1;
|
||||||
private FxProcessor fx = new FxProcessor(Format.rgba8888, 2, 2, false, true);
|
private FxProcessor fx;
|
||||||
private WindowedMean renderTimes = new WindowedMean(20);
|
private WindowedMean renderTimes = new WindowedMean(20);
|
||||||
private long lastFrameTime;
|
private long lastFrameTime;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
//some systems don't support rgba8888 w/ a stencil buffer
|
||||||
|
try{
|
||||||
|
fx = new FxProcessor(Format.rgba8888, 2, 2, false, true);
|
||||||
|
}catch(Exception e){
|
||||||
|
fx = new FxProcessor(Format.rgb565, 2, 2, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
//vignetting is probably too much
|
//vignetting is probably too much
|
||||||
//fx.addEffect(new VignettingFilter(false));
|
//fx.addEffect(new VignettingFilter(false));
|
||||||
fx.addEffect(new BloomFilter());
|
fx.addEffect(new BloomFilter());
|
||||||
|
|||||||
@@ -836,7 +836,6 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
if(type == null) return;
|
if(type == null) return;
|
||||||
|
|
||||||
boolean omni = unit.type.omniMovement;
|
boolean omni = unit.type.omniMovement;
|
||||||
boolean ground = unit.isGrounded();
|
|
||||||
boolean allowHealing = type.canHeal;
|
boolean allowHealing = type.canHeal;
|
||||||
boolean validHealTarget = allowHealing && target instanceof Building && ((Building)target).isValid() && target.team() == unit.team &&
|
boolean validHealTarget = allowHealing && target instanceof Building && ((Building)target).isValid() && target.team() == unit.team &&
|
||||||
((Building)target).damaged() && target.within(unit, type.range);
|
((Building)target).damaged() && target.within(unit, type.range);
|
||||||
|
|||||||
@@ -83,8 +83,9 @@ public class JsonIO{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Sector read(Json json, JsonValue jsonData, Class type){
|
public Sector read(Json json, JsonValue jsonData, Class type){
|
||||||
String[] split = jsonData.asString().split("-");
|
String name = jsonData.asString();
|
||||||
return Vars.content.<Planet>getByName(ContentType.planet, split[0]).sectors.get(Integer.parseInt(split[1]));
|
int idx = name.lastIndexOf('-');
|
||||||
|
return Vars.content.<Planet>getByName(ContentType.planet, name.substring(0, idx)).sectors.get(Integer.parseInt(name.substring(idx + 1)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ public class SectorDamage{
|
|||||||
enemyHealth += info.bossHealth;
|
enemyHealth += info.bossHealth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(i == waveBegin){
|
||||||
|
enemyDps += info.curEnemyDps;
|
||||||
|
enemyHealth += info.curEnemyHealth;
|
||||||
|
}
|
||||||
|
|
||||||
//happens due to certain regressions
|
//happens due to certain regressions
|
||||||
if(enemyHealth < 0 || enemyDps < 0) continue;
|
if(enemyHealth < 0 || enemyDps < 0) continue;
|
||||||
|
|
||||||
@@ -293,18 +298,19 @@ public class SectorDamage{
|
|||||||
//skip player
|
//skip player
|
||||||
if(unit.isPlayer()) continue;
|
if(unit.isPlayer()) continue;
|
||||||
|
|
||||||
if(unit.team == state.rules.defaultTeam){
|
|
||||||
//scale health based on armor - yes, this is inaccurate, but better than nothing
|
//scale health based on armor - yes, this is inaccurate, but better than nothing
|
||||||
float healthMult = 1f + Mathf.clamp(unit.armor / 20f);
|
float healthMult = 1f + Mathf.clamp(unit.armor / 20f);
|
||||||
|
|
||||||
|
if(unit.team == state.rules.defaultTeam){
|
||||||
sumHealth += unit.health*healthMult + unit.shield;
|
sumHealth += unit.health*healthMult + unit.shield;
|
||||||
sumDps += unit.type.dpsEstimate;
|
sumDps += unit.type.dpsEstimate;
|
||||||
if(unit.abilities.find(a -> a instanceof RepairFieldAbility) instanceof RepairFieldAbility h){
|
if(unit.abilities.find(a -> a instanceof RepairFieldAbility) instanceof RepairFieldAbility h){
|
||||||
sumRps += h.amount / h.reload * 60f;
|
sumRps += h.amount / h.reload * 60f;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
curEnemyDps += unit.type.dpsEstimate;
|
float bossMult = unit.isBoss() ? 3f : 1f;
|
||||||
curEnemyHealth += unit.health;
|
curEnemyDps += unit.type.dpsEstimate * unit.damageMultiplier() * bossMult;
|
||||||
|
curEnemyHealth += unit.health * healthMult * unit.healthMultiplier() * bossMult + unit.shield;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,12 +322,6 @@ public class SectorDamage{
|
|||||||
for(int wave = state.wave; wave < state.wave + 10; wave ++){
|
for(int wave = state.wave; wave < state.wave + 10; wave ++){
|
||||||
float sumWaveDps = 0f, sumWaveHealth = 0f;
|
float sumWaveDps = 0f, sumWaveHealth = 0f;
|
||||||
|
|
||||||
//first wave has to take into account current dps
|
|
||||||
if(wave == state.wave){
|
|
||||||
sumWaveDps += curEnemyDps;
|
|
||||||
sumWaveHealth += curEnemyHealth;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(SpawnGroup group : state.rules.spawns){
|
for(SpawnGroup group : state.rules.spawns){
|
||||||
float healthMult = 1f + Mathf.clamp(group.type.armor / 20f);
|
float healthMult = 1f + Mathf.clamp(group.type.armor / 20f);
|
||||||
StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect);
|
StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect);
|
||||||
@@ -369,6 +369,11 @@ public class SectorDamage{
|
|||||||
info.sumDps = sumDps * 1.05f;
|
info.sumDps = sumDps * 1.05f;
|
||||||
info.sumRps = sumRps;
|
info.sumRps = sumRps;
|
||||||
|
|
||||||
|
float cmult = 1.5f;
|
||||||
|
|
||||||
|
info.curEnemyDps = curEnemyDps*cmult;
|
||||||
|
info.curEnemyHealth = curEnemyHealth*cmult;
|
||||||
|
|
||||||
info.wavesSurvived = getWavesSurvived(info);
|
info.wavesSurvived = getWavesSurvived(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -356,8 +356,9 @@ public class JoinDialog extends BaseDialog{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Table[] groupTable = {null};
|
||||||
|
|
||||||
//table containing all groups
|
//table containing all groups
|
||||||
global.table(g -> {
|
|
||||||
for(String address : group.addresses){
|
for(String address : group.addresses){
|
||||||
String resaddress = address.contains(":") ? address.split(":")[0] : address;
|
String resaddress = address.contains(":") ? address.split(":")[0] : address;
|
||||||
int resport = address.contains(":") ? Strings.parseInt(address.split(":")[1]) : port;
|
int resport = address.contains(":") ? Strings.parseInt(address.split(":")[1]) : port;
|
||||||
@@ -366,8 +367,10 @@ public class JoinDialog extends BaseDialog{
|
|||||||
res.port = resport;
|
res.port = resport;
|
||||||
|
|
||||||
//add header
|
//add header
|
||||||
if(g.getChildren().isEmpty()){
|
if(groupTable[0] == null){
|
||||||
g.table(head -> {
|
global.table(t -> groupTable[0] = t).row();
|
||||||
|
|
||||||
|
groupTable[0].table(head -> {
|
||||||
if(!group.name.isEmpty()){
|
if(!group.name.isEmpty()){
|
||||||
head.add(group.name).color(Color.lightGray).padRight(4);
|
head.add(group.name).color(Color.lightGray).padRight(4);
|
||||||
}
|
}
|
||||||
@@ -379,20 +382,19 @@ public class JoinDialog extends BaseDialog{
|
|||||||
group.setHidden(!group.hidden());
|
group.setHidden(!group.hidden());
|
||||||
image[0].getStyle().imageUp = group.hidden() ? Icon.eyeOffSmall : Icon.eyeSmall;
|
image[0].getStyle().imageUp = group.hidden() ? Icon.eyeOffSmall : Icon.eyeSmall;
|
||||||
if(group.hidden() && !showHidden){
|
if(group.hidden() && !showHidden){
|
||||||
g.remove();
|
groupTable[0].remove();
|
||||||
}
|
}
|
||||||
}).size(40f).get();
|
}).size(40f).get();
|
||||||
image[0].addListener(new Tooltip(t -> t.background(Styles.black6).margin(4).label(() -> !group.hidden() ? "@server.shown" : "@server.hidden")));
|
image[0].addListener(new Tooltip(t -> t.background(Styles.black6).margin(4).label(() -> !group.hidden() ? "@server.shown" : "@server.hidden")));
|
||||||
}).width(targetWidth()).padBottom(-2).row();
|
}).width(targetWidth()).padBottom(-2).row();
|
||||||
}
|
}
|
||||||
|
|
||||||
addGlobalHost(res, g);
|
addGlobalHost(res, groupTable[0]);
|
||||||
|
|
||||||
g.margin(5f);
|
groupTable[0].margin(5f);
|
||||||
g.pack();
|
groupTable[0].pack();
|
||||||
}, e -> {});
|
}, e -> {});
|
||||||
}
|
}
|
||||||
}).row();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +404,16 @@ public class JoinDialog extends BaseDialog{
|
|||||||
|
|
||||||
container.button(b -> buildServer(host, b), Styles.cleart, () -> {
|
container.button(b -> buildServer(host, b), Styles.cleart, () -> {
|
||||||
Events.fire(new ClientPreConnectEvent(host));
|
Events.fire(new ClientPreConnectEvent(host));
|
||||||
|
if(!Core.settings.getBool("server-disclaimer", false)){
|
||||||
|
ui.showCustomConfirm("@warning", "@servers.disclaimer", "@ok", "@back", () -> {
|
||||||
|
Core.settings.put("server-disclaimer", true);
|
||||||
safeConnect(host.address, host.port, host.version);
|
safeConnect(host.address, host.port, host.version);
|
||||||
|
}, () -> {
|
||||||
|
Core.settings.put("server-disclaimer", false);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
safeConnect(host.address, host.port, host.version);
|
||||||
|
}
|
||||||
}).width(w).row();
|
}).width(w).row();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ import arc.scene.ui.layout.*;
|
|||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
import mindustry.content.TechTree.*;
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.game.Objectives.*;
|
||||||
import mindustry.game.SectorInfo.*;
|
import mindustry.game.SectorInfo.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -144,7 +146,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
//load legacy research
|
//load legacy research
|
||||||
if(Core.settings.has("unlocks") && !Core.settings.has("junction-unlocked")){
|
if(Core.settings.has("unlocks") && !Core.settings.has("junction-unlocked")){
|
||||||
Core.app.post(() -> {
|
Core.app.post(() -> {
|
||||||
ui.showCustomConfirm("@research", "@research.legacy", "@research.load", "@research.discard", LegacyIO::readResearch, () -> Core.settings.remove("unlocks"));
|
ui.showCustomConfirm("@research", "@research.legacy", "@research.load", "@research.discard", () -> {
|
||||||
|
LegacyIO.readResearch();
|
||||||
|
Core.settings.remove("unlocks");
|
||||||
|
}, () -> Core.settings.remove("unlocks"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +255,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
boolean canSelect(Sector sector){
|
boolean canSelect(Sector sector){
|
||||||
if(mode == select) return sector.hasBase();
|
if(mode == select) return sector.hasBase();
|
||||||
//preset sectors can only be selected once unlocked
|
//preset sectors can only be selected once unlocked
|
||||||
if(sector.preset != null) return sector.preset.unlocked() || sector.hasBase();
|
if(sector.preset != null){
|
||||||
|
TechNode node = sector.preset.node();
|
||||||
|
return node == null || node.parent == null || node.parent.content.unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
return sector.hasBase() || sector.near().contains(Sector::hasBase); //near an occupied sector
|
return sector.hasBase() || sector.near().contains(Sector::hasBase); //near an occupied sector
|
||||||
}
|
}
|
||||||
@@ -288,7 +296,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
Color color =
|
Color color =
|
||||||
sec.hasBase() ? Tmp.c2.set(Team.sharded.color).lerp(Team.crux.color, sec.hasEnemyBase() ? 0.5f : 0f) :
|
sec.hasBase() ? Tmp.c2.set(Team.sharded.color).lerp(Team.crux.color, sec.hasEnemyBase() ? 0.5f : 0f) :
|
||||||
sec.preset != null ? Tmp.c2.set(Team.derelict.color).lerp(Color.white, Mathf.absin(Time.time, 10f, 1f)) :
|
sec.preset != null ?
|
||||||
|
sec.preset.unlocked() ? Tmp.c2.set(Team.derelict.color).lerp(Color.white, Mathf.absin(Time.time, 10f, 1f)) :
|
||||||
|
Color.gray :
|
||||||
sec.hasEnemyBase() ? Team.crux.color :
|
sec.hasEnemyBase() ? Team.crux.color :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
@@ -349,7 +359,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
for(Sector sec : planet.sectors){
|
for(Sector sec : planet.sectors){
|
||||||
if(sec != hovered){
|
if(sec != hovered){
|
||||||
var preficon = sec.icon();
|
var preficon = sec.icon();
|
||||||
var icon = (sec.isAttacked() ? Fonts.getLargeIcon("warning") : !sec.hasBase() && sec.preset != null && sec.preset.unlocked() && preficon == null ? Fonts.getLargeIcon("terrain") : preficon);
|
var icon =
|
||||||
|
sec.isAttacked() ? Fonts.getLargeIcon("warning") :
|
||||||
|
!sec.hasBase() && sec.preset != null && sec.preset.unlocked() && preficon == null ?
|
||||||
|
Fonts.getLargeIcon("terrain") :
|
||||||
|
sec.preset != null && sec.preset.locked() && sec.preset.node() != null && !sec.preset.node().parent.content.locked() ? Fonts.getLargeIcon("lock") :
|
||||||
|
preficon;
|
||||||
var color = sec.preset != null && !sec.hasBase() ? Team.derelict.color : Team.sharded.color;
|
var color = sec.preset != null && !sec.hasBase() ? Team.derelict.color : Team.sharded.color;
|
||||||
|
|
||||||
if(icon != null){
|
if(icon != null){
|
||||||
@@ -490,7 +505,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
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, -planets.planet.getRotation()).add(planets.planet.position));
|
||||||
hoverLabel.setPosition(pos.x, pos.y, Align.center);
|
hoverLabel.setPosition(pos.x, pos.y - Core.scene.marginBottom, Align.center);
|
||||||
|
|
||||||
hoverLabel.getText().setLength(0);
|
hoverLabel.getText().setLength(0);
|
||||||
if(hovered != null){
|
if(hovered != null){
|
||||||
@@ -687,7 +702,21 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
stable.image().color(Pal.accent).fillX().height(3f).pad(3f).row();
|
stable.image().color(Pal.accent).fillX().height(3f).pad(3f).row();
|
||||||
|
|
||||||
if(!sector.hasBase()){
|
boolean locked = sector.preset != null && sector.preset.locked() && sector.preset.node() != null;
|
||||||
|
|
||||||
|
if(locked){
|
||||||
|
stable.table(r -> {
|
||||||
|
r.add("@complete").colspan(2).left();
|
||||||
|
r.row();
|
||||||
|
for(Objective o : sector.preset.node().objectives){
|
||||||
|
if(o.complete()) continue;
|
||||||
|
|
||||||
|
r.add("> " + o.display()).color(Color.lightGray).left();
|
||||||
|
r.image(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||||
|
r.row();
|
||||||
|
}
|
||||||
|
}).row();
|
||||||
|
}else if(!sector.hasBase()){
|
||||||
stable.add(Core.bundle.get("sectors.threat") + " [accent]" + sector.displayThreat()).row();
|
stable.add(Core.bundle.get("sectors.threat") + " [accent]" + sector.displayThreat()).row();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,13 +756,23 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if((sector.hasBase() && mode == look) || canSelect(sector) || (sector.preset != null && sector.preset.alwaysUnlocked) || debugSelect){
|
if((sector.hasBase() && mode == look) || canSelect(sector) || (sector.preset != null && sector.preset.alwaysUnlocked) || debugSelect){
|
||||||
stable.button(mode == select ? "@sectors.select" : sector.isBeingPlayed() ? "@sectors.resume" : sector.hasBase() ? "@sectors.go" : "@sectors.launch", Icon.play, () -> {
|
stable.button(
|
||||||
|
mode == select ? "@sectors.select" :
|
||||||
|
sector.isBeingPlayed() ? "@sectors.resume" :
|
||||||
|
sector.hasBase() ? "@sectors.go" :
|
||||||
|
locked ? "@locked" : "@sectors.launch",
|
||||||
|
locked ? Icon.lock :Icon.play, () -> {
|
||||||
|
|
||||||
if(sector.isBeingPlayed()){
|
if(sector.isBeingPlayed()){
|
||||||
//already at this sector
|
//already at this sector
|
||||||
hide();
|
hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sector.preset != null && sector.preset.locked()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boolean shouldHide = true;
|
boolean shouldHide = true;
|
||||||
|
|
||||||
//save before launch.
|
//save before launch.
|
||||||
@@ -775,7 +814,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(shouldHide) hide();
|
if(shouldHide) hide();
|
||||||
}).growX().height(54f).minWidth(170f).padTop(4);
|
}).growX().height(54f).minWidth(170f).padTop(4).disabled(locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
stable.pack();
|
stable.pack();
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class ChatFragment extends Table{
|
|||||||
Draw.color(shadowColor);
|
Draw.color(shadowColor);
|
||||||
|
|
||||||
if(shown){
|
if(shown){
|
||||||
Fill.crect(offsetx, chatfield.y, chatfield.getWidth() + 15f, chatfield.getHeight() - 1);
|
Fill.crect(offsetx, chatfield.y + scene.marginBottom, chatfield.getWidth() + 15f, chatfield.getHeight() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.draw();
|
super.draw();
|
||||||
@@ -137,7 +137,7 @@ public class ChatFragment extends Table{
|
|||||||
Draw.color(shadowColor);
|
Draw.color(shadowColor);
|
||||||
Draw.alpha(shadowColor.a * opacity);
|
Draw.alpha(shadowColor.a * opacity);
|
||||||
|
|
||||||
float theight = offsety + spacing + getMarginBottom();
|
float theight = offsety + spacing + getMarginBottom() + scene.marginBottom;
|
||||||
for(int i = scrollPos; i < messages.size && i < messagesShown + scrollPos && (i < fadetime || shown); i++){
|
for(int i = scrollPos; i < messages.size && i < messagesShown + scrollPos && (i < fadetime || shown); i++){
|
||||||
|
|
||||||
layout.setText(font, messages.get(i).formattedMessage, Color.white, textWidth, Align.bottomLeft, true);
|
layout.setText(font, messages.get(i).formattedMessage, Color.white, textWidth, Align.bottomLeft, true);
|
||||||
|
|||||||
@@ -162,6 +162,17 @@ public class HintsFragment extends Fragment{
|
|||||||
waveFire(() -> Groups.fire.size() > 0 && Blocks.wave.unlockedNow(), () -> indexer.getAllied(state.rules.defaultTeam, BlockFlag.extinguisher).size() > 0),
|
waveFire(() -> Groups.fire.size() > 0 && Blocks.wave.unlockedNow(), () -> indexer.getAllied(state.rules.defaultTeam, BlockFlag.extinguisher).size() > 0),
|
||||||
generator(() -> control.input.block == Blocks.combustionGenerator, () -> ui.hints.placedBlocks.contains(Blocks.combustionGenerator)),
|
generator(() -> control.input.block == Blocks.combustionGenerator, () -> ui.hints.placedBlocks.contains(Blocks.combustionGenerator)),
|
||||||
guardian(() -> state.boss() != null && state.boss().armor >= 4, () -> state.boss() == null),
|
guardian(() -> state.boss() != null && state.boss().armor >= 4, () -> state.boss() == null),
|
||||||
|
coreUpgrade(() -> state.isCampaign() && Blocks.coreFoundation.unlocked()
|
||||||
|
&& state.rules.defaultTeam.core() != null
|
||||||
|
&& state.rules.defaultTeam.core().block == Blocks.coreShard
|
||||||
|
&& state.rules.defaultTeam.core().items.has(Blocks.coreFoundation.requirements),
|
||||||
|
() -> ui.hints.placedBlocks.contains(Blocks.coreFoundation)),
|
||||||
|
presetLaunch(() -> state.isCampaign()
|
||||||
|
&& state.getSector().preset == null
|
||||||
|
&& SectorPresets.frozenForest.unlocked()
|
||||||
|
&& SectorPresets.frozenForest.sector.save == null,
|
||||||
|
() -> state.isCampaign() && state.getSector().preset == SectorPresets.frozenForest),
|
||||||
|
coreIncinerate(() -> state.isCampaign() && state.rules.defaultTeam.core() != null && state.rules.defaultTeam.core().items.get(Items.copper) >= state.rules.defaultTeam.core().storageCapacity - 10, () -> false),
|
||||||
;
|
;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package mindustry.ui.fragments;
|
package mindustry.ui.fragments;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
import arc.scene.*;
|
import arc.scene.*;
|
||||||
import arc.scene.actions.*;
|
import arc.scene.actions.*;
|
||||||
import arc.scene.event.*;
|
import arc.scene.event.*;
|
||||||
@@ -18,7 +20,12 @@ public class LoadingFragment extends Fragment{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(Group parent){
|
public void build(Group parent){
|
||||||
parent.fill(Styles.black8, t -> {
|
parent.fill(t -> {
|
||||||
|
//rect must fill screen completely.
|
||||||
|
t.rect((x, y, w, h) -> {
|
||||||
|
Draw.alpha(t.color.a);
|
||||||
|
Styles.black8.draw(0, 0, Core.graphics.getWidth(), Core.graphics.getHeight());
|
||||||
|
});
|
||||||
t.visible = false;
|
t.visible = false;
|
||||||
t.touchable = Touchable.enabled;
|
t.touchable = Touchable.enabled;
|
||||||
t.add().height(133f).row();
|
t.add().height(133f).row();
|
||||||
|
|||||||
@@ -77,12 +77,13 @@ public class MenuFragment extends Fragment{
|
|||||||
String versionText = ((Version.build == -1) ? "[#fc8140aa]" : "[#ffffffba]") + Version.combined();
|
String versionText = ((Version.build == -1) ? "[#fc8140aa]" : "[#ffffffba]") + Version.combined();
|
||||||
parent.fill((x, y, w, h) -> {
|
parent.fill((x, y, w, h) -> {
|
||||||
TextureRegion logo = Core.atlas.find("logo");
|
TextureRegion logo = Core.atlas.find("logo");
|
||||||
|
float width = Core.graphics.getWidth(), height = Core.graphics.getHeight() - Core.scene.marginTop;
|
||||||
float logoscl = Scl.scl(1);
|
float logoscl = Scl.scl(1);
|
||||||
float logow = Math.min(logo.width * logoscl, Core.graphics.getWidth() - Scl.scl(20));
|
float logow = Math.min(logo.width * logoscl, Core.graphics.getWidth() - Scl.scl(20));
|
||||||
float logoh = logow * (float)logo.height / logo.width;
|
float logoh = logow * (float)logo.height / logo.width;
|
||||||
|
|
||||||
float fx = (int)(Core.graphics.getWidth() / 2f);
|
float fx = (int)(width / 2f);
|
||||||
float fy = (int)(Core.graphics.getHeight() - 6 - logoh) + logoh / 2 - (Core.graphics.isPortrait() ? Scl.scl(30f) : 0f);
|
float fy = (int)(height - 6 - logoh) + logoh / 2 - (Core.graphics.isPortrait() ? Scl.scl(30f) : 0f);
|
||||||
|
|
||||||
Draw.color();
|
Draw.color();
|
||||||
Draw.rect(logo, fx, fy, logow, logoh);
|
Draw.rect(logo, fx, fy, logow, logoh);
|
||||||
@@ -230,7 +231,7 @@ public class MenuFragment extends Fragment{
|
|||||||
submenu.clearChildren();
|
submenu.clearChildren();
|
||||||
fadeInMenu();
|
fadeInMenu();
|
||||||
//correctly offset the button
|
//correctly offset the button
|
||||||
submenu.add().height((Core.graphics.getHeight() - out[0].getY(Align.topLeft)) / Scl.scl(1f));
|
submenu.add().height((Core.graphics.getHeight() - Core.scene.marginTop - Core.scene.marginBottom - out[0].getY(Align.topLeft)) / Scl.scl(1f));
|
||||||
submenu.row();
|
submenu.row();
|
||||||
buttons(submenu, b.submenu);
|
buttons(submenu, b.submenu);
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class MinimapFragment extends Fragment{
|
|||||||
float size = baseSize * zoom * world.width();
|
float size = baseSize * zoom * world.width();
|
||||||
|
|
||||||
Draw.color(Color.black);
|
Draw.color(Color.black);
|
||||||
Fill.crect(x, y, w, h);
|
Fill.crect(0, 0, w, h);
|
||||||
|
|
||||||
if(renderer.minimap.getTexture() != null){
|
if(renderer.minimap.getTexture() != null){
|
||||||
Draw.color();
|
Draw.color();
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class ScriptConsoleFragment extends Table{
|
|||||||
Draw.color(shadowColor);
|
Draw.color(shadowColor);
|
||||||
|
|
||||||
if(open){
|
if(open){
|
||||||
Fill.crect(offsetx, chatfield.y, chatfield.getWidth() + 15f, chatfield.getHeight() - 1);
|
Fill.crect(offsetx, chatfield.y + scene.marginBottom, chatfield.getWidth() + 15f, chatfield.getHeight() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.draw();
|
super.draw();
|
||||||
@@ -125,7 +125,7 @@ public class ScriptConsoleFragment extends Table{
|
|||||||
Draw.color(shadowColor);
|
Draw.color(shadowColor);
|
||||||
Draw.alpha(shadowColor.a * opacity);
|
Draw.alpha(shadowColor.a * opacity);
|
||||||
|
|
||||||
float theight = offsety + spacing + getMarginBottom();
|
float theight = offsety + spacing + getMarginBottom() + scene.marginBottom;
|
||||||
for(int i = scrollPos; i < messages.size && i < messagesShown + scrollPos; i++){
|
for(int i = scrollPos; i < messages.size && i < messagesShown + scrollPos; i++){
|
||||||
|
|
||||||
layout.setText(font, messages.get(i), Color.white, textWidth, Align.bottomLeft, true);
|
layout.setText(font, messages.get(i), Color.white, textWidth, Align.bottomLeft, true);
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class Block extends UnlockableContent{
|
|||||||
public BlockGroup group = BlockGroup.none;
|
public BlockGroup group = BlockGroup.none;
|
||||||
/** List of block flags. Used for AI indexing. */
|
/** List of block flags. Used for AI indexing. */
|
||||||
public EnumSet<BlockFlag> flags = EnumSet.of();
|
public EnumSet<BlockFlag> flags = EnumSet.of();
|
||||||
/** Targeting priority of this block, as seen by enemies.*/
|
/** Targeting priority of this block, as seen by enemies .*/
|
||||||
public TargetPriority priority = TargetPriority.base;
|
public TargetPriority priority = TargetPriority.base;
|
||||||
/** How much this block affects the unit cap by.
|
/** How much this block affects the unit cap by.
|
||||||
* The block flags must contain unitModifier in order for this to work. */
|
* The block flags must contain unitModifier in order for this to work. */
|
||||||
@@ -139,9 +139,9 @@ public class Block extends UnlockableContent{
|
|||||||
public boolean consumesTap;
|
public boolean consumesTap;
|
||||||
/** Whether to draw the glow of the liquid for this block, if it has one. */
|
/** Whether to draw the glow of the liquid for this block, if it has one. */
|
||||||
public boolean drawLiquidLight = true;
|
public boolean drawLiquidLight = true;
|
||||||
/** Whether to periodically sync this block across the network.*/
|
/** Whether to periodically sync this block across the network. */
|
||||||
public boolean sync;
|
public boolean sync;
|
||||||
/** Whether this block uses conveyor-type placement mode.*/
|
/** Whether this block uses conveyor-type placement mode. */
|
||||||
public boolean conveyorPlacement;
|
public boolean conveyorPlacement;
|
||||||
/**
|
/**
|
||||||
* The color of this block when displayed on the minimap or map preview.
|
* The color of this block when displayed on the minimap or map preview.
|
||||||
@@ -173,12 +173,12 @@ public class Block extends UnlockableContent{
|
|||||||
/** Radius of the light emitted by this block. */
|
/** Radius of the light emitted by this block. */
|
||||||
public float lightRadius = 60f;
|
public float lightRadius = 60f;
|
||||||
|
|
||||||
/** The sound that this block makes while active. One sound loop. Do not overuse.*/
|
/** The sound that this block makes while active. One sound loop. Do not overuse. */
|
||||||
public Sound loopSound = Sounds.none;
|
public Sound loopSound = Sounds.none;
|
||||||
/** Active sound base volume. */
|
/** Active sound base volume. */
|
||||||
public float loopSoundVolume = 0.5f;
|
public float loopSoundVolume = 0.5f;
|
||||||
|
|
||||||
/** The sound that this block makes while idle. Uses one sound loop for all blocks.*/
|
/** The sound that this block makes while idle. Uses one sound loop for all blocks. */
|
||||||
public Sound ambientSound = Sounds.none;
|
public Sound ambientSound = Sounds.none;
|
||||||
/** Idle sound base volume. */
|
/** Idle sound base volume. */
|
||||||
public float ambientSoundVolume = 0.05f;
|
public float ambientSoundVolume = 0.05f;
|
||||||
@@ -193,6 +193,8 @@ public class Block extends UnlockableContent{
|
|||||||
public BuildVisibility buildVisibility = BuildVisibility.hidden;
|
public BuildVisibility buildVisibility = BuildVisibility.hidden;
|
||||||
/** Multiplier for speed of building this block. */
|
/** Multiplier for speed of building this block. */
|
||||||
public float buildCostMultiplier = 1f;
|
public float buildCostMultiplier = 1f;
|
||||||
|
/** Build completion at which deconstruction finishes. */
|
||||||
|
public float deconstructThreshold = 0f;
|
||||||
/** Multiplier for cost of research in tech tree. */
|
/** Multiplier for cost of research in tech tree. */
|
||||||
public float researchCostMultiplier = 1;
|
public float researchCostMultiplier = 1;
|
||||||
/** Whether this block has instant transfer.*/
|
/** Whether this block has instant transfer.*/
|
||||||
@@ -634,6 +636,8 @@ public class Block extends UnlockableContent{
|
|||||||
|
|
||||||
//also requires inputs
|
//also requires inputs
|
||||||
consumes.each(c -> {
|
consumes.each(c -> {
|
||||||
|
if(c.isOptional()) return;
|
||||||
|
|
||||||
if(c instanceof ConsumeItems i){
|
if(c instanceof ConsumeItems i){
|
||||||
for(ItemStack stack : i.items){
|
for(ItemStack stack : i.items){
|
||||||
cons.get(stack.item);
|
cons.get(stack.item);
|
||||||
|
|||||||
@@ -37,8 +37,12 @@ public class Build{
|
|||||||
Block previous = tile.block();
|
Block previous = tile.block();
|
||||||
Block sub = ConstructBlock.get(previous.size);
|
Block sub = ConstructBlock.get(previous.size);
|
||||||
|
|
||||||
|
Seq<Building> prevBuild = new Seq<>(1);
|
||||||
|
if(tile.build != null) prevBuild.add(tile.build);
|
||||||
|
|
||||||
tile.setBlock(sub, team, rotation);
|
tile.setBlock(sub, team, rotation);
|
||||||
tile.<ConstructBuild>bc().setDeconstruct(previous);
|
tile.<ConstructBuild>bc().setDeconstruct(previous);
|
||||||
|
tile.<ConstructBuild>bc().prevBuild = prevBuild;
|
||||||
tile.build.health = tile.build.maxHealth * prevPercent;
|
tile.build.health = tile.build.maxHealth * prevPercent;
|
||||||
if(unit != null && unit.isPlayer()) tile.build.lastAccessed = unit.getPlayer().name;
|
if(unit != null && unit.isPlayer()) tile.build.lastAccessed = unit.getPlayer().name;
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ public class ConstructBlock extends Block{
|
|||||||
|
|
||||||
progress = Mathf.clamp(progress - amount);
|
progress = Mathf.clamp(progress - amount);
|
||||||
|
|
||||||
if(progress <= 0 || state.rules.infiniteResources){
|
if(progress <= (previous == null ? 0 : previous.deconstructThreshold) || state.rules.infiniteResources){
|
||||||
if(lastBuilder == null) lastBuilder = builder;
|
if(lastBuilder == null) lastBuilder = builder;
|
||||||
Call.deconstructFinish(tile, this.cblock == null ? previous : this.cblock, lastBuilder);
|
Call.deconstructFinish(tile, this.cblock == null ? previous : this.cblock, lastBuilder);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean pass(Item item){
|
public boolean pass(Item item){
|
||||||
if(next != null && next.team == team && next.acceptItem(this, item)){
|
if(item != null && next != null && next.team == team && next.acceptItem(this, item)){
|
||||||
next.handleItem(this, item);
|
next.handleItem(this, item);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ public class MassDriver extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Building source, Item item){
|
public boolean acceptItem(Building source, Item item){
|
||||||
//mass drivers that ouput only cannot accept items
|
//mass drivers that output only cannot accept items
|
||||||
return items.total() < itemCapacity && linkValid();
|
return items.total() < itemCapacity && linkValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ public class Boulder extends Block{
|
|||||||
super(name);
|
super(name);
|
||||||
breakable = true;
|
breakable = true;
|
||||||
alwaysReplace = true;
|
alwaysReplace = true;
|
||||||
|
|
||||||
|
deconstructThreshold = 0.35f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import java.util.zip.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class LogicBlock extends Block{
|
public class LogicBlock extends Block{
|
||||||
|
private static final int maxByteLen = 1024 * 500;
|
||||||
|
|
||||||
public int maxInstructionScale = 5;
|
public int maxInstructionScale = 5;
|
||||||
public int instructionsPerTick = 1;
|
public int instructionsPerTick = 1;
|
||||||
public float range = 8 * 10;
|
public float range = 8 * 10;
|
||||||
@@ -137,6 +139,9 @@ public class LogicBlock extends Block{
|
|||||||
stream.read();
|
stream.read();
|
||||||
|
|
||||||
int bytelen = stream.readInt();
|
int bytelen = stream.readInt();
|
||||||
|
|
||||||
|
if(bytelen > maxByteLen) throw new RuntimeException("Malformed logic data! Length: " + bytelen);
|
||||||
|
|
||||||
byte[] bytes = new byte[bytelen];
|
byte[] bytes = new byte[bytelen];
|
||||||
stream.readFully(bytes);
|
stream.readFully(bytes);
|
||||||
|
|
||||||
@@ -197,6 +202,7 @@ public class LogicBlock extends Block{
|
|||||||
int version = stream.read();
|
int version = stream.read();
|
||||||
|
|
||||||
int bytelen = stream.readInt();
|
int bytelen = stream.readInt();
|
||||||
|
if(bytelen > maxByteLen) throw new RuntimeException("Malformed logic data! Length: " + bytelen);
|
||||||
byte[] bytes = new byte[bytelen];
|
byte[] bytes = new byte[bytelen];
|
||||||
stream.readFully(bytes);
|
stream.readFully(bytes);
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,13 @@ public class Reconstructor extends UnitBlock{
|
|||||||
return capacities[item.id];
|
return capacities[item.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void overwrote(Seq<Building> builds){
|
||||||
|
if(builds.first().block == block){
|
||||||
|
items.add(builds.first().items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
Draw.rect(region, x, y);
|
Draw.rect(region, x, y);
|
||||||
|
|||||||
5
fastlane/metadata/android/en-US/changelogs/29741.txt
Normal file
5
fastlane/metadata/android/en-US/changelogs/29741.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[This is a truncated changelog, see Github for full notes]
|
||||||
|
- Fixed two rare crashes
|
||||||
|
- Made units depend on their production materials in tech tree
|
||||||
|
- Made conveyors replaceable by distributors
|
||||||
|
- Translation updates
|
||||||
5
fastlane/metadata/android/en-US/changelogs/29744.txt
Normal file
5
fastlane/metadata/android/en-US/changelogs/29744.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[This is a truncated changelog, see Github for full notes]
|
||||||
|
Yeah, it's another hotfix. I missed these during earlier testing.
|
||||||
|
|
||||||
|
- Fixed research deadlock caused by blocks requiring optional inputs as research
|
||||||
|
- Possible fix for "Unsupported combination of formats" startup error
|
||||||
8
fastlane/metadata/android/en-US/changelogs/29747.txt
Normal file
8
fastlane/metadata/android/en-US/changelogs/29747.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[This is a truncated changelog, see Github for full notes]
|
||||||
|
- Added disclaimer for community servers
|
||||||
|
- Added hints concerning core upgrades and numbered sectors
|
||||||
|
- Decreased spore storm opacity
|
||||||
|
- Made items stay inside reconstructors when rebuilding (Contributed by @Quezler)
|
||||||
|
- Made early game procedural sectors slightly easier
|
||||||
|
- Fixed some blocks having duplicate research dependencies
|
||||||
|
- Fixed legacy research not being cleared after first import
|
||||||
@@ -56,21 +56,21 @@
|
|||||||
"NEW_ACHIEVEMENT_21_3_NAME" "Swarm"
|
"NEW_ACHIEVEMENT_21_3_NAME" "Swarm"
|
||||||
"NEW_ACHIEVEMENT_21_3_DESC" "Have 100 units active at once."
|
"NEW_ACHIEVEMENT_21_3_DESC" "Have 100 units active at once."
|
||||||
"NEW_ACHIEVEMENT_21_4_NAME" "Flock"
|
"NEW_ACHIEVEMENT_21_4_NAME" "Flock"
|
||||||
"NEW_ACHIEVEMENT_21_4_DESC" "Have 10 Phantom Poly drones active at once."
|
"NEW_ACHIEVEMENT_21_4_DESC" "Have 10 Poly drones active at once."
|
||||||
"NEW_ACHIEVEMENT_21_5_NAME" "Roboticist"
|
"NEW_ACHIEVEMENT_21_5_NAME" "Roboticist"
|
||||||
"NEW_ACHIEVEMENT_21_5_DESC" "Build every type of unit."
|
"NEW_ACHIEVEMENT_21_5_DESC" "Build every type of unit."
|
||||||
"NEW_ACHIEVEMENT_21_6_NAME" "Legions"
|
"NEW_ACHIEVEMENT_21_6_NAME" "Legions"
|
||||||
"NEW_ACHIEVEMENT_21_6_DESC" "Build 1000 units total."
|
"NEW_ACHIEVEMENT_21_6_DESC" "Build 1000 units total."
|
||||||
"NEW_ACHIEVEMENT_21_9_NAME" "You Should've Listened"
|
"NEW_ACHIEVEMENT_21_9_NAME" "You Should've Listened"
|
||||||
"NEW_ACHIEVEMENT_21_9_DESC" "Die in the drop point exclusion zone."
|
"NEW_ACHIEVEMENT_21_9_DESC" "Die in the drop point exclusion zone."
|
||||||
"NEW_ACHIEVEMENT_21_10_NAME" "There are naval units for that."
|
"NEW_ACHIEVEMENT_21_10_NAME" "There Are Naval Units For That"
|
||||||
"NEW_ACHIEVEMENT_21_10_DESC" "Drown."
|
"NEW_ACHIEVEMENT_21_10_DESC" "Drown."
|
||||||
"NEW_ACHIEVEMENT_21_11_NAME" "Collector"
|
"NEW_ACHIEVEMENT_21_11_NAME" "Collector"
|
||||||
"NEW_ACHIEVEMENT_21_11_DESC" "Fill the core to maximum capacity with every type of material."
|
"NEW_ACHIEVEMENT_21_11_DESC" "Fill the core to maximum capacity with every type of material."
|
||||||
"NEW_ACHIEVEMENT_21_12_NAME" "Crowd"
|
"NEW_ACHIEVEMENT_21_12_NAME" "Crowd"
|
||||||
"NEW_ACHIEVEMENT_21_12_DESC" "Host a server with 10 players on it."
|
"NEW_ACHIEVEMENT_21_12_DESC" "Host a server with 10 players on it."
|
||||||
"NEW_ACHIEVEMENT_21_13_NAME" "Invulnerable"
|
"NEW_ACHIEVEMENT_21_13_NAME" "Invulnerable"
|
||||||
"NEW_ACHIEVEMENT_21_13_DESC" "Build the Meltdown and, Spectre and Foreshadow.."
|
"NEW_ACHIEVEMENT_21_13_DESC" "Build the Meltdown, Spectre and Foreshadow."
|
||||||
"NEW_ACHIEVEMENT_21_14_NAME" "Liftoff"
|
"NEW_ACHIEVEMENT_21_14_NAME" "Liftoff"
|
||||||
"NEW_ACHIEVEMENT_21_14_DESC" "Use the Launch Pad."
|
"NEW_ACHIEVEMENT_21_14_DESC" "Use the Launch Pad."
|
||||||
"NEW_ACHIEVEMENT_21_16_NAME" "Heresy"
|
"NEW_ACHIEVEMENT_21_16_NAME" "Heresy"
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
"NEW_ACHIEVEMENT_21_23_NAME" "Ignition"
|
"NEW_ACHIEVEMENT_21_23_NAME" "Ignition"
|
||||||
"NEW_ACHIEVEMENT_21_23_DESC" "Power up an Impact Reactor."
|
"NEW_ACHIEVEMENT_21_23_DESC" "Power up an Impact Reactor."
|
||||||
"NEW_ACHIEVEMENT_21_24_NAME" "Acceleration"
|
"NEW_ACHIEVEMENT_21_24_NAME" "Acceleration"
|
||||||
"NEW_ACHIEVEMENT_21_24_DESC" "Activate the Interplanteary Accelerator."
|
"NEW_ACHIEVEMENT_21_24_DESC" "Activate the Interplanetary Accelerator."
|
||||||
"NEW_ACHIEVEMENT_21_25_NAME" "The Spiral"
|
"NEW_ACHIEVEMENT_21_25_NAME" "The Spiral"
|
||||||
"NEW_ACHIEVEMENT_21_25_DESC" "Round and round it goes..."
|
"NEW_ACHIEVEMENT_21_25_DESC" "Round and round it goes..."
|
||||||
"NEW_ACHIEVEMENT_21_26_NAME" "Escalation"
|
"NEW_ACHIEVEMENT_21_26_NAME" "Escalation"
|
||||||
|
|||||||
@@ -43,10 +43,10 @@
|
|||||||
|
|
||||||
[list]
|
[list]
|
||||||
[*] 16 built in maps for custom games, in addition to campaign
|
[*] 16 built in maps for custom games, in addition to campaign
|
||||||
[*] Play Co-op, PvP or sandbox
|
[*] Play co-op, PvP or sandbox
|
||||||
[*] Join a public dedicated server, or invite friends to your own private session
|
[*] Join a public dedicated server, or invite friends to your own private session
|
||||||
[*] Customizable game rules: Change block costs, enemy stats, starting items, wave timing and more
|
[*] Customizable game rules: Change block costs, enemy stats, starting items, wave timing and more
|
||||||
[*] Mix&match gamemodes: Combine PvP and PvE gamemodes together
|
[*] Mix & match gamemodes: Combine PvP and PvE gamemodes together
|
||||||
[/list]
|
[/list]
|
||||||
|
|
||||||
[h2]Custom Map Editor[/h2]
|
[h2]Custom Map Editor[/h2]
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=e13f9a192be0bad00766ff15a6bf7d2897ba00d1
|
archash=d44cbae08716cfe97012c84399a1e61854d6b16c
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
{
|
{
|
||||||
"address": "nydustry.nydus.app:6060"
|
"address": "nydustry.nydus.app:6060"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"address": "md.surrealment.com"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"address": "routerchain.ddns.net:6568"
|
"address": "routerchain.ddns.net:6568"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "{AA}",
|
"name": "{AA}",
|
||||||
"address": ["aamindustry.play.ai:6571", "aamindustry.play.ai:6572"]
|
"address": ["aamindustry.play.ai", "aamindustry.play.ai:6571", "aamindustry.play.ai:6572", "aamindustry.play.ai:6573"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Atanner",
|
"name": "Atanner",
|
||||||
@@ -42,5 +42,9 @@
|
|||||||
{
|
{
|
||||||
"name": "Gearblock",
|
"name": "Gearblock",
|
||||||
"address": ["attack.gearblock.app"]
|
"address": ["attack.gearblock.app"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Surrealment",
|
||||||
|
"address": ["md.surrealment.com"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public class ApplicationTests{
|
|||||||
add(netServer = new NetServer());
|
add(netServer = new NetServer());
|
||||||
|
|
||||||
content.init();
|
content.init();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -77,9 +78,15 @@ public class ApplicationTests{
|
|||||||
}
|
}
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Block block = content.getByName(ContentType.block, "build2");
|
||||||
|
assertEquals("build2", block == null ? null : block.name, "2x2 construct block doesn't exist?");
|
||||||
}catch(Throwable r){
|
}catch(Throwable r){
|
||||||
fail(r);
|
fail(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.info("init app");
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@@ -496,8 +503,8 @@ public class ApplicationTests{
|
|||||||
void buildingOverlap(){
|
void buildingOverlap(){
|
||||||
initBuilding();
|
initBuilding();
|
||||||
|
|
||||||
Builderc d1 = (Builderc)UnitTypes.poly.create(Team.sharded);
|
Unit d1 = UnitTypes.poly.create(Team.sharded);
|
||||||
Builderc d2 = (Builderc)UnitTypes.poly.create(Team.sharded);
|
Unit d2 = UnitTypes.poly.create(Team.sharded);
|
||||||
|
|
||||||
//infinite build range
|
//infinite build range
|
||||||
state.rules.editor = true;
|
state.rules.editor = true;
|
||||||
@@ -523,8 +530,8 @@ public class ApplicationTests{
|
|||||||
void buildingDestruction(){
|
void buildingDestruction(){
|
||||||
initBuilding();
|
initBuilding();
|
||||||
|
|
||||||
Builderc d1 = (Builderc)UnitTypes.poly.create(Team.sharded);
|
Builderc d1 = UnitTypes.poly.create(Team.sharded);
|
||||||
Builderc d2 = (Builderc)UnitTypes.poly.create(Team.sharded);
|
Builderc d2 = UnitTypes.poly.create(Team.sharded);
|
||||||
|
|
||||||
d1.set(10f, 20f);
|
d1.set(10f, 20f);
|
||||||
d2.set(10f, 20f);
|
d2.set(10f, 20f);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{
|
|||||||
public void createGenerator(InputType inputType){
|
public void createGenerator(InputType inputType){
|
||||||
Vars.state = new GameState();
|
Vars.state = new GameState();
|
||||||
Vars.state.rules = new Rules();
|
Vars.state.rules = new Rules();
|
||||||
generator = new ItemLiquidGenerator(inputType != InputType.liquids, inputType != InputType.items, "fakegen"){
|
generator = new ItemLiquidGenerator(inputType != InputType.liquids, inputType != InputType.items, "fakegen" + System.nanoTime()){
|
||||||
{
|
{
|
||||||
powerProduction = 0.1f;
|
powerProduction = 0.1f;
|
||||||
itemDuration = fakeItemDuration;
|
itemDuration = fakeItemDuration;
|
||||||
|
|||||||
@@ -25,38 +25,46 @@ public class PowerTestFixture{
|
|||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void initializeDependencies(){
|
static void initializeDependencies(){
|
||||||
|
Log.info("init power test fixture");
|
||||||
headless = true;
|
headless = true;
|
||||||
Core.graphics = new FakeGraphics();
|
Core.graphics = new FakeGraphics();
|
||||||
Core.files = new MockFiles();
|
Core.files = new MockFiles();
|
||||||
|
|
||||||
|
boolean make = content == null;
|
||||||
|
|
||||||
|
if(make){
|
||||||
Vars.content = new ContentLoader(){
|
Vars.content = new ContentLoader(){
|
||||||
@Override
|
@Override
|
||||||
public void handleMappableContent(MappableContent content){
|
public void handleMappableContent(MappableContent content){
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
Vars.state = new GameState();
|
Vars.state = new GameState();
|
||||||
Vars.tree = new FileTree();
|
Vars.tree = new FileTree();
|
||||||
|
if(make){
|
||||||
content.createBaseContent();
|
content.createBaseContent();
|
||||||
|
}
|
||||||
Log.useColors = false;
|
Log.useColors = false;
|
||||||
Time.setDeltaProvider(() -> 0.5f);
|
Time.setDeltaProvider(() -> 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static PowerGenerator createFakeProducerBlock(float producedPower){
|
protected static PowerGenerator createFakeProducerBlock(float producedPower){
|
||||||
return new PowerGenerator("fakegen"){{
|
return new PowerGenerator("fakegen" + System.nanoTime()){{
|
||||||
buildType = () -> new GeneratorBuild();
|
buildType = () -> new GeneratorBuild();
|
||||||
powerProduction = producedPower;
|
powerProduction = producedPower;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Battery createFakeBattery(float capacity){
|
protected static Battery createFakeBattery(float capacity){
|
||||||
return new Battery("fakebattery"){{
|
return new Battery("fakebattery" + System.nanoTime()){{
|
||||||
buildType = () -> new BatteryBuild();
|
buildType = () -> new BatteryBuild();
|
||||||
consumes.powerBuffered(capacity);
|
consumes.powerBuffered(capacity);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Block createFakeDirectConsumer(float powerPerTick){
|
protected static Block createFakeDirectConsumer(float powerPerTick){
|
||||||
return new PowerBlock("fakedirectconsumer"){{
|
return new PowerBlock("fakedirectconsumer" + System.nanoTime()){{
|
||||||
buildType = Building::create;
|
buildType = Building::create;
|
||||||
consumes.power(powerPerTick);
|
consumes.power(powerPerTick);
|
||||||
}};
|
}};
|
||||||
|
|||||||
Reference in New Issue
Block a user