Merge branch 'master' into patch-1
This commit is contained in:
@@ -10,7 +10,7 @@ script:
|
|||||||
- git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
- git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
||||||
- cd ../MindustryBuilds
|
- cd ../MindustryBuilds
|
||||||
- echo ${TRAVIS_TAG}
|
- echo ${TRAVIS_TAG}
|
||||||
- if [ -n "$TRAVIS_TAG" ]; then echo versionName=5-fdroid-${TRAVIS_TAG:1}$'\n'versionCode=${TRAVIS_TAG:1} > version_fdroid.txt; git add .; git commit -m "Updating to build ${TRAVIS_TAG}"; fi
|
- if [ -n "$TRAVIS_TAG" ]; then echo versionName=6-fdroid-${TRAVIS_TAG:1}$'\n'versionCode=${TRAVIS_TAG:1} > version_fdroid.txt; git add .; git commit -m "Updating to build ${TRAVIS_TAG}"; fi
|
||||||
- git tag ${TRAVIS_BUILD_NUMBER}
|
- git tag ${TRAVIS_BUILD_NUMBER}
|
||||||
- git config --global user.name "Build Uploader"
|
- git config --global user.name "Build Uploader"
|
||||||
- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git push https://Anuken:${GH_PUSH_TOKEN}@github.com/Anuken/MindustryBuilds ${TRAVIS_BUILD_NUMBER}; git push https://Anuken:${GH_PUSH_TOKEN}@github.com/Anuken/MindustryBuilds; fi
|
- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git push https://Anuken:${GH_PUSH_TOKEN}@github.com/Anuken/MindustryBuilds ${TRAVIS_BUILD_NUMBER}; git push https://Anuken:${GH_PUSH_TOKEN}@github.com/Anuken/MindustryBuilds; fi
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ gameover = Game Over
|
|||||||
gameover.pvp = The[accent] {0}[] team is victorious!
|
gameover.pvp = The[accent] {0}[] team is victorious!
|
||||||
highscore = [accent]New highscore!
|
highscore = [accent]New highscore!
|
||||||
copied = Copied.
|
copied = Copied.
|
||||||
indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
|
indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- SFX and music are unfinished/missing\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
|
||||||
indev.notready = This part of the game isn't ready yet
|
indev.notready = This part of the game isn't ready yet
|
||||||
|
|
||||||
load.sound = Sounds
|
load.sound = Sounds
|
||||||
@@ -291,6 +291,8 @@ waiting = [lightgray]Waiting...
|
|||||||
waiting.players = Waiting for players...
|
waiting.players = Waiting for players...
|
||||||
wave.enemies = [lightgray]{0} Enemies Remaining
|
wave.enemies = [lightgray]{0} Enemies Remaining
|
||||||
wave.enemy = [lightgray]{0} Enemy Remaining
|
wave.enemy = [lightgray]{0} Enemy Remaining
|
||||||
|
wave.guardianwarn = Guardian approaching in [accent]{0}[] waves.
|
||||||
|
wave.guardianwarn.one = Guardian approaching in [accent]{0}[] wave.
|
||||||
loadimage = Load Image
|
loadimage = Load Image
|
||||||
saveimage = Save Image
|
saveimage = Save Image
|
||||||
unknown = Unknown
|
unknown = Unknown
|
||||||
@@ -573,6 +575,7 @@ info.title = Info
|
|||||||
error.title = [scarlet]An error has occured
|
error.title = [scarlet]An error has occured
|
||||||
error.crashtitle = An error has occured
|
error.crashtitle = An error has occured
|
||||||
unit.nobuild = [scarlet]Unit can't build
|
unit.nobuild = [scarlet]Unit can't build
|
||||||
|
lastaccessed = [lightgray]Last Accessed: {0}
|
||||||
blocks.input = Input
|
blocks.input = Input
|
||||||
blocks.output = Output
|
blocks.output = Output
|
||||||
blocks.booster = Booster
|
blocks.booster = Booster
|
||||||
@@ -628,6 +631,7 @@ bar.powerbalance = Power: {0}/s
|
|||||||
bar.powerstored = Stored: {0}/{1}
|
bar.powerstored = Stored: {0}/{1}
|
||||||
bar.poweramount = Power: {0}
|
bar.poweramount = Power: {0}
|
||||||
bar.poweroutput = Power Output: {0}
|
bar.poweroutput = Power Output: {0}
|
||||||
|
bar.powerlines = Connections: {0}/{1}
|
||||||
bar.items = Items: {0}
|
bar.items = Items: {0}
|
||||||
bar.capacity = Capacity: {0}
|
bar.capacity = Capacity: {0}
|
||||||
bar.unitcap = {0} {1}/{2}
|
bar.unitcap = {0} {1}/{2}
|
||||||
@@ -990,6 +994,7 @@ block.darksand-water.name = Dark Sand Water
|
|||||||
block.char.name = Char
|
block.char.name = Char
|
||||||
block.dacite.name = Dacite
|
block.dacite.name = Dacite
|
||||||
block.dacite-wall.name = Dacite Wall
|
block.dacite-wall.name = Dacite Wall
|
||||||
|
block.dacite-boulder.name = Dacite Boulder
|
||||||
block.ice-snow.name = Ice Snow
|
block.ice-snow.name = Ice Snow
|
||||||
block.stone-wall.name = Stone Wall
|
block.stone-wall.name = Stone Wall
|
||||||
block.ice-wall.name = Ice Wall
|
block.ice-wall.name = Ice Wall
|
||||||
|
|||||||
Binary file not shown.
@@ -85,9 +85,9 @@ public class Vars implements Loadable{
|
|||||||
/** range for moving items for logic units */
|
/** range for moving items for logic units */
|
||||||
public static final float logicItemTransferRange = 45f;
|
public static final float logicItemTransferRange = 45f;
|
||||||
/** duration of time between turns in ticks */
|
/** duration of time between turns in ticks */
|
||||||
public static final float turnDuration = 20 * Time.toMinutes;
|
public static final float turnDuration = 2 * Time.toMinutes;
|
||||||
/** turns needed to destroy a sector completely */
|
/** turns needed to destroy a sector completely */
|
||||||
public static final float sectorDestructionTurns = 3f;
|
public static final float sectorDestructionTurns = 2f;
|
||||||
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */
|
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */
|
||||||
public static final float minArmorDamage = 0.1f;
|
public static final float minArmorDamage = 0.1f;
|
||||||
/** launch animation duration */
|
/** launch animation duration */
|
||||||
@@ -184,7 +184,7 @@ public class Vars implements Loadable{
|
|||||||
public static GameState state;
|
public static GameState state;
|
||||||
public static EntityCollisions collisions;
|
public static EntityCollisions collisions;
|
||||||
public static DefaultWaves defaultWaves;
|
public static DefaultWaves defaultWaves;
|
||||||
public static mindustry.audio.LoopControl loops;
|
public static LoopControl loops;
|
||||||
public static Platform platform = new Platform(){};
|
public static Platform platform = new Platform(){};
|
||||||
public static Mods mods;
|
public static Mods mods;
|
||||||
public static Schematics schematics;
|
public static Schematics schematics;
|
||||||
|
|||||||
@@ -77,14 +77,18 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
eachGroundSpawn((spawnX, spawnY, doShockwave) -> {
|
eachGroundSpawn((spawnX, spawnY, doShockwave) -> {
|
||||||
if(doShockwave){
|
if(doShockwave){
|
||||||
Time.run(20f, () -> Fx.spawnShockwave.at(spawnX, spawnY, state.rules.dropZoneRadius));
|
doShockwave(spawnX, spawnY);
|
||||||
Time.run(40f, () -> Damage.damage(state.rules.waveTeam, spawnX, spawnY, state.rules.dropZoneRadius, 99999999f, true));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Time.runTask(121f, () -> spawning = false);
|
Time.runTask(121f, () -> spawning = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void doShockwave(float x, float y){
|
||||||
|
Time.run(20f, () -> Fx.spawnShockwave.at(x, y, state.rules.dropZoneRadius));
|
||||||
|
Time.run(40f, () -> Damage.damage(state.rules.waveTeam, x, y, state.rules.dropZoneRadius, 99999999f, true));
|
||||||
|
}
|
||||||
|
|
||||||
private void eachGroundSpawn(SpawnConsumer cons){
|
private void eachGroundSpawn(SpawnConsumer cons){
|
||||||
for(Tile spawn : spawns){
|
for(Tile spawn : spawns){
|
||||||
cons.accept(spawn.worldx(), spawn.worldy(), true);
|
cons.accept(spawn.worldx(), spawn.worldy(), true);
|
||||||
|
|||||||
@@ -17,13 +17,17 @@ public class BuilderAI extends AIController{
|
|||||||
@Nullable Builderc following;
|
@Nullable Builderc following;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateMovement(){
|
||||||
Builderc builder = (Builderc)unit;
|
Builderc builder = (Builderc)unit;
|
||||||
|
|
||||||
if(builder.moving()){
|
if(builder.moving()){
|
||||||
builder.lookAt(builder.vel().angle());
|
builder.lookAt(builder.vel().angle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(target != null && shouldShoot()){
|
||||||
|
unit.lookAt(target);
|
||||||
|
}
|
||||||
|
|
||||||
builder.updateBuilding(true);
|
builder.updateBuilding(true);
|
||||||
|
|
||||||
if(following != null){
|
if(following != null){
|
||||||
@@ -95,13 +99,29 @@ public class BuilderAI extends AIController{
|
|||||||
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
||||||
//add build request.
|
//add build request.
|
||||||
builder.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
builder.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
||||||
|
//shift build plan to tail so next unit builds something else.
|
||||||
|
blocks.addLast(blocks.removeFirst());
|
||||||
}else{
|
}else{
|
||||||
//shift head of queue to tail, try something else next time
|
//shift head of queue to tail, try something else next time
|
||||||
blocks.removeFirst();
|
blocks.removeFirst();
|
||||||
blocks.addLast(block);
|
blocks.addLast(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AIController fallback(){
|
||||||
|
return unit.type().flying ? new FlyingAI() : new GroundAI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useFallback(){
|
||||||
|
return state.rules.waves && unit.team == state.rules.waveTeam && !unit.team.rules().ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldShoot(){
|
||||||
|
return !((Builderc)unit).isBuilding();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class LogicAI extends AIController{
|
|||||||
public LUnitControl control = LUnitControl.stop;
|
public LUnitControl control = LUnitControl.stop;
|
||||||
public float moveX, moveY, moveRad;
|
public float moveX, moveY, moveRad;
|
||||||
public float itemTimer, payTimer, controlTimer = logicControlTimeout, targetTimer;
|
public float itemTimer, payTimer, controlTimer = logicControlTimeout, targetTimer;
|
||||||
|
@Nullable
|
||||||
public Building controller;
|
public Building controller;
|
||||||
public BuildPlan plan = new BuildPlan();
|
public BuildPlan plan = new BuildPlan();
|
||||||
|
|
||||||
|
|||||||
@@ -2,27 +2,33 @@ package mindustry.ai.types;
|
|||||||
|
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
import mindustry.world.blocks.ConstructBlock.*;
|
import mindustry.world.blocks.ConstructBlock.*;
|
||||||
|
|
||||||
//note that repair AI doesn't attack anything even if it theoretically can
|
|
||||||
public class RepairAI extends AIController{
|
public class RepairAI extends AIController{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateMovement(){
|
protected void updateMovement(){
|
||||||
boolean shoot = false;
|
if(target instanceof Building){
|
||||||
|
boolean shoot = false;
|
||||||
if(target != null){
|
|
||||||
if(!target.within(unit, unit.type().range * 0.8f)){
|
|
||||||
moveTo(target, unit.type().range * 0.8f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.within(unit, unit.type().range)){
|
if(target.within(unit, unit.type().range)){
|
||||||
unit.aim(target);
|
unit.aim(target);
|
||||||
shoot = true;
|
shoot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unit.controlWeapons(shoot);
|
||||||
|
}else if(target == null){
|
||||||
|
unit.controlWeapons(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unit.controlWeapons(shoot);
|
if(target != null){
|
||||||
|
if(!target.within(unit, unit.type().range * 0.65f)){
|
||||||
|
moveTo(target, unit.type().range * 0.65f);
|
||||||
|
}
|
||||||
|
|
||||||
|
unit.lookAt(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -30,5 +36,10 @@ public class RepairAI extends AIController{
|
|||||||
target = Units.findDamagedTile(unit.team, unit.x, unit.y);
|
target = Units.findDamagedTile(unit.team, unit.x, unit.y);
|
||||||
|
|
||||||
if(target instanceof ConstructBuild) target = null;
|
if(target instanceof ConstructBuild) target = null;
|
||||||
|
|
||||||
|
if(target == null){
|
||||||
|
super.updateTargeting();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import mindustry.entities.*;
|
|||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.distribution.*;
|
||||||
|
import mindustry.world.blocks.liquid.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
public class SuicideAI extends GroundAI{
|
public class SuicideAI extends GroundAI{
|
||||||
@@ -14,7 +16,7 @@ public class SuicideAI extends GroundAI{
|
|||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateUnit(){
|
||||||
|
|
||||||
if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){
|
if(Units.invalidateTarget(target, unit.team, unit.x, unit.y, Float.MAX_VALUE)){
|
||||||
target = null;
|
target = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ public class SuicideAI extends GroundAI{
|
|||||||
|
|
||||||
boolean rotate = false, shoot = false, moveToTarget = false;
|
boolean rotate = false, shoot = false, moveToTarget = false;
|
||||||
|
|
||||||
if(!Units.invalidateTarget(target, unit, unit.range())){
|
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.hasWeapons()){
|
||||||
rotate = true;
|
rotate = true;
|
||||||
shoot = unit.within(target, unit.type().weapons.first().bullet.range() +
|
shoot = unit.within(target, unit.type().weapons.first().bullet.range() +
|
||||||
(target instanceof Building ? ((Building)target).block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
|
(target instanceof Building ? ((Building)target).block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
|
||||||
@@ -35,29 +37,36 @@ public class SuicideAI extends GroundAI{
|
|||||||
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
|
unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
|
||||||
}
|
}
|
||||||
|
|
||||||
blockedByBlock = false;
|
//do not move toward walls or transport blocks
|
||||||
|
if(!(target instanceof Building build && (
|
||||||
|
build.block.group == BlockGroup.walls ||
|
||||||
|
build.block.group == BlockGroup.liquids ||
|
||||||
|
build.block.group == BlockGroup.transportation
|
||||||
|
))){
|
||||||
|
blockedByBlock = false;
|
||||||
|
|
||||||
//raycast for target
|
//raycast for target
|
||||||
boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
||||||
Tile tile = Vars.world.tile(x, y);
|
Tile tile = Vars.world.tile(x, y);
|
||||||
if(tile != null && tile.build == target) return false;
|
if(tile != null && tile.build == target) return false;
|
||||||
if(tile != null && tile.build != null && tile.build.team != unit.team()){
|
if(tile != null && tile.build != null && tile.build.team != unit.team()){
|
||||||
blockedByBlock = true;
|
blockedByBlock = true;
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
return tile == null || tile.solid();
|
return tile == null || tile.solid();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//shoot when there's an enemy block in the way
|
||||||
|
if(blockedByBlock){
|
||||||
|
shoot = true;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
//shoot when there's an enemy block in the way
|
if(!blocked){
|
||||||
if(blockedByBlock){
|
moveToTarget = true;
|
||||||
shoot = true;
|
//move towards target directly
|
||||||
}
|
unit.moveAt(vec.set(target).sub(unit).limit(unit.type().speed));
|
||||||
|
}
|
||||||
if(!blocked){
|
|
||||||
moveToTarget = true;
|
|
||||||
//move towards target directly
|
|
||||||
unit.moveAt(vec.set(target).sub(unit).limit(unit.type().speed));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -78,4 +87,10 @@ public class SuicideAI extends GroundAI{
|
|||||||
|
|
||||||
unit.controlWeapons(rotate, shoot);
|
unit.controlWeapons(rotate, shoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Teamc target(float x, float y, float range, boolean air, boolean ground){
|
||||||
|
return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground &&
|
||||||
|
!(t.block instanceof Conveyor || t.block instanceof Conduit)); //do not target conveyors/conduits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -702,7 +702,7 @@ public class Blocks implements ContentList{
|
|||||||
drawer = new DrawAnimation();
|
drawer = new DrawAnimation();
|
||||||
|
|
||||||
consumes.item(Items.sporePod, 1);
|
consumes.item(Items.sporePod, 1);
|
||||||
consumes.power(0.60f);
|
consumes.power(0.7f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
pulverizer = new GenericCrafter("pulverizer"){{
|
pulverizer = new GenericCrafter("pulverizer"){{
|
||||||
@@ -727,7 +727,7 @@ public class Blocks implements ContentList{
|
|||||||
hasPower = hasItems = hasLiquids = true;
|
hasPower = hasItems = hasLiquids = true;
|
||||||
|
|
||||||
consumes.liquid(Liquids.oil, 0.1f);
|
consumes.liquid(Liquids.oil, 0.1f);
|
||||||
consumes.power(0.5f);
|
consumes.power(0.7f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
incinerator = new Incinerator("incinerator"){{
|
incinerator = new Incinerator("incinerator"){{
|
||||||
@@ -829,27 +829,27 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
scrapWall = new Wall("scrap-wall"){{
|
scrapWall = new Wall("scrap-wall"){{
|
||||||
requirements(Category.defense, BuildVisibility.sandboxOnly, with());
|
requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 6));
|
||||||
health = 60 * wallHealthMultiplier;
|
health = 60 * wallHealthMultiplier;
|
||||||
variants = 5;
|
variants = 5;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
scrapWallLarge = new Wall("scrap-wall-large"){{
|
scrapWallLarge = new Wall("scrap-wall-large"){{
|
||||||
requirements(Category.defense, BuildVisibility.sandboxOnly, with());
|
requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 4));
|
||||||
health = 60 * 4 * wallHealthMultiplier;
|
health = 60 * 4 * wallHealthMultiplier;
|
||||||
size = 2;
|
size = 2;
|
||||||
variants = 4;
|
variants = 4;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
scrapWallHuge = new Wall("scrap-wall-huge"){{
|
scrapWallHuge = new Wall("scrap-wall-huge"){{
|
||||||
requirements(Category.defense, BuildVisibility.sandboxOnly, with());
|
requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 9));
|
||||||
health = 60 * 9 * wallHealthMultiplier;
|
health = 60 * 9 * wallHealthMultiplier;
|
||||||
size = 3;
|
size = 3;
|
||||||
variants = 3;
|
variants = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
scrapWallGigantic = new Wall("scrap-wall-gigantic"){{
|
scrapWallGigantic = new Wall("scrap-wall-gigantic"){{
|
||||||
requirements(Category.defense, BuildVisibility.sandboxOnly, with());
|
requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 16));
|
||||||
health = 60 * 16 * wallHealthMultiplier;
|
health = 60 * 16 * wallHealthMultiplier;
|
||||||
size = 4;
|
size = 4;
|
||||||
}};
|
}};
|
||||||
@@ -994,7 +994,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
router = new Router("router"){{
|
router = new Router("router"){{
|
||||||
requirements(Category.distribution, with(Items.copper, 3));
|
requirements(Category.distribution, with(Items.copper, 3));
|
||||||
buildCostMultiplier = 2f;
|
buildCostMultiplier = 4f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
distributor = new Router("distributor"){{
|
distributor = new Router("distributor"){{
|
||||||
@@ -1287,7 +1287,7 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
cultivator = new Cultivator("cultivator"){{
|
cultivator = new Cultivator("cultivator"){{
|
||||||
requirements(Category.production, with(Items.copper, 10, Items.lead, 25, Items.silicon, 10));
|
requirements(Category.production, with(Items.copper, 25, Items.lead, 25, Items.silicon, 10));
|
||||||
outputItem = new ItemStack(Items.sporePod, 1);
|
outputItem = new ItemStack(Items.sporePod, 1);
|
||||||
craftTime = 140;
|
craftTime = 140;
|
||||||
size = 2;
|
size = 2;
|
||||||
@@ -1295,7 +1295,7 @@ public class Blocks implements ContentList{
|
|||||||
hasPower = true;
|
hasPower = true;
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
|
|
||||||
consumes.power(0.80f);
|
consumes.power(0.9f);
|
||||||
consumes.liquid(Liquids.water, 0.2f);
|
consumes.liquid(Liquids.water, 0.2f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1341,6 +1341,7 @@ public class Blocks implements ContentList{
|
|||||||
size = 4;
|
size = 4;
|
||||||
|
|
||||||
unitCapModifier = 14;
|
unitCapModifier = 14;
|
||||||
|
researchCostMultiplier = 0.04f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
coreNucleus = new CoreBlock("core-nucleus"){{
|
coreNucleus = new CoreBlock("core-nucleus"){{
|
||||||
@@ -1352,6 +1353,7 @@ public class Blocks implements ContentList{
|
|||||||
size = 5;
|
size = 5;
|
||||||
|
|
||||||
unitCapModifier = 20;
|
unitCapModifier = 20;
|
||||||
|
researchCostMultiplier = 0.06f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
vault = new StorageBlock("vault"){{
|
vault = new StorageBlock("vault"){{
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
freezing = new StatusEffect("freezing"){{
|
freezing = new StatusEffect("freezing"){{
|
||||||
speedMultiplier = 0.6f;
|
speedMultiplier = 0.6f;
|
||||||
armorMultiplier = 0.8f;
|
healthMultiplier = 0.8f;
|
||||||
effect = Fx.freezing;
|
effect = Fx.freezing;
|
||||||
|
|
||||||
init(() -> {
|
init(() -> {
|
||||||
@@ -81,7 +81,7 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
melting = new StatusEffect("melting"){{
|
melting = new StatusEffect("melting"){{
|
||||||
speedMultiplier = 0.8f;
|
speedMultiplier = 0.8f;
|
||||||
armorMultiplier = 0.8f;
|
healthMultiplier = 0.8f;
|
||||||
damage = 0.3f;
|
damage = 0.3f;
|
||||||
effect = Fx.melting;
|
effect = Fx.melting;
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
sapped = new StatusEffect("sapped"){{
|
sapped = new StatusEffect("sapped"){{
|
||||||
speedMultiplier = 0.7f;
|
speedMultiplier = 0.7f;
|
||||||
armorMultiplier = 0.8f;
|
healthMultiplier = 0.8f;
|
||||||
effect = Fx.sapped;
|
effect = Fx.sapped;
|
||||||
effectChance = 0.1f;
|
effectChance = 0.1f;
|
||||||
}};
|
}};
|
||||||
@@ -115,7 +115,7 @@ public class StatusEffects implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
overdrive = new StatusEffect("overdrive"){{
|
overdrive = new StatusEffect("overdrive"){{
|
||||||
armorMultiplier = 0.95f;
|
healthMultiplier = 0.95f;
|
||||||
speedMultiplier = 1.15f;
|
speedMultiplier = 1.15f;
|
||||||
damageMultiplier = 1.4f;
|
damageMultiplier = 1.4f;
|
||||||
damage = -0.01f;
|
damage = -0.01f;
|
||||||
@@ -132,13 +132,13 @@ public class StatusEffects implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
shielded = new StatusEffect("shielded"){{
|
shielded = new StatusEffect("shielded"){{
|
||||||
armorMultiplier = 3f;
|
healthMultiplier = 3f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
boss = new StatusEffect("boss"){{
|
boss = new StatusEffect("boss"){{
|
||||||
permanent = true;
|
permanent = true;
|
||||||
damageMultiplier = 1.5f;
|
damageMultiplier = 2f;
|
||||||
armorMultiplier = 1.5f;
|
healthMultiplier = 2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
shocked = new StatusEffect("shocked");
|
shocked = new StatusEffect("shocked");
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ public class UnitTypes implements ContentList{
|
|||||||
crawler = new UnitType("crawler"){{
|
crawler = new UnitType("crawler"){{
|
||||||
defaultController = SuicideAI::new;
|
defaultController = SuicideAI::new;
|
||||||
|
|
||||||
speed = 0.92f;
|
speed = 1f;
|
||||||
hitSize = 8f;
|
hitSize = 8f;
|
||||||
health = 180;
|
health = 180;
|
||||||
mechSideSway = 0.25f;
|
mechSideSway = 0.25f;
|
||||||
@@ -529,9 +529,9 @@ public class UnitTypes implements ContentList{
|
|||||||
hitEffect = Fx.pulverize;
|
hitEffect = Fx.pulverize;
|
||||||
lifetime = 10f;
|
lifetime = 10f;
|
||||||
speed = 1f;
|
speed = 1f;
|
||||||
splashDamageRadius = 55f;
|
splashDamageRadius = 70f;
|
||||||
instantDisappear = true;
|
instantDisappear = true;
|
||||||
splashDamage = 60f;
|
splashDamage = 80f;
|
||||||
killShooter = true;
|
killShooter = true;
|
||||||
hittable = false;
|
hittable = false;
|
||||||
collidesAir = true;
|
collidesAir = true;
|
||||||
@@ -1145,7 +1145,7 @@ public class UnitTypes implements ContentList{
|
|||||||
speed = 1.9f;
|
speed = 1.9f;
|
||||||
rotateSpeed = 15f;
|
rotateSpeed = 15f;
|
||||||
accel = 0.1f;
|
accel = 0.1f;
|
||||||
range = 70f;
|
range = 130f;
|
||||||
health = 400;
|
health = 400;
|
||||||
buildSpeed = 0.5f;
|
buildSpeed = 0.5f;
|
||||||
engineOffset = 6.5f;
|
engineOffset = 6.5f;
|
||||||
@@ -1187,8 +1187,6 @@ public class UnitTypes implements ContentList{
|
|||||||
healPercent = 5.5f;
|
healPercent = 5.5f;
|
||||||
collidesTeam = true;
|
collidesTeam = true;
|
||||||
backColor = Pal.heal;
|
backColor = Pal.heal;
|
||||||
frontColor = Color.white;
|
|
||||||
backColor = Pal.heal;
|
|
||||||
trailColor = Pal.heal;
|
trailColor = Pal.heal;
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
@@ -1233,7 +1231,7 @@ public class UnitTypes implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
quad = new UnitType("quad"){{
|
quad = new UnitType("quad"){{
|
||||||
armor = 4f;
|
armor = 8f;
|
||||||
health = 6000;
|
health = 6000;
|
||||||
speed = 1.2f;
|
speed = 1.2f;
|
||||||
rotateSpeed = 2f;
|
rotateSpeed = 2f;
|
||||||
@@ -1256,7 +1254,7 @@ public class UnitTypes implements ContentList{
|
|||||||
new Weapon(){{
|
new Weapon(){{
|
||||||
x = y = 0f;
|
x = y = 0f;
|
||||||
mirror = false;
|
mirror = false;
|
||||||
reload = 60f;
|
reload = 55f;
|
||||||
minShootVelocity = 0.01f;
|
minShootVelocity = 0.01f;
|
||||||
|
|
||||||
bullet = new BasicBulletType(){{
|
bullet = new BasicBulletType(){{
|
||||||
@@ -1289,9 +1287,9 @@ public class UnitTypes implements ContentList{
|
|||||||
speed = 0.001f;
|
speed = 0.001f;
|
||||||
collides = false;
|
collides = false;
|
||||||
|
|
||||||
healPercent = 10f;
|
healPercent = 15f;
|
||||||
splashDamage = 240f;
|
splashDamage = 320f;
|
||||||
splashDamageRadius = 115f;
|
splashDamageRadius = 120f;
|
||||||
}};
|
}};
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
@@ -1546,7 +1544,7 @@ public class UnitTypes implements ContentList{
|
|||||||
xRand = 8f;
|
xRand = 8f;
|
||||||
shotDelay = 1f;
|
shotDelay = 1f;
|
||||||
|
|
||||||
bullet = new MissileBulletType(4.2f, 25){{
|
bullet = new MissileBulletType(4.2f, 30){{
|
||||||
homingPower = 0.12f;
|
homingPower = 0.12f;
|
||||||
width = 8f;
|
width = 8f;
|
||||||
height = 8f;
|
height = 8f;
|
||||||
@@ -1554,8 +1552,8 @@ public class UnitTypes implements ContentList{
|
|||||||
drag = -0.003f;
|
drag = -0.003f;
|
||||||
homingRange = 80f;
|
homingRange = 80f;
|
||||||
keepVelocity = false;
|
keepVelocity = false;
|
||||||
splashDamageRadius = 25f;
|
splashDamageRadius = 30f;
|
||||||
splashDamage = 25f;
|
splashDamage = 35f;
|
||||||
lifetime = 56f;
|
lifetime = 56f;
|
||||||
trailColor = Pal.bulletYellowBack;
|
trailColor = Pal.bulletYellowBack;
|
||||||
backColor = Pal.bulletYellowBack;
|
backColor = Pal.bulletYellowBack;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ public class Weathers implements ContentList{
|
|||||||
if(tile != null && tile.floor().liquidDrop == Liquids.water){
|
if(tile != null && tile.floor().liquidDrop == Liquids.water){
|
||||||
Draw.color(Tmp.c1.set(tile.floor().mapColor).mul(1.5f).a(state.opacity()));
|
Draw.color(Tmp.c1.set(tile.floor().mapColor).mul(1.5f).a(state.opacity()));
|
||||||
Draw.rect(splashes[(int)(life * (splashes.length - 1))], x, y);
|
Draw.rect(splashes[(int)(life * (splashes.length - 1))], x, y);
|
||||||
}else{
|
}else if(tile != null && tile.floor().liquidDrop == null && !tile.floor().solid){
|
||||||
Draw.color(Color.royal, Color.white, 0.3f);
|
Draw.color(Color.royal, Color.white, 0.3f);
|
||||||
Draw.alpha(Mathf.slope(life) * state.opacity());
|
Draw.alpha(Mathf.slope(life) * state.opacity());
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import mindustry.game.EventType.*;
|
|||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.game.Teams.*;
|
import mindustry.game.Teams.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.maps.*;
|
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.type.Weather.*;
|
import mindustry.type.Weather.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
@@ -89,13 +88,16 @@ public class Logic implements ApplicationListener{
|
|||||||
if(state.isCampaign()){
|
if(state.isCampaign()){
|
||||||
long seconds = state.rules.sector.getSecondsPassed();
|
long seconds = state.rules.sector.getSecondsPassed();
|
||||||
CoreBuild core = state.rules.defaultTeam.core();
|
CoreBuild core = state.rules.defaultTeam.core();
|
||||||
|
//THE WAVES NEVER END
|
||||||
|
state.rules.waves = true;
|
||||||
|
|
||||||
//apply fractional damage based on how many turns have passed for this sector
|
//apply fractional damage based on how many turns have passed for this sector
|
||||||
float turnsPassed = seconds / (turnDuration / 60f);
|
//float turnsPassed = seconds / (turnDuration / 60f);
|
||||||
|
|
||||||
if(state.rules.sector.hasWaves() && turnsPassed > 0 && state.rules.sector.hasBase()){
|
//TODO sector damage disabled for now
|
||||||
SectorDamage.apply(turnsPassed / sectorDestructionTurns);
|
//if(state.rules.sector.hasWaves() && turnsPassed > 0 && state.rules.sector.hasBase()){
|
||||||
}
|
// SectorDamage.apply(turnsPassed / sectorDestructionTurns);
|
||||||
|
//}
|
||||||
|
|
||||||
//add resources based on turns passed
|
//add resources based on turns passed
|
||||||
if(state.rules.sector.save != null && core != null){
|
if(state.rules.sector.save != null && core != null){
|
||||||
@@ -197,6 +199,8 @@ public class Logic implements ApplicationListener{
|
|||||||
state.rules.waves = false;
|
state.rules.waves = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO capturing is disabled
|
||||||
|
/*
|
||||||
//if there's a "win" wave and no enemies are present, win automatically
|
//if there's a "win" wave and no enemies are present, win automatically
|
||||||
if(state.rules.waves && state.enemies == 0 && state.rules.winWave > 0 && state.wave >= state.rules.winWave && !spawner.isSpawning()){
|
if(state.rules.waves && state.enemies == 0 && state.rules.winWave > 0 && state.wave >= state.rules.winWave && !spawner.isSpawning()){
|
||||||
//the sector has been conquered - waves get disabled
|
//the sector has been conquered - waves get disabled
|
||||||
@@ -209,7 +213,7 @@ public class Logic implements ApplicationListener{
|
|||||||
if(!headless){
|
if(!headless){
|
||||||
control.saves.saveSector(state.rules.sector);
|
control.saves.saveSector(state.rules.sector);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}else{
|
}else{
|
||||||
if(!state.rules.attackMode && state.teams.playerCores().size == 0 && !state.gameOver){
|
if(!state.rules.attackMode && state.teams.playerCores().size == 0 && !state.gameOver){
|
||||||
state.gameOver = true;
|
state.gameOver = true;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public abstract class UnlockableContent extends MappableContent{
|
|||||||
/** Whether this content is always unlocked in the tech tree. */
|
/** Whether this content is always unlocked in the tech tree. */
|
||||||
public boolean alwaysUnlocked = false;
|
public boolean alwaysUnlocked = false;
|
||||||
/** Icons by Cicon ID.*/
|
/** Icons by Cicon ID.*/
|
||||||
protected TextureRegion[] cicons = new TextureRegion[mindustry.ui.Cicon.all.length];
|
protected TextureRegion[] cicons = new TextureRegion[Cicon.all.length];
|
||||||
/** Unlock state. Loaded from settings. Do not modify outside of the constructor. */
|
/** Unlock state. Loaded from settings. Do not modify outside of the constructor. */
|
||||||
protected boolean unlocked;
|
protected boolean unlocked;
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,6 @@ abstract class BuilderComp implements Unitc{
|
|||||||
current.progress = entity.progress;
|
current.progress = entity.progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
||||||
void drawBuildRequests(){
|
void drawBuildRequests(){
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
transient int rotation;
|
transient int rotation;
|
||||||
transient boolean enabled = true;
|
transient boolean enabled = true;
|
||||||
transient float enabledControlTime;
|
transient float enabledControlTime;
|
||||||
|
transient String lastAccessed;
|
||||||
|
|
||||||
PowerModule power;
|
PowerModule power;
|
||||||
ItemModule items;
|
ItemModule items;
|
||||||
@@ -348,6 +349,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
//endregion
|
//endregion
|
||||||
//region handler methods
|
//region handler methods
|
||||||
|
|
||||||
|
/** Called when an unloader takes an item. */
|
||||||
|
public void itemTaken(Item item){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when this block is dropped as a payload. */
|
/** Called when this block is dropped as a payload. */
|
||||||
public void dropped(){
|
public void dropped(){
|
||||||
|
|
||||||
@@ -874,6 +880,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
//null is of type void.class; anonymous classes use their superclass.
|
//null is of type void.class; anonymous classes use their superclass.
|
||||||
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
|
Class<?> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
|
||||||
|
|
||||||
|
if(builder != null && builder.isPlayer()){
|
||||||
|
lastAccessed = builder.getPlayer().name;
|
||||||
|
}
|
||||||
|
|
||||||
if(block.configurations.containsKey(type)){
|
if(block.configurations.containsKey(type)){
|
||||||
block.configurations.get(type).get(this, value);
|
block.configurations.get(type).get(this, value);
|
||||||
}
|
}
|
||||||
@@ -1038,6 +1048,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(net.active() && lastAccessed != null){
|
||||||
|
table.row();
|
||||||
|
table.add(Core.bundle.format("lastaccessed", lastAccessed)).growX().wrap().left();
|
||||||
|
}
|
||||||
|
|
||||||
table.marginBottom(-5);
|
table.marginBottom(-5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,10 +86,10 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(payload instanceof BuildPayload){
|
if(payload instanceof BuildPayload b){
|
||||||
return dropBlock((BuildPayload)payload);
|
return dropBlock(b);
|
||||||
}else if(payload instanceof UnitPayload){
|
}else if(payload instanceof UnitPayload p){
|
||||||
return dropUnit((UnitPayload)payload);
|
return dropUnit(p);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -126,6 +126,8 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
|
|||||||
int rot = (int)((rotation + 45f) / 90f) % 4;
|
int rot = (int)((rotation + 45f) / 90f) % 4;
|
||||||
payload.place(on, rot);
|
payload.place(on, rot);
|
||||||
|
|
||||||
|
if(isPlayer()) payload.build.lastAccessed = getPlayer().name;
|
||||||
|
|
||||||
Fx.unitDrop.at(tile);
|
Fx.unitDrop.at(tile);
|
||||||
Fx.placeBlock.at(on.drawx(), on.drawy(), on.block().size);
|
Fx.placeBlock.at(on.drawx(), on.drawy(), on.block().size);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
@Component
|
@Component
|
||||||
abstract class ShieldComp implements Healthc, Posc{
|
abstract class ShieldComp implements Healthc, Posc{
|
||||||
@Import float health, hitTime, x, y;
|
@Import float health, hitTime, x, y, healthMultiplier;
|
||||||
@Import boolean dead;
|
@Import boolean dead;
|
||||||
|
|
||||||
/** Absorbs health damage. */
|
/** Absorbs health damage. */
|
||||||
@@ -22,6 +22,7 @@ abstract class ShieldComp implements Healthc, Posc{
|
|||||||
@Replace
|
@Replace
|
||||||
@Override
|
@Override
|
||||||
public void damage(float amount){
|
public void damage(float amount){
|
||||||
|
amount /= healthMultiplier;
|
||||||
//apply armor
|
//apply armor
|
||||||
amount = Math.max(amount - armor, minArmorDamage * amount);
|
amount = Math.max(amount - armor, minArmorDamage * amount);
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ abstract class StatusComp implements Posc, Flyingc{
|
|||||||
private Seq<StatusEntry> statuses = new Seq<>();
|
private Seq<StatusEntry> statuses = new Seq<>();
|
||||||
private transient Bits applied = new Bits(content.getBy(ContentType.status).size);
|
private transient Bits applied = new Bits(content.getBy(ContentType.status).size);
|
||||||
|
|
||||||
@ReadOnly transient float speedMultiplier = 1, damageMultiplier = 1, armorMultiplier = 1, reloadMultiplier = 1;
|
@ReadOnly transient float speedMultiplier = 1, damageMultiplier = 1, healthMultiplier = 1, reloadMultiplier = 1;
|
||||||
|
|
||||||
@Import UnitType type;
|
@Import UnitType type;
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ abstract class StatusComp implements Posc, Flyingc{
|
|||||||
}
|
}
|
||||||
|
|
||||||
applied.clear();
|
applied.clear();
|
||||||
speedMultiplier = damageMultiplier = armorMultiplier = reloadMultiplier = 1f;
|
speedMultiplier = damageMultiplier = healthMultiplier = reloadMultiplier = 1f;
|
||||||
|
|
||||||
if(statuses.isEmpty()) return;
|
if(statuses.isEmpty()) return;
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ abstract class StatusComp implements Posc, Flyingc{
|
|||||||
statuses.remove(index);
|
statuses.remove(index);
|
||||||
}else{
|
}else{
|
||||||
speedMultiplier *= entry.effect.speedMultiplier;
|
speedMultiplier *= entry.effect.speedMultiplier;
|
||||||
armorMultiplier *= entry.effect.armorMultiplier;
|
healthMultiplier *= entry.effect.healthMultiplier;
|
||||||
damageMultiplier *= entry.effect.damageMultiplier;
|
damageMultiplier *= entry.effect.damageMultiplier;
|
||||||
reloadMultiplier *= entry.effect.reloadMultiplier;
|
reloadMultiplier *= entry.effect.reloadMultiplier;
|
||||||
entry.effect.update(self(), entry.time);
|
entry.effect.update(self(), entry.time);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class AIController implements UnitController{
|
|||||||
|
|
||||||
protected Unit unit;
|
protected Unit unit;
|
||||||
protected Interval timer = new Interval(4);
|
protected Interval timer = new Interval(4);
|
||||||
|
protected AIController fallback;
|
||||||
|
|
||||||
/** main target that is being faced */
|
/** main target that is being faced */
|
||||||
protected Teamc target;
|
protected Teamc target;
|
||||||
@@ -34,11 +35,27 @@ public class AIController implements UnitController{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateUnit(){
|
public void updateUnit(){
|
||||||
|
//use fallback AI when possible
|
||||||
|
if(useFallback() && (fallback != null || (fallback = fallback()) != null)){
|
||||||
|
if(fallback.unit != unit) fallback.unit(unit);
|
||||||
|
fallback.updateUnit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateVisuals();
|
updateVisuals();
|
||||||
updateTargeting();
|
updateTargeting();
|
||||||
updateMovement();
|
updateMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected AIController fallback(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean useFallback(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected UnitCommand command(){
|
protected UnitCommand command(){
|
||||||
return unit.team.data().command;
|
return unit.team.data().command;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ public class DefaultWaves{
|
|||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
max = 20;
|
max = 20;
|
||||||
|
shieldScaling = 30;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(dagger){{
|
new SpawnGroup(dagger){{
|
||||||
@@ -144,6 +145,7 @@ public class DefaultWaves{
|
|||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
|
shieldScaling = 20;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(flare){{
|
new SpawnGroup(flare){{
|
||||||
@@ -162,6 +164,7 @@ public class DefaultWaves{
|
|||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
spacing = 5;
|
spacing = 5;
|
||||||
max = 16;
|
max = 16;
|
||||||
|
shieldScaling = 30;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(nova){{
|
new SpawnGroup(nova){{
|
||||||
@@ -169,6 +172,7 @@ public class DefaultWaves{
|
|||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
spacing = 4;
|
spacing = 4;
|
||||||
|
shieldScaling = 20;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(atrax){{
|
new SpawnGroup(atrax){{
|
||||||
@@ -192,15 +196,15 @@ public class DefaultWaves{
|
|||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 40;
|
spacing = 40;
|
||||||
shieldScaling = 10f;
|
shieldScaling = 20f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(antumbra){{
|
new SpawnGroup(antumbra){{
|
||||||
begin = 131;
|
begin = 120;
|
||||||
unitAmount = 1;
|
unitAmount = 1;
|
||||||
unitScaling = 1;
|
unitScaling = 1;
|
||||||
spacing = 40;
|
spacing = 40;
|
||||||
shieldScaling = 10f;
|
shieldScaling = 20f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(vela){{
|
new SpawnGroup(vela){{
|
||||||
@@ -211,6 +215,15 @@ public class DefaultWaves{
|
|||||||
shieldScaling = 20f;
|
shieldScaling = 20f;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
new SpawnGroup(corvus){{
|
||||||
|
begin = 145;
|
||||||
|
unitAmount = 1;
|
||||||
|
unitScaling = 1;
|
||||||
|
spacing = 35;
|
||||||
|
shieldScaling = 30f;
|
||||||
|
shields = 100;
|
||||||
|
}},
|
||||||
|
|
||||||
new SpawnGroup(horizon){{
|
new SpawnGroup(horizon){{
|
||||||
begin = 90;
|
begin = 90;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
@@ -252,7 +265,7 @@ public class DefaultWaves{
|
|||||||
//max reasonable wave, after which everything gets boring
|
//max reasonable wave, after which everything gets boring
|
||||||
int cap = 200;
|
int cap = 200;
|
||||||
|
|
||||||
float shieldStart = 30, shieldsPerWave = 15 + difficulty*20f;
|
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
|
||||||
|
|
||||||
Intc createProgression = start -> {
|
Intc createProgression = start -> {
|
||||||
//main sequence
|
//main sequence
|
||||||
@@ -314,8 +327,8 @@ public class DefaultWaves{
|
|||||||
step += (int)(Mathf.random(12, 25) * Mathf.lerp(1f, 0.4f, difficulty));
|
step += (int)(Mathf.random(12, 25) * Mathf.lerp(1f, 0.4f, difficulty));
|
||||||
}
|
}
|
||||||
|
|
||||||
int bossWave = Mathf.random(30, 60);
|
int bossWave = (int)(Mathf.random(30, 60) * Mathf.lerp(1f, 0.7f, difficulty));
|
||||||
int bossSpacing = Mathf.random(30, 50);
|
int bossSpacing = (int)(Mathf.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty));
|
||||||
|
|
||||||
//main boss progression
|
//main boss progression
|
||||||
out.add(new SpawnGroup(Structs.random(species)[4]){{
|
out.add(new SpawnGroup(Structs.random(species)[4]){{
|
||||||
@@ -339,6 +352,14 @@ public class DefaultWaves{
|
|||||||
shieldScaling = shieldsPerWave;
|
shieldScaling = shieldsPerWave;
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
//shift back waves on higher difficulty for a harder start
|
||||||
|
int shift = Math.max((int)(difficulty * 15 - 5), 0);
|
||||||
|
|
||||||
|
for(SpawnGroup group : out){
|
||||||
|
group.begin -= shift;
|
||||||
|
group.end -= shift;
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class Objectives{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO fix
|
||||||
public static class SectorComplete extends SectorObjective{
|
public static class SectorComplete extends SectorObjective{
|
||||||
|
|
||||||
public SectorComplete(SectorPreset zone){
|
public SectorComplete(SectorPreset zone){
|
||||||
@@ -38,12 +39,12 @@ public class Objectives{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean complete(){
|
public boolean complete(){
|
||||||
return preset.sector.isCaptured();
|
return preset.sector.save != null && preset.sector.save.meta.wave >= preset.sector.save.meta.rules.winWave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String display(){
|
public String display(){
|
||||||
return Core.bundle.format("requirement.capture", preset.localizedName);
|
return Core.bundle.format("requirement.wave", preset.sector.save == null ? "<unknown>" : preset.sector.save.meta.rules.winWave, preset.localizedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ public class Schematic implements Publishable, Comparable<Schematic>{
|
|||||||
return tags.get("name", "unknown");
|
return tags.get("name", "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String description(){
|
||||||
|
return tags.get("description", "");
|
||||||
|
}
|
||||||
|
|
||||||
public void save(){
|
public void save(){
|
||||||
schematics.saveChanges(this);
|
schematics.saveChanges(this);
|
||||||
}
|
}
|
||||||
@@ -90,7 +94,7 @@ public class Schematic implements Publishable, Comparable<Schematic>{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String steamDescription(){
|
public String steamDescription(){
|
||||||
return null;
|
return description();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import mindustry.world.*;
|
|||||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
import mindustry.world.modules.*;
|
import mindustry.world.modules.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class SectorInfo{
|
public class SectorInfo{
|
||||||
@@ -42,7 +44,15 @@ public class SectorInfo{
|
|||||||
/** Counter refresh state. */
|
/** Counter refresh state. */
|
||||||
private transient Interval time = new Interval();
|
private transient Interval time = new Interval();
|
||||||
/** Core item storage to prevent spoofing. */
|
/** Core item storage to prevent spoofing. */
|
||||||
private transient int[] lastCoreItems;
|
private transient int[] coreItemCounts;
|
||||||
|
|
||||||
|
/** Handles core item changes. */
|
||||||
|
public void handleCoreItem(Item item, int amount){
|
||||||
|
if(coreItemCounts == null){
|
||||||
|
coreItemCounts = new int[content.items().size];
|
||||||
|
}
|
||||||
|
coreItemCounts[item.id] += amount;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return the real location items go when launched on this sector */
|
/** @return the real location items go when launched on this sector */
|
||||||
public Sector getRealDestination(){
|
public Sector getRealDestination(){
|
||||||
@@ -105,12 +115,6 @@ public class SectorInfo{
|
|||||||
universe.runTurn();
|
universe.runTurn();
|
||||||
}
|
}
|
||||||
|
|
||||||
//create last stored core items
|
|
||||||
if(lastCoreItems == null){
|
|
||||||
lastCoreItems = new int[content.items().size];
|
|
||||||
updateCoreDeltas();
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreBuild ent = state.rules.defaultTeam.core();
|
CoreBuild ent = state.rules.defaultTeam.core();
|
||||||
|
|
||||||
//refresh throughput
|
//refresh throughput
|
||||||
@@ -124,15 +128,16 @@ public class SectorInfo{
|
|||||||
stat.loaded = true;
|
stat.loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//how the resources changed - only interested in negative deltas, since that's what happens during spoofing
|
|
||||||
int coreDelta = Math.min(ent == null ? 0 : ent.items.get(item) - lastCoreItems[item.id], 0);
|
|
||||||
|
|
||||||
//add counter, subtract how many items were taken from the core during this time
|
//add counter, subtract how many items were taken from the core during this time
|
||||||
stat.means.add(Math.max(stat.counter + coreDelta, 0));
|
stat.means.add(Math.max(stat.counter, 0));
|
||||||
stat.counter = 0;
|
stat.counter = 0;
|
||||||
stat.mean = stat.means.rawMean();
|
stat.mean = stat.means.rawMean();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(coreItemCounts == null){
|
||||||
|
coreItemCounts = new int[content.items().size];
|
||||||
|
}
|
||||||
|
|
||||||
//refresh core items
|
//refresh core items
|
||||||
for(Item item : content.items()){
|
for(Item item : content.items()){
|
||||||
ExportStat stat = production.get(item, ExportStat::new);
|
ExportStat stat = production.get(item, ExportStat::new);
|
||||||
@@ -143,21 +148,14 @@ public class SectorInfo{
|
|||||||
|
|
||||||
//get item delta
|
//get item delta
|
||||||
//TODO is preventing negative production a good idea?
|
//TODO is preventing negative production a good idea?
|
||||||
int delta = Math.max((ent == null ? 0 : ent.items.get(item)) - lastCoreItems[item.id], 0);
|
int delta = Math.max(ent == null ? 0 : coreItemCounts[item.id], 0);
|
||||||
|
|
||||||
//store means
|
//store means
|
||||||
stat.means.add(delta);
|
stat.means.add(delta);
|
||||||
stat.mean = stat.means.rawMean();
|
stat.mean = stat.means.rawMean();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCoreDeltas();
|
Arrays.fill(coreItemCounts, 0);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCoreDeltas(){
|
|
||||||
CoreBuild ent = state.rules.defaultTeam.core();
|
|
||||||
for(int i = 0; i < lastCoreItems.length; i++){
|
|
||||||
lastCoreItems[i] = ent == null ? 0 : ent.items.get(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class SpawnGroup implements Serializable{
|
|||||||
/** The spacing, in waves, of spawns. For example, 2 = spawns every other wave */
|
/** The spacing, in waves, of spawns. For example, 2 = spawns every other wave */
|
||||||
public int spacing = 1;
|
public int spacing = 1;
|
||||||
/** Maximum amount of units that spawn */
|
/** Maximum amount of units that spawn */
|
||||||
public int max = 100;
|
public int max = 40;
|
||||||
/** How many waves need to pass before the amount of units spawned increases by 1 */
|
/** How many waves need to pass before the amount of units spawned increases by 1 */
|
||||||
public float unitScaling = never;
|
public float unitScaling = never;
|
||||||
/** Shield points that this unit has. */
|
/** Shield points that this unit has. */
|
||||||
@@ -88,7 +88,7 @@ public class SpawnGroup implements Serializable{
|
|||||||
if(begin != 0) json.writeValue("begin", begin);
|
if(begin != 0) json.writeValue("begin", begin);
|
||||||
if(end != never) json.writeValue("end", end);
|
if(end != never) json.writeValue("end", end);
|
||||||
if(spacing != 1) json.writeValue("spacing", spacing);
|
if(spacing != 1) json.writeValue("spacing", spacing);
|
||||||
//if(max != 40) json.writeValue("max", max);
|
if(max != 40) json.writeValue("max", max);
|
||||||
if(unitScaling != never) json.writeValue("scaling", unitScaling);
|
if(unitScaling != never) json.writeValue("scaling", unitScaling);
|
||||||
if(shields != 0) json.writeValue("shields", shields);
|
if(shields != 0) json.writeValue("shields", shields);
|
||||||
if(shieldScaling != 0) json.writeValue("shieldScaling", shieldScaling);
|
if(shieldScaling != 0) json.writeValue("shieldScaling", shieldScaling);
|
||||||
@@ -105,12 +105,18 @@ public class SpawnGroup implements Serializable{
|
|||||||
begin = data.getInt("begin", 0);
|
begin = data.getInt("begin", 0);
|
||||||
end = data.getInt("end", never);
|
end = data.getInt("end", never);
|
||||||
spacing = data.getInt("spacing", 1);
|
spacing = data.getInt("spacing", 1);
|
||||||
//max = data.getInt("max", 40);
|
max = data.getInt("max", 40);
|
||||||
unitScaling = data.getFloat("scaling", never);
|
unitScaling = data.getFloat("scaling", never);
|
||||||
shields = data.getFloat("shields", 0);
|
shields = data.getFloat("shields", 0);
|
||||||
shieldScaling = data.getFloat("shieldScaling", 0);
|
shieldScaling = data.getFloat("shieldScaling", 0);
|
||||||
unitAmount = data.getInt("amount", 1);
|
unitAmount = data.getInt("amount", 1);
|
||||||
effect = content.getByName(ContentType.status, data.hasChild("effect") && data.getChild("effect").isString() ? data.getString("effect", "none") : "none");
|
|
||||||
|
//old boss effect ID
|
||||||
|
if(data.has("effect") && data.get("effect").isNumber() && data.getInt("effect", -1) == 8){
|
||||||
|
effect = StatusEffects.boss;
|
||||||
|
}else{
|
||||||
|
effect = content.getByName(ContentType.status, data.has("effect") && data.get("effect").isString() ? data.getString("effect", "none") : "none");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -140,8 +140,9 @@ public class Universe{
|
|||||||
if(!sector.isBeingPlayed()){
|
if(!sector.isBeingPlayed()){
|
||||||
sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed);
|
sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed);
|
||||||
|
|
||||||
|
//TODO sector damage disabled for now
|
||||||
//check if the sector has been attacked too many times...
|
//check if the sector has been attacked too many times...
|
||||||
if(sector.hasBase() && sector.hasWaves() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){
|
/*if(sector.hasBase() && sector.hasWaves() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){
|
||||||
//fire event for losing the sector
|
//fire event for losing the sector
|
||||||
Events.fire(new SectorLoseEvent(sector));
|
Events.fire(new SectorLoseEvent(sector));
|
||||||
|
|
||||||
@@ -151,17 +152,17 @@ public class Universe{
|
|||||||
//clear recieved
|
//clear recieved
|
||||||
sector.setExtraItems(new ItemSeq());
|
sector.setExtraItems(new ItemSeq());
|
||||||
sector.save = null;
|
sector.save = null;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//export to another sector
|
//export to another sector
|
||||||
if(sector.save != null && sector.save.meta != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.destination != null){
|
if(sector.save != null && sector.save.meta != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.destination != null){
|
||||||
Sector to = sector.save.meta.secinfo.destination;
|
Sector to = sector.save.meta.secinfo.destination;
|
||||||
if(to.save != null){
|
if(to.save != null){
|
||||||
ItemSeq items = to.getExtraItems();
|
ItemSeq items = new ItemSeq();
|
||||||
//calculated exported items to this sector
|
//calculated exported items to this sector
|
||||||
sector.save.meta.secinfo.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed)));
|
sector.save.meta.secinfo.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed)));
|
||||||
to.setExtraItems(items);
|
to.addItems(items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import arc.math.*;
|
|||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
|
import mindustry.ai.types.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
@@ -151,6 +152,13 @@ public class OverlayRenderer{
|
|||||||
|
|
||||||
input.drawOverSelect();
|
input.drawOverSelect();
|
||||||
|
|
||||||
|
if(ui.hudfrag.blockfrag.hover() instanceof Unit unit && unit.controller() instanceof LogicAI ai && ai.controller instanceof Building build){
|
||||||
|
Drawf.square(build.x, build.y, build.block.size * tilesize/2f + 2f);
|
||||||
|
if(!unit.within(build, unit.hitSize * 2f)){
|
||||||
|
Drawf.arrow(unit.x, unit.y, build.x, build.y, unit.hitSize *2f, 4f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//draw selection overlay when dropping item
|
//draw selection overlay when dropping item
|
||||||
if(input.isDroppingItem()){
|
if(input.isDroppingItem()){
|
||||||
Vec2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
|
Vec2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY());
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
public void update(){
|
public void update(){
|
||||||
super.update();
|
super.update();
|
||||||
|
|
||||||
if(net.active() && Core.input.keyTap(Binding.player_list) && (scene.getKeyboardFocus() == null || scene.getKeyboardFocus().isDescendantOf(ui.listfrag.content))){
|
if(net.active() && Core.input.keyTap(Binding.player_list) && (scene.getKeyboardFocus() == null || scene.getKeyboardFocus().isDescendantOf(ui.listfrag.content) || scene.getKeyboardFocus().isDescendantOf(ui.minimapfrag.elem))){
|
||||||
ui.listfrag.toggle();
|
ui.listfrag.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true)
|
@Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true)
|
||||||
public static void rotateBlock(Player player, Building tile, boolean direction){
|
public static void rotateBlock(@Nullable Player player, Building tile, boolean direction){
|
||||||
if(tile == null) return;
|
if(tile == null) return;
|
||||||
|
|
||||||
if(net.server() && (!Units.canInteract(player, tile) ||
|
if(net.server() && (!Units.canInteract(player, tile) ||
|
||||||
@@ -264,6 +264,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
throw new ValidateException(player, "Player cannot rotate a block.");
|
throw new ValidateException(player, "Player cannot rotate a block.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(player != null) tile.lastAccessed = player.name;
|
||||||
tile.rotation = Mathf.mod(tile.rotation + Mathf.sign(direction), 4);
|
tile.rotation = Mathf.mod(tile.rotation + Mathf.sign(direction), 4);
|
||||||
tile.updateProximity();
|
tile.updateProximity();
|
||||||
tile.noSleep();
|
tile.noSleep();
|
||||||
@@ -531,6 +532,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
lastSchematic.tags.put("name", text);
|
lastSchematic.tags.put("name", text);
|
||||||
|
lastSchematic.tags.put("description", "");
|
||||||
schematics.add(lastSchematic);
|
schematics.add(lastSchematic);
|
||||||
ui.showInfoFade("@schematic.saved");
|
ui.showInfoFade("@schematic.saved");
|
||||||
ui.schematics.showInfo(lastSchematic);
|
ui.schematics.showInfo(lastSchematic);
|
||||||
|
|||||||
@@ -290,12 +290,15 @@ public class TypeIO{
|
|||||||
|
|
||||||
public static void writeController(Writes write, UnitController control){
|
public static void writeController(Writes write, UnitController control){
|
||||||
//no real unit controller state is written, only the type
|
//no real unit controller state is written, only the type
|
||||||
if(control instanceof Player){
|
if(control instanceof Player p){
|
||||||
write.b(0);
|
write.b(0);
|
||||||
write.i(((Player)control).id);
|
write.i(p.id);
|
||||||
}else if(control instanceof FormationAI){
|
}else if(control instanceof FormationAI form){
|
||||||
write.b(1);
|
write.b(1);
|
||||||
write.i(((FormationAI)control).leader.id);
|
write.i(form.leader.id);
|
||||||
|
}else if(control instanceof LogicAI logic && logic.controller != null){
|
||||||
|
write.b(3);
|
||||||
|
write.i(logic.controller.pos());
|
||||||
}else{
|
}else{
|
||||||
write.b(2);
|
write.b(2);
|
||||||
}
|
}
|
||||||
@@ -312,6 +315,19 @@ public class TypeIO{
|
|||||||
}else if(type == 1){ //formation controller
|
}else if(type == 1){ //formation controller
|
||||||
int id = read.i();
|
int id = read.i();
|
||||||
return prev instanceof FormationAI ? prev : new FormationAI(Groups.unit.getByID(id), null);
|
return prev instanceof FormationAI ? prev : new FormationAI(Groups.unit.getByID(id), null);
|
||||||
|
}else if(type == 3){
|
||||||
|
int pos = read.i();
|
||||||
|
if(prev instanceof LogicAI pai){
|
||||||
|
pai.controller = world.build(pos);
|
||||||
|
return pai;
|
||||||
|
}else{
|
||||||
|
//create new AI for assignment
|
||||||
|
LogicAI out = new LogicAI();
|
||||||
|
//instantly time out when updated.
|
||||||
|
out.controlTimer = LogicAI.logicControlTimeout;
|
||||||
|
out.controller = world.build(pos);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
//there are two cases here:
|
//there are two cases here:
|
||||||
//1: prev controller was not a player, carry on
|
//1: prev controller was not a player, carry on
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ public class LAssembler{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//used as a special value for any environmental solid block
|
||||||
|
putConst("@solid", Blocks.stoneWall);
|
||||||
|
|
||||||
putConst("@air", Blocks.air);
|
putConst("@air", Blocks.air);
|
||||||
|
|
||||||
for(UnitType type : Vars.content.units()){
|
for(UnitType type : Vars.content.units()){
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import arc.util.*;
|
|||||||
import arc.util.noise.*;
|
import arc.util.noise.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.ai.types.*;
|
import mindustry.ai.types.*;
|
||||||
|
import mindustry.content.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
@@ -251,6 +252,11 @@ public class LExecutor{
|
|||||||
case spawn -> {
|
case spawn -> {
|
||||||
res = Geometry.findClosest(unit.x, unit.y, Vars.spawner.getSpawns());
|
res = Geometry.findClosest(unit.x, unit.y, Vars.spawner.getSpawns());
|
||||||
}
|
}
|
||||||
|
case damaged -> {
|
||||||
|
Building b = Units.findDamagedTile(unit.team, unit.x, unit.y);
|
||||||
|
res = b == null ? null : b.tile;
|
||||||
|
build = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(res != null && (!build || res.build != null)){
|
if(res != null && (!build || res.build != null)){
|
||||||
@@ -435,12 +441,16 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
case getBlock -> {
|
case getBlock -> {
|
||||||
float x = exec.numf(p1), y = exec.numf(p2);
|
float x = exec.numf(p1), y = exec.numf(p2);
|
||||||
if(unit.within(x, y, unit.range())){
|
float range = Math.max(unit.range(), buildingRange);
|
||||||
|
if(!unit.within(x, y, range)){
|
||||||
exec.setobj(p3, null);
|
exec.setobj(p3, null);
|
||||||
|
exec.setnum(p4, 0);
|
||||||
}else{
|
}else{
|
||||||
Tile tile = world.tileWorld(x, y);
|
Tile tile = world.tileWorld(x, y);
|
||||||
Block block = tile == null || !tile.synthetic() ? null : tile.block();
|
//any environmental solid block is returned as StoneWall, aka "@solid"
|
||||||
|
Block block = tile == null ? null : !tile.synthetic() ? (tile.solid() ? Blocks.stoneWall : Blocks.air) : tile.block();
|
||||||
exec.setobj(p3, block);
|
exec.setobj(p3, block);
|
||||||
|
exec.setnum(p4, tile != null && tile.build != null ? tile.build.rotation : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case itemDrop -> {
|
case itemDrop -> {
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package mindustry.logic;
|
|||||||
public enum LLocate{
|
public enum LLocate{
|
||||||
ore,
|
ore,
|
||||||
building,
|
building,
|
||||||
spawn;
|
spawn,
|
||||||
|
damaged;
|
||||||
|
|
||||||
public static final LLocate[] all = values();
|
public static final LLocate[] all = values();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -889,7 +889,7 @@ public class LStatements{
|
|||||||
table.row();
|
table.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
case spawn -> {
|
case spawn, damaged -> {
|
||||||
table.row();
|
table.row();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public enum LUnitControl{
|
|||||||
mine("x", "y"),
|
mine("x", "y"),
|
||||||
flag("value"),
|
flag("value"),
|
||||||
build("x", "y", "block", "rotation"),
|
build("x", "y", "block", "rotation"),
|
||||||
getBlock("x", "y", "result"),
|
getBlock("x", "y", "result", "resRot"),
|
||||||
within("x", "y", "radius", "result");
|
within("x", "y", "radius", "result");
|
||||||
|
|
||||||
public final String[] params;
|
public final String[] params;
|
||||||
|
|||||||
@@ -98,7 +98,9 @@ public class Map implements Comparable<Map>, Publishable{
|
|||||||
|
|
||||||
public Rules rules(Rules base){
|
public Rules rules(Rules base){
|
||||||
try{
|
try{
|
||||||
Rules result = JsonIO.read(Rules.class, base, tags.get("rules", "{}"));
|
//this replacement is a MASSIVE hack but it fixes some incorrect overwriting of team-specific rules.
|
||||||
|
//may need to be tweaked later
|
||||||
|
Rules result = JsonIO.read(Rules.class, base, tags.get("rules", "{}").replace("teams:{2:{infiniteAmmo:true}},", ""));
|
||||||
if(result.spawns.isEmpty()) result.spawns = Vars.defaultWaves.get();
|
if(result.spawns.isEmpty()) result.spawns = Vars.defaultWaves.get();
|
||||||
return result;
|
return result;
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
float constraint = 1.3f;
|
float constraint = 1.3f;
|
||||||
float radius = width / 2f / Mathf.sqrt3;
|
float radius = width / 2f / Mathf.sqrt3;
|
||||||
int rooms = rand.random(2, 5);
|
int rooms = rand.random(2, 5);
|
||||||
Seq<Room> array = new Seq<>();
|
Seq<Room> roomseq = new Seq<>();
|
||||||
|
|
||||||
for(int i = 0; i < rooms; i++){
|
for(int i = 0; i < rooms; i++){
|
||||||
Tmp.v1.trns(rand.random(360f), rand.random(radius / constraint));
|
Tmp.v1.trns(rand.random(360f), rand.random(radius / constraint));
|
||||||
@@ -153,7 +153,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
float ry = (height/2f + Tmp.v1.y);
|
float ry = (height/2f + Tmp.v1.y);
|
||||||
float maxrad = radius - Tmp.v1.len();
|
float maxrad = radius - Tmp.v1.len();
|
||||||
float rrad = Math.min(rand.random(9f, maxrad / 2f), 30f);
|
float rrad = Math.min(rand.random(9f, maxrad / 2f), 30f);
|
||||||
array.add(new Room((int)rx, (int)ry, (int)rrad));
|
roomseq.add(new Room((int)rx, (int)ry, (int)rrad));
|
||||||
}
|
}
|
||||||
|
|
||||||
//check positions on the map to place the player spawn. this needs to be in the corner of the map
|
//check positions on the map to place the player spawn. this needs to be in the corner of the map
|
||||||
@@ -182,13 +182,13 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(waterTiles <= 4 || (i + angleStep >= 360)){
|
if(waterTiles <= 4 || (i + angleStep >= 360)){
|
||||||
array.add(spawn = new Room(cx, cy, rand.random(8, 15)));
|
roomseq.add(spawn = new Room(cx, cy, rand.random(8, 15)));
|
||||||
|
|
||||||
for(int j = 0; j < enemySpawns; j++){
|
for(int j = 0; j < enemySpawns; j++){
|
||||||
float enemyOffset = rand.range(60f);
|
float enemyOffset = rand.range(60f);
|
||||||
Tmp.v1.set(cx - width/2, cy - height/2).rotate(180f + enemyOffset).add(width/2, height/2);
|
Tmp.v1.set(cx - width/2, cy - height/2).rotate(180f + enemyOffset).add(width/2, height/2);
|
||||||
Room espawn = new Room((int)Tmp.v1.x, (int)Tmp.v1.y, rand.random(8, 15));
|
Room espawn = new Room((int)Tmp.v1.x, (int)Tmp.v1.y, rand.random(8, 15));
|
||||||
array.add(espawn);
|
roomseq.add(espawn);
|
||||||
enemies.add(espawn);
|
enemies.add(espawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,16 +196,16 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Room room : array){
|
for(Room room : roomseq){
|
||||||
erase(room.x, room.y, room.radius);
|
erase(room.x, room.y, room.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
int connections = rand.random(Math.max(rooms - 1, 1), rooms + 3);
|
int connections = rand.random(Math.max(rooms - 1, 1), rooms + 3);
|
||||||
for(int i = 0; i < connections; i++){
|
for(int i = 0; i < connections; i++){
|
||||||
array.random(rand).connect(array.random(rand));
|
roomseq.random(rand).connect(roomseq.random(rand));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Room room : array){
|
for(Room room : roomseq){
|
||||||
spawn.connect(room);
|
spawn.connect(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,10 +252,6 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for(Room espawn : enemies){
|
|
||||||
tiles.getn(espawn.x, espawn.y).setOverlay(Blocks.spawn);
|
|
||||||
}
|
|
||||||
|
|
||||||
trimDark();
|
trimDark();
|
||||||
|
|
||||||
median(2);
|
median(2);
|
||||||
@@ -273,7 +269,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
//tar
|
//tar
|
||||||
if(floor == Blocks.darksand){
|
if(floor == Blocks.darksand){
|
||||||
if(Math.abs(0.5f - noise(x - 40, y, 2, 0.7, 80)) > 0.25f &&
|
if(Math.abs(0.5f - noise(x - 40, y, 2, 0.7, 80)) > 0.25f &&
|
||||||
Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f){
|
Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f && !(roomseq.contains(r -> Mathf.within(x, y, r.x, r.y, 15)))){
|
||||||
floor = Blocks.tar;
|
floor = Blocks.tar;
|
||||||
ore = Blocks.air;
|
ore = Blocks.air;
|
||||||
}
|
}
|
||||||
@@ -298,6 +294,23 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(rand.chance(0.0075)){
|
||||||
|
//random spore trees
|
||||||
|
boolean any = false;
|
||||||
|
boolean all = true;
|
||||||
|
for(Point2 p : Geometry.d4){
|
||||||
|
Tile other = tiles.get(x + p.x, y + p.y);
|
||||||
|
if(other != null && other.block() == Blocks.air){
|
||||||
|
any = true;
|
||||||
|
}else{
|
||||||
|
all = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(any && ((block == Blocks.snowWall || block == Blocks.iceWall) || (all && block == Blocks.air && floor == Blocks.snow && rand.chance(0.03)))){
|
||||||
|
block = rand.chance(0.5) ? Blocks.whiteTree : Blocks.whiteTreeDead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//random stuff
|
//random stuff
|
||||||
dec: {
|
dec: {
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
@@ -392,6 +405,10 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
|
|
||||||
Schematics.placeLaunchLoadout(spawn.x, spawn.y);
|
Schematics.placeLaunchLoadout(spawn.x, spawn.y);
|
||||||
|
|
||||||
|
for(Room espawn : enemies){
|
||||||
|
tiles.getn(espawn.x, espawn.y).setOverlay(Blocks.spawn);
|
||||||
|
}
|
||||||
|
|
||||||
if(sector.hasEnemyBase()){
|
if(sector.hasEnemyBase()){
|
||||||
basegen.generate(tiles, enemies.map(r -> tiles.getn(r.x, r.y)), tiles.get(spawn.x, spawn.y), state.rules.waveTeam, sector, difficulty);
|
basegen.generate(tiles, enemies.map(r -> tiles.getn(r.x, r.y)), tiles.get(spawn.x, spawn.y), state.rules.waveTeam, sector, difficulty);
|
||||||
|
|
||||||
|
|||||||
@@ -603,7 +603,7 @@ public class ContentParser{
|
|||||||
customRequirements = null;
|
customRequirements = null;
|
||||||
}else{
|
}else{
|
||||||
researchName = research.getString("parent");
|
researchName = research.getString("parent");
|
||||||
customRequirements = research.hasChild("requirements") ? parser.readValue(ItemStack[].class, research.getChild("requirements")) : null;
|
customRequirements = research.has("requirements") ? parser.readValue(ItemStack[].class, research.get("requirements")) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove old node
|
//remove old node
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import arc.util.*;
|
|||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
import mindustry.graphics.g3d.PlanetGrid.*;
|
import mindustry.graphics.g3d.PlanetGrid.*;
|
||||||
|
import mindustry.world.modules.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -143,9 +144,17 @@ public class Sector{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeItem(Item item, int amount){
|
public void removeItem(Item item, int amount){
|
||||||
|
ItemSeq seq = new ItemSeq();
|
||||||
|
seq.add(item, -amount);
|
||||||
|
addItems(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItems(ItemSeq items){
|
||||||
if(isBeingPlayed()){
|
if(isBeingPlayed()){
|
||||||
if(state.rules.defaultTeam.core() != null){
|
if(state.rules.defaultTeam.core() != null){
|
||||||
state.rules.defaultTeam.items().remove(item, amount);
|
ItemModule storage = state.rules.defaultTeam.items();
|
||||||
|
int cap = state.rules.defaultTeam.core().storageCapacity;
|
||||||
|
items.each((item, amount) -> storage.add(item, Math.min(cap - storage.get(item), amount)));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ItemSeq recv = getExtraItems();
|
ItemSeq recv = getExtraItems();
|
||||||
@@ -170,7 +179,7 @@ public class Sector{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
recv.remove(item, amount);
|
recv.add(items);
|
||||||
|
|
||||||
setExtraItems(recv);
|
setExtraItems(recv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import mindustry.gen.*;
|
|||||||
public class StatusEffect extends MappableContent{
|
public class StatusEffect extends MappableContent{
|
||||||
/** Damage dealt by the unit with the effect. */
|
/** Damage dealt by the unit with the effect. */
|
||||||
public float damageMultiplier = 1f;
|
public float damageMultiplier = 1f;
|
||||||
/** Unit armor multiplier. */
|
/** Unit health multiplier. */
|
||||||
public float armorMultiplier = 1f;
|
public float healthMultiplier = 1f;
|
||||||
/** Unit speed multiplier */
|
/** Unit speed multiplier */
|
||||||
public float speedMultiplier = 1f;
|
public float speedMultiplier = 1f;
|
||||||
/** Unit speed multiplier */
|
/** Unit speed multiplier */
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import static arc.util.Time.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class CustomRulesDialog extends BaseDialog{
|
public class CustomRulesDialog extends BaseDialog{
|
||||||
private Table main;
|
|
||||||
Rules rules;
|
Rules rules;
|
||||||
|
private Table main;
|
||||||
private Prov<Rules> resetter;
|
private Prov<Rules> resetter;
|
||||||
private LoadoutDialog loadoutDialog;
|
private LoadoutDialog loadoutDialog;
|
||||||
private BaseDialog banDialog;
|
private BaseDialog banDialog;
|
||||||
@@ -166,7 +166,7 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
|
|
||||||
title("@rules.title.enemy");
|
title("@rules.title.enemy");
|
||||||
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
||||||
check("@rules.buildai", b -> rules.waveTeam.rules().ai = b, () -> rules.waveTeam.rules().ai);
|
check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai);
|
||||||
number("@rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200));
|
number("@rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200));
|
||||||
|
|
||||||
title("@rules.title.environment");
|
title("@rules.title.environment");
|
||||||
|
|||||||
@@ -35,17 +35,18 @@ public class PausedDialog extends BaseDialog{
|
|||||||
|
|
||||||
if(!mobile){
|
if(!mobile){
|
||||||
//TODO localize
|
//TODO localize
|
||||||
cont.label(() -> state.getSector() == null ? "" :
|
//TODO capturing is disabled, remove?
|
||||||
("[lightgray]Next turn in [accent]" + state.getSector().displayTimeRemaining() +
|
//cont.label(() -> state.getSector() == null ? "" :
|
||||||
(state.rules.winWave > 0 && !state.getSector().isCaptured() ? "\n[lightgray]Reach wave[accent] " + state.rules.winWave + "[] to capture" : "")))
|
//("[lightgray]Next turn in [accent]" + state.getSector().displayTimeRemaining() +
|
||||||
.visible(() -> state.getSector() != null).colspan(2);
|
// (state.rules.winWave > 0 && !state.getSector().isCaptured() ? "\n[lightgray]Reach wave[accent] " + state.rules.winWave + "[] to capture" : "")))
|
||||||
|
// .visible(() -> state.getSector() != null).colspan(2);
|
||||||
cont.row();
|
cont.row();
|
||||||
|
|
||||||
float dw = 220f;
|
float dw = 220f;
|
||||||
cont.defaults().width(dw).height(55).pad(5f);
|
cont.defaults().width(dw).height(55).pad(5f);
|
||||||
|
|
||||||
cont.button("@back", Icon.left, this::hide);
|
cont.button("@back", Icon.left, this::hide).name("back");
|
||||||
cont.button("@settings", Icon.settings, ui.settings::show);
|
cont.button("@settings", Icon.settings, ui.settings::show).name("settings");
|
||||||
|
|
||||||
if(!state.rules.tutorial){
|
if(!state.rules.tutorial){
|
||||||
if(!state.isCampaign() && !state.isEditor()){
|
if(!state.isCampaign() && !state.isEditor()){
|
||||||
|
|||||||
@@ -32,18 +32,18 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
//if true, enables launching anywhere for testing
|
//if true, enables launching anywhere for testing
|
||||||
public static boolean debugSelect = false;
|
public static boolean debugSelect = false;
|
||||||
|
|
||||||
final FrameBuffer buffer = new FrameBuffer(2, 2, true);
|
public final FrameBuffer buffer = new FrameBuffer(2, 2, true);
|
||||||
final PlanetRenderer planets = renderer.planets;
|
public final PlanetRenderer planets = renderer.planets;
|
||||||
final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
|
public final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
|
||||||
final Table stable = new Table().background(Styles.black3);
|
public final Table stable = new Table().background(Styles.black3);
|
||||||
|
|
||||||
int launchRange;
|
public int launchRange;
|
||||||
float zoom = 1f, selectAlpha = 1f;
|
public float zoom = 1f, selectAlpha = 1f;
|
||||||
@Nullable Sector selected, hovered, launchSector;
|
public @Nullable Sector selected, hovered, launchSector;
|
||||||
CoreBuild launcher;
|
public CoreBuild launcher;
|
||||||
Mode mode = look;
|
public Mode mode = look;
|
||||||
boolean launching;
|
public boolean launching;
|
||||||
Cons<Sector> listener = s -> {};
|
public Cons<Sector> listener = s -> {};
|
||||||
|
|
||||||
public PlanetDialog(){
|
public PlanetDialog(){
|
||||||
super("", Styles.fullDialog);
|
super("", Styles.fullDialog);
|
||||||
@@ -237,7 +237,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
cont.clear();
|
cont.clear();
|
||||||
titleTable.remove();
|
titleTable.remove();
|
||||||
|
|
||||||
|
|
||||||
cont.stack(
|
cont.stack(
|
||||||
new Element(){
|
new Element(){
|
||||||
{
|
{
|
||||||
@@ -263,9 +262,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Table(t -> {
|
new Table(t -> {
|
||||||
|
t.touchable = Touchable.disabled;
|
||||||
//TODO localize
|
//TODO localize
|
||||||
t.top();
|
t.top();
|
||||||
t.label(() -> mode == select ? "@sectors.select" : mode == launch ? "Select Launch Sector" : "Turn " + universe.turn()).style(Styles.outlineLabel).color(Pal.accent);
|
t.label(() -> mode == select ? "@sectors.select" : mode == launch ? "Select Launch Sector" : "").style(Styles.outlineLabel).color(Pal.accent);
|
||||||
})).grow();
|
})).grow();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -338,6 +338,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
stable.add("[accent]Difficulty: " + (int)(sector.baseCoverage * 10)).row();
|
stable.add("[accent]Difficulty: " + (int)(sector.baseCoverage * 10)).row();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO sector damage is disabled, remove when finalized
|
||||||
|
/*
|
||||||
if(sector.hasBase() && sector.hasWaves()){
|
if(sector.hasBase() && sector.hasWaves()){
|
||||||
//TODO localize when finalized
|
//TODO localize when finalized
|
||||||
//these mechanics are likely to change and as such are not added to the bundle
|
//these mechanics are likely to change and as such are not added to the bundle
|
||||||
@@ -345,7 +347,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
stable.row();
|
stable.row();
|
||||||
stable.add("[accent]" + Mathf.ceil(sectorDestructionTurns - (sector.getSecondsPassed() * 60) / turnDuration) + " turn(s)\nuntil destruction");
|
stable.add("[accent]" + Mathf.ceil(sectorDestructionTurns - (sector.getSecondsPassed() * 60) / turnDuration) + " turn(s)\nuntil destruction");
|
||||||
stable.row();
|
stable.row();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if(sector.save != null){
|
if(sector.save != null){
|
||||||
stable.add("@sectors.resources").row();
|
stable.add("@sectors.resources").row();
|
||||||
@@ -468,7 +470,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
stable.act(0f);
|
stable.act(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Mode{
|
public enum Mode{
|
||||||
/** Look around for existing sectors. Can only deploy. */
|
/** Look around for existing sectors. Can only deploy. */
|
||||||
look,
|
look,
|
||||||
/** Launch to a new location. */
|
/** Launch to a new location. */
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ import java.util.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class ResearchDialog extends BaseDialog{
|
public class ResearchDialog extends BaseDialog{
|
||||||
final float nodeSize = Scl.scl(60f);
|
public final float nodeSize = Scl.scl(60f);
|
||||||
ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
public ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
||||||
TechTreeNode root = new TechTreeNode(TechTree.root, null);
|
public TechTreeNode root = new TechTreeNode(TechTree.root, null);
|
||||||
Rect bounds = new Rect();
|
public Rect bounds = new Rect();
|
||||||
ItemsDisplay itemDisplay;
|
public ItemsDisplay itemDisplay;
|
||||||
View view;
|
public View view;
|
||||||
|
|
||||||
ItemSeq items;
|
public ItemSeq items;
|
||||||
|
|
||||||
public ResearchDialog(){
|
public ResearchDialog(){
|
||||||
super("");
|
super("");
|
||||||
@@ -114,7 +114,7 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
buttons.button("@database", Icon.book, () -> {
|
buttons.button("@database", Icon.book, () -> {
|
||||||
hide();
|
hide();
|
||||||
ui.database.show();
|
ui.database.show();
|
||||||
}).size(210f, 64f);
|
}).size(210f, 64f).name("database");
|
||||||
|
|
||||||
//scaling/drag input
|
//scaling/drag input
|
||||||
addListener(new InputListener(){
|
addListener(new InputListener(){
|
||||||
@@ -250,7 +250,7 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
return node.content.unlocked() || !node.objectives.contains(i -> !i.complete());
|
return node.content.unlocked() || !node.objectives.contains(i -> !i.complete());
|
||||||
}
|
}
|
||||||
|
|
||||||
void showToast(String info){
|
public void showToast(String info){
|
||||||
Table table = new Table();
|
Table table = new Table();
|
||||||
table.actions(Actions.fadeOut(0.5f, Interp.fade), Actions.remove());
|
table.actions(Actions.fadeOut(0.5f, Interp.fade), Actions.remove());
|
||||||
table.top().add(info);
|
table.top().add(info);
|
||||||
@@ -279,11 +279,11 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TechTreeNode extends TreeNode<TechTreeNode>{
|
public class TechTreeNode extends TreeNode<TechTreeNode>{
|
||||||
final TechNode node;
|
public final TechNode node;
|
||||||
boolean visible = true, selectable = true;
|
public boolean visible = true, selectable = true;
|
||||||
|
|
||||||
TechTreeNode(TechNode node, TechTreeNode parent){
|
public TechTreeNode(TechNode node, TechTreeNode parent){
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.width = this.height = nodeSize;
|
this.width = this.height = nodeSize;
|
||||||
@@ -297,11 +297,11 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class View extends Group{
|
public class View extends Group{
|
||||||
float panX = 0, panY = -200, lastZoom = -1;
|
public float panX = 0, panY = -200, lastZoom = -1;
|
||||||
boolean moved = false;
|
public boolean moved = false;
|
||||||
ImageButton hoverNode;
|
public ImageButton hoverNode;
|
||||||
Table infoTable = new Table();
|
public Table infoTable = new Table();
|
||||||
|
|
||||||
{
|
{
|
||||||
infoTable.touchable = Touchable.enabled;
|
infoTable.touchable = Touchable.enabled;
|
||||||
@@ -400,7 +400,8 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
//can always spend when locked
|
||||||
|
return node.content.locked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void spend(TechNode node){
|
void spend(TechNode node){
|
||||||
@@ -414,7 +415,7 @@ public class ResearchDialog extends BaseDialog{
|
|||||||
ItemStack completed = node.finishedRequirements[i];
|
ItemStack completed = node.finishedRequirements[i];
|
||||||
|
|
||||||
//amount actually taken from inventory
|
//amount actually taken from inventory
|
||||||
int used = Math.min(req.amount - completed.amount, items.get(req.item));
|
int used = Math.max(Math.min(req.amount - completed.amount, items.get(req.item)), 0);
|
||||||
items.remove(req.item, used);
|
items.remove(req.item, used);
|
||||||
completed.amount += used;
|
completed.amount += used;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import arc.*;
|
|||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.Texture.*;
|
import arc.graphics.Texture.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.input.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
@@ -106,18 +107,36 @@ public class SchematicsDialog extends BaseDialog{
|
|||||||
});
|
});
|
||||||
|
|
||||||
buttons.button(Icon.pencil, style, () -> {
|
buttons.button(Icon.pencil, style, () -> {
|
||||||
ui.showTextInput("@schematic.rename", "@name", s.name(), res -> {
|
new Dialog("@schematic.rename"){{
|
||||||
Schematic replacement = schematics.all().find(other -> other.name().equals(res) && other != s);
|
cont.margin(30).add("@name").padRight(6f);
|
||||||
if(replacement != null){
|
TextField nameField = cont.field(s.name(), null).size(400f, 55f).addInputDialog().get();
|
||||||
//renaming to an existing schematic is not allowed, as it is not clear how the tags would be merged, and which one should be removed
|
|
||||||
ui.showErrorMessage("@schematic.exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s.tags.put("name", res);
|
cont.row();
|
||||||
s.save();
|
|
||||||
rebuildPane[0].run();
|
cont.margin(30).add("@editor.description").padRight(6f);
|
||||||
});
|
TextField descripionField = cont.area(s.description(), Styles.areaField, t -> {}).size(400f, 140f).addInputDialog().get();
|
||||||
|
|
||||||
|
Runnable accept = () -> {
|
||||||
|
s.tags.put("name", nameField.getText());
|
||||||
|
s.tags.put("description", descripionField.getText());
|
||||||
|
s.save();
|
||||||
|
hide();
|
||||||
|
rebuildPane[0].run();
|
||||||
|
};
|
||||||
|
|
||||||
|
buttons.defaults().size(120, 54).pad(4);
|
||||||
|
buttons.button("@ok", accept).disabled(b -> nameField.getText().isEmpty());
|
||||||
|
buttons.button("@cancel", this::hide);
|
||||||
|
|
||||||
|
keyDown(KeyCode.enter, () -> {
|
||||||
|
if(!nameField.getText().isEmpty() && Core.scene.getKeyboardFocus() != descripionField){
|
||||||
|
accept.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
keyDown(KeyCode.escape, this::hide);
|
||||||
|
keyDown(KeyCode.back, this::hide);
|
||||||
|
show();
|
||||||
|
}};
|
||||||
});
|
});
|
||||||
|
|
||||||
if(s.hasSteamID()){
|
if(s.hasSteamID()){
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import arc.scene.ui.layout.*;
|
|||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
@@ -47,6 +48,26 @@ public class HudFragment extends Fragment{
|
|||||||
@Override
|
@Override
|
||||||
public void build(Group parent){
|
public void build(Group parent){
|
||||||
|
|
||||||
|
//warn about guardian/boss waves
|
||||||
|
Events.on(WaveEvent.class, e -> {
|
||||||
|
int max = 10;
|
||||||
|
outer:
|
||||||
|
for(int i = state.wave - 1; i <= state.wave + max; i++){
|
||||||
|
for(SpawnGroup group : state.rules.spawns){
|
||||||
|
if(group.effect == StatusEffects.boss && group.getUnitsSpawned(i) > 0){
|
||||||
|
int diff = (i + 2) - state.wave;
|
||||||
|
|
||||||
|
//increments at which to warn about incoming guardian
|
||||||
|
if(diff == 1 || diff == 2 || diff == 5 || diff == 10){
|
||||||
|
showToast(Icon.warning, Core.bundle.format("wave.guardianwarn" + (diff == 1 ? ".one" : ""), diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//TODO details and stuff
|
//TODO details and stuff
|
||||||
Events.on(SectorCaptureEvent.class, e ->{
|
Events.on(SectorCaptureEvent.class, e ->{
|
||||||
//TODO localize
|
//TODO localize
|
||||||
@@ -63,36 +84,25 @@ public class HudFragment extends Fragment{
|
|||||||
coreItems.clear();
|
coreItems.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(TurnEvent.class, e -> {
|
|
||||||
Seq<Sector> attacked = universe.getAttacked(state.getSector().planet);
|
|
||||||
|
|
||||||
if(attacked.any()){
|
|
||||||
|
|
||||||
//TODO localize
|
|
||||||
String text = attacked.size > 1 ? attacked.size + " sectors attacked." : "Sector " + attacked.first().id + " under attack.";
|
|
||||||
|
|
||||||
showToast(Icon.warning, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
//ui.announce("[accent][[ Turn " + universe.turn() + " ]\n[scarlet]" + attackedSectors.size + "[lightgray] sector(s) attacked.");
|
|
||||||
});
|
|
||||||
|
|
||||||
//paused table
|
//paused table
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "paused";
|
||||||
t.top().visible(() -> state.isPaused()).touchable = Touchable.disabled;
|
t.top().visible(() -> state.isPaused()).touchable = Touchable.disabled;
|
||||||
t.table(Styles.black5, top -> top.add("@paused").style(Styles.outlineLabel).pad(8f)).growX();
|
t.table(Styles.black5, top -> top.add("@paused").style(Styles.outlineLabel).pad(8f)).growX();
|
||||||
});
|
});
|
||||||
|
|
||||||
//minimap + position
|
//minimap + position
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "minimap/position";
|
||||||
t.visible(() -> Core.settings.getBool("minimap") && !state.rules.tutorial && shown);
|
t.visible(() -> Core.settings.getBool("minimap") && !state.rules.tutorial && shown);
|
||||||
//minimap
|
//minimap
|
||||||
t.add(new Minimap());
|
t.add(new Minimap()).name("minimap");
|
||||||
t.row();
|
t.row();
|
||||||
//position
|
//position
|
||||||
t.label(() -> player.tileX() + "," + player.tileY())
|
t.label(() -> player.tileX() + "," + player.tileY())
|
||||||
.visible(() -> Core.settings.getBool("position") && !state.rules.tutorial)
|
.visible(() -> Core.settings.getBool("position") && !state.rules.tutorial)
|
||||||
.touchable(Touchable.disabled);
|
.touchable(Touchable.disabled)
|
||||||
|
.name("position");
|
||||||
t.top().right();
|
t.top().right();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -104,15 +114,18 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
if(mobile){
|
if(mobile){
|
||||||
cont.table(select -> {
|
cont.table(select -> {
|
||||||
|
select.name = "mobile buttons";
|
||||||
select.left();
|
select.left();
|
||||||
select.defaults().size(dsize).left();
|
select.defaults().size(dsize).left();
|
||||||
|
|
||||||
ImageButtonStyle style = Styles.clearTransi;
|
ImageButtonStyle style = Styles.clearTransi;
|
||||||
|
|
||||||
select.button(Icon.menu, style, ui.paused::show);
|
select.button(Icon.menu, style, ui.paused::show).name("menu");
|
||||||
flip = select.button(Icon.upOpen, style, this::toggleMenus).get();
|
flip = select.button(Icon.upOpen, style, this::toggleMenus).get();
|
||||||
|
flip.name = "flip";
|
||||||
|
|
||||||
select.button(Icon.paste, style, ui.schematics::show);
|
select.button(Icon.paste, style, ui.schematics::show)
|
||||||
|
.name("schematics");
|
||||||
|
|
||||||
select.button(Icon.pause, style, () -> {
|
select.button(Icon.pause, style, () -> {
|
||||||
if(net.active()){
|
if(net.active()){
|
||||||
@@ -141,7 +154,7 @@ public class HudFragment extends Fragment{
|
|||||||
}else{
|
}else{
|
||||||
ui.database.show();
|
ui.database.show();
|
||||||
}
|
}
|
||||||
}).update(i -> {
|
}).name("chat").update(i -> {
|
||||||
if(net.active() && mobile){
|
if(net.active() && mobile){
|
||||||
i.getStyle().imageUp = Icon.chat;
|
i.getStyle().imageUp = Icon.chat;
|
||||||
}else if(state.isCampaign()){
|
}else if(state.isCampaign()){
|
||||||
@@ -167,14 +180,15 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
Table wavesMain, editorMain;
|
Table wavesMain, editorMain;
|
||||||
|
|
||||||
cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight());
|
cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight())
|
||||||
|
.name("waves/editor");
|
||||||
|
|
||||||
wavesMain.visible(() -> shown && !state.isEditor());
|
wavesMain.visible(() -> shown && !state.isEditor());
|
||||||
wavesMain.top().left();
|
wavesMain.top().left().name = "waves";
|
||||||
|
|
||||||
wavesMain.table(s -> {
|
wavesMain.table(s -> {
|
||||||
//wave info button with text
|
//wave info button with text
|
||||||
s.add(makeStatusTable()).grow();
|
s.add(makeStatusTable()).grow().name("status");
|
||||||
|
|
||||||
//table with button to skip wave
|
//table with button to skip wave
|
||||||
s.button(Icon.play, Styles.righti, 30f, () -> {
|
s.button(Icon.play, Styles.righti, 30f, () -> {
|
||||||
@@ -183,18 +197,22 @@ public class HudFragment extends Fragment{
|
|||||||
}else{
|
}else{
|
||||||
logic.skipWave();
|
logic.skipWave();
|
||||||
}
|
}
|
||||||
}).growY().fillX().right().width(40f).disabled(b -> !canSkipWave()).visible(() -> state.rules.waves);
|
}).growY().fillX().right().width(40f).disabled(b -> !canSkipWave())
|
||||||
|
.visible(() -> state.rules.waves).name("skip");
|
||||||
}).width(dsize * 5 + 4f);
|
}).width(dsize * 5 + 4f);
|
||||||
|
|
||||||
wavesMain.row();
|
wavesMain.row();
|
||||||
|
|
||||||
wavesMain.table(Tex.button, t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.white))
|
wavesMain.table(Tex.button, t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.white))
|
||||||
.grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get();
|
.grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get()
|
||||||
|
.name = "boss";
|
||||||
|
|
||||||
wavesMain.row();
|
wavesMain.row();
|
||||||
|
|
||||||
|
editorMain.name = "editor";
|
||||||
editorMain.table(Tex.buttonEdge4, t -> {
|
editorMain.table(Tex.buttonEdge4, t -> {
|
||||||
//t.margin(0f);
|
//t.margin(0f);
|
||||||
|
t.name = "teams";
|
||||||
t.add("@editor.teams").growX().left();
|
t.add("@editor.teams").growX().left();
|
||||||
t.row();
|
t.row();
|
||||||
t.table(teams -> {
|
t.table(teams -> {
|
||||||
@@ -215,29 +233,33 @@ public class HudFragment extends Fragment{
|
|||||||
}).width(dsize * 5 + 4f);
|
}).width(dsize * 5 + 4f);
|
||||||
editorMain.visible(() -> shown && state.isEditor());
|
editorMain.visible(() -> shown && state.isEditor());
|
||||||
|
|
||||||
|
|
||||||
//fps display
|
//fps display
|
||||||
cont.table(info -> {
|
cont.table(info -> {
|
||||||
|
info.name = "fps/ping";
|
||||||
info.touchable = Touchable.disabled;
|
info.touchable = Touchable.disabled;
|
||||||
info.top().left().margin(4).visible(() -> Core.settings.getBool("fps") && shown);
|
info.top().left().margin(4).visible(() -> Core.settings.getBool("fps") && shown);
|
||||||
info.update(() -> info.setTranslation(state.rules.waves || state.isEditor() ? 0f : -Scl.scl(dsize * 4 + 3), 0));
|
info.update(() -> info.setTranslation(state.rules.waves || state.isEditor() ? 0f : -Scl.scl(dsize * 4 + 3), 0));
|
||||||
IntFormat fps = new IntFormat("fps");
|
IntFormat fps = new IntFormat("fps");
|
||||||
IntFormat ping = new IntFormat("ping");
|
IntFormat ping = new IntFormat("ping");
|
||||||
|
|
||||||
info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left().style(Styles.outlineLabel);
|
info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left()
|
||||||
|
.style(Styles.outlineLabel).name("fps");
|
||||||
info.row();
|
info.row();
|
||||||
info.label(() -> ping.get(netClient.getPing())).visible(net::client).left().style(Styles.outlineLabel);
|
info.label(() -> ping.get(netClient.getPing())).visible(net::client).left()
|
||||||
|
.style(Styles.outlineLabel).name("ping");
|
||||||
}).top().left();
|
}).top().left();
|
||||||
});
|
});
|
||||||
|
|
||||||
//core items
|
//core items
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "coreitems";
|
||||||
t.top().add(coreItems);
|
t.top().add(coreItems);
|
||||||
t.visible(() -> Core.settings.getBool("coreitems") && !mobile && !state.isPaused() && shown);
|
t.visible(() -> Core.settings.getBool("coreitems") && !mobile && !state.isPaused() && shown);
|
||||||
});
|
});
|
||||||
|
|
||||||
//spawner warning
|
//spawner warning
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "nearpoint";
|
||||||
t.touchable = Touchable.disabled;
|
t.touchable = Touchable.disabled;
|
||||||
t.table(Styles.black, c -> c.add("@nearpoint")
|
t.table(Styles.black, c -> c.add("@nearpoint")
|
||||||
.update(l -> l.setColor(Tmp.c1.set(Color.white).lerp(Color.scarlet, Mathf.absin(Time.time(), 10f, 1f))))
|
.update(l -> l.setColor(Tmp.c1.set(Color.white).lerp(Color.scarlet, Mathf.absin(Time.time(), 10f, 1f))))
|
||||||
@@ -246,12 +268,14 @@ public class HudFragment extends Fragment{
|
|||||||
});
|
});
|
||||||
|
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "waiting";
|
||||||
t.visible(() -> netServer.isWaitingForPlayers());
|
t.visible(() -> netServer.isWaitingForPlayers());
|
||||||
t.table(Tex.button, c -> c.add("@waiting.players"));
|
t.table(Tex.button, c -> c.add("@waiting.players"));
|
||||||
});
|
});
|
||||||
|
|
||||||
//'core is under attack' table
|
//'core is under attack' table
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "coreattack";
|
||||||
t.touchable = Touchable.disabled;
|
t.touchable = Touchable.disabled;
|
||||||
float notifDuration = 240f;
|
float notifDuration = 240f;
|
||||||
float[] coreAttackTime = {0};
|
float[] coreAttackTime = {0};
|
||||||
@@ -285,6 +309,7 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
//tutorial text
|
//tutorial text
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "tutorial";
|
||||||
Runnable resize = () -> {
|
Runnable resize = () -> {
|
||||||
t.clearChildren();
|
t.clearChildren();
|
||||||
t.top().right().visible(() -> state.rules.tutorial);
|
t.top().right().visible(() -> state.rules.tutorial);
|
||||||
@@ -307,11 +332,13 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
//'saving' indicator
|
//'saving' indicator
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "saving";
|
||||||
t.bottom().visible(() -> control.saves.isSaving());
|
t.bottom().visible(() -> control.saves.isSaving());
|
||||||
t.add("@saving").style(Styles.outlineLabel);
|
t.add("@saving").style(Styles.outlineLabel);
|
||||||
});
|
});
|
||||||
|
|
||||||
parent.fill(p -> {
|
parent.fill(p -> {
|
||||||
|
p.name = "hudtext";
|
||||||
p.top().table(Styles.black3, t -> t.margin(4).label(() -> hudText)
|
p.top().table(Styles.black3, t -> t.margin(4).label(() -> hudText)
|
||||||
.style(Styles.outlineLabel)).padTop(10).visible(p.color.a >= 0.001f);
|
.style(Styles.outlineLabel)).padTop(10).visible(p.color.a >= 0.001f);
|
||||||
p.update(() -> {
|
p.update(() -> {
|
||||||
@@ -327,6 +354,7 @@ public class HudFragment extends Fragment{
|
|||||||
//TODO DEBUG: rate table
|
//TODO DEBUG: rate table
|
||||||
if(false)
|
if(false)
|
||||||
parent.fill(t -> {
|
parent.fill(t -> {
|
||||||
|
t.name = "rates";
|
||||||
t.bottom().left();
|
t.bottom().left();
|
||||||
t.table(Styles.black6, c -> {
|
t.table(Styles.black6, c -> {
|
||||||
Bits used = new Bits(content.items().size);
|
Bits used = new Bits(content.items().size);
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class MenuFragment extends Fragment{
|
|||||||
|
|
||||||
parent.fill(c -> {
|
parent.fill(c -> {
|
||||||
container = c;
|
container = c;
|
||||||
|
c.name = "menu container";
|
||||||
|
|
||||||
if(!mobile){
|
if(!mobile){
|
||||||
buildDesktop();
|
buildDesktop();
|
||||||
@@ -57,8 +58,8 @@ public class MenuFragment extends Fragment{
|
|||||||
|
|
||||||
//info icon
|
//info icon
|
||||||
if(mobile){
|
if(mobile){
|
||||||
parent.fill(c -> c.bottom().left().button("", Styles.infot, ui.about::show).size(84, 45));
|
parent.fill(c -> c.bottom().left().button("", Styles.infot, ui.about::show).size(84, 45).name("info"));
|
||||||
parent.fill(c -> c.bottom().right().button("", Styles.discordt, ui.discord::show).size(84, 45));
|
parent.fill(c -> c.bottom().right().button("", Styles.discordt, ui.discord::show).size(84, 45).name("discord"));
|
||||||
}else if(becontrol.active()){
|
}else if(becontrol.active()){
|
||||||
parent.fill(c -> c.bottom().right().button("@be.check", Icon.refresh, () -> {
|
parent.fill(c -> c.bottom().right().button("@be.check", Icon.refresh, () -> {
|
||||||
ui.loadfrag.show();
|
ui.loadfrag.show();
|
||||||
@@ -68,7 +69,7 @@ public class MenuFragment extends Fragment{
|
|||||||
ui.showInfo("@be.noupdates");
|
ui.showInfo("@be.noupdates");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).size(200, 60).update(t -> {
|
}).size(200, 60).name("becheck").update(t -> {
|
||||||
t.getLabel().setColor(becontrol.isUpdateAvailable() ? Tmp.c1.set(Color.white).lerp(Pal.accent, Mathf.absin(5f, 1f)) : Color.white);
|
t.getLabel().setColor(becontrol.isUpdateAvailable() ? Tmp.c1.set(Color.white).lerp(Pal.accent, Mathf.absin(5f, 1f)) : Color.white);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -93,6 +94,7 @@ public class MenuFragment extends Fragment{
|
|||||||
|
|
||||||
private void buildMobile(){
|
private void buildMobile(){
|
||||||
container.clear();
|
container.clear();
|
||||||
|
container.name = "buttons";
|
||||||
container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
||||||
|
|
||||||
float size = 120f;
|
float size = 120f;
|
||||||
@@ -153,7 +155,6 @@ public class MenuFragment extends Fragment{
|
|||||||
container.clear();
|
container.clear();
|
||||||
container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
||||||
|
|
||||||
|
|
||||||
float width = 230f;
|
float width = 230f;
|
||||||
Drawable background = Styles.black6;
|
Drawable background = Styles.black6;
|
||||||
|
|
||||||
@@ -161,6 +162,7 @@ public class MenuFragment extends Fragment{
|
|||||||
container.add().width(Core.graphics.getWidth()/10f);
|
container.add().width(Core.graphics.getWidth()/10f);
|
||||||
container.table(background, t -> {
|
container.table(background, t -> {
|
||||||
t.defaults().width(width).height(70f);
|
t.defaults().width(width).height(70f);
|
||||||
|
t.name = "buttons";
|
||||||
|
|
||||||
buttons(t,
|
buttons(t,
|
||||||
new Buttoni("@play", Icon.play,
|
new Buttoni("@play", Icon.play,
|
||||||
@@ -183,6 +185,7 @@ public class MenuFragment extends Fragment{
|
|||||||
|
|
||||||
container.table(background, t -> {
|
container.table(background, t -> {
|
||||||
submenu = t;
|
submenu = t;
|
||||||
|
t.name = "submenu";
|
||||||
t.color.a = 0f;
|
t.color.a = 0f;
|
||||||
t.top();
|
t.top();
|
||||||
t.defaults().width(width).height(70f);
|
t.defaults().width(width).height(70f);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class MinimapFragment extends Fragment{
|
|||||||
private boolean shown;
|
private boolean shown;
|
||||||
float panx, pany, zoom = 1f, lastZoom = -1;
|
float panx, pany, zoom = 1f, lastZoom = -1;
|
||||||
private float baseSize = Scl.scl(5f);
|
private float baseSize = Scl.scl(5f);
|
||||||
private Element elem;
|
public Element elem;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(Group parent){
|
public void build(Group parent){
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ public class PlayerListFragment extends Fragment{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(Group parent){
|
public void build(Group parent){
|
||||||
|
content.name = "players";
|
||||||
parent.fill(cont -> {
|
parent.fill(cont -> {
|
||||||
|
cont.name = "playerlist";
|
||||||
cont.visible(() -> visible);
|
cont.visible(() -> visible);
|
||||||
cont.update(() -> {
|
cont.update(() -> {
|
||||||
if(!(net.active() && state.isGame())){
|
if(!(net.active() && state.isGame())){
|
||||||
@@ -47,6 +49,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
sField = pane.field(null, text -> {
|
sField = pane.field(null, text -> {
|
||||||
rebuild();
|
rebuild();
|
||||||
}).grow().pad(8).get();
|
}).grow().pad(8).get();
|
||||||
|
sField.name = "search";
|
||||||
sField.setMaxLength(maxNameLength);
|
sField.setMaxLength(maxNameLength);
|
||||||
sField.setMessageText(Core.bundle.format("players.search"));
|
sField.setMessageText(Core.bundle.format("players.search"));
|
||||||
|
|
||||||
@@ -56,6 +59,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
|
|
||||||
pane.table(menu -> {
|
pane.table(menu -> {
|
||||||
menu.defaults().growX().height(50f).fillY();
|
menu.defaults().growX().height(50f).fillY();
|
||||||
|
menu.name = "menu";
|
||||||
|
|
||||||
menu.button("@server.bans", ui.bans::show).disabled(b -> net.client());
|
menu.button("@server.bans", ui.bans::show).disabled(b -> net.client());
|
||||||
menu.button("@server.admins", ui.admins::show).disabled(b -> net.client());
|
menu.button("@server.admins", ui.admins::show).disabled(b -> net.client());
|
||||||
@@ -99,6 +103,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
};
|
};
|
||||||
table.margin(8);
|
table.margin(8);
|
||||||
table.add(new Image(user.icon()).setScaling(Scaling.bounded)).grow();
|
table.add(new Image(user.icon()).setScaling(Scaling.bounded)).grow();
|
||||||
|
table.name = user.name();
|
||||||
|
|
||||||
button.add(table).size(h);
|
button.add(table).size(h);
|
||||||
button.labelWrap("[#" + user.color().toString().toUpperCase() + "]" + user.name()).width(170f).pad(10);
|
button.labelWrap("[#" + user.color().toString().toUpperCase() + "]" + user.name()).width(170f).pad(10);
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ public class ScriptConsoleFragment extends Table{
|
|||||||
};
|
};
|
||||||
|
|
||||||
public ScriptConsoleFragment(){
|
public ScriptConsoleFragment(){
|
||||||
|
|
||||||
setFillParent(true);
|
setFillParent(true);
|
||||||
font = Fonts.def;
|
font = Fonts.def;
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,8 @@ public class Block extends UnlockableContent{
|
|||||||
public BuildPlaceability buildPlaceability = BuildPlaceability.always;
|
public BuildPlaceability buildPlaceability = BuildPlaceability.always;
|
||||||
/** Multiplier for speed of building this block. */
|
/** Multiplier for speed of building this block. */
|
||||||
public float buildCostMultiplier = 1f;
|
public float buildCostMultiplier = 1f;
|
||||||
|
/** Multiplier for cost of research in tech tree. */
|
||||||
|
public float researchCostMultiplier = 1;
|
||||||
/** Whether this block has instant transfer.*/
|
/** Whether this block has instant transfer.*/
|
||||||
public boolean instantTransfer = false;
|
public boolean instantTransfer = false;
|
||||||
/** Whether you can rotate this block with Keybind rotateplaced + Scroll Wheel. */
|
/** Whether you can rotate this block with Keybind rotateplaced + Scroll Wheel. */
|
||||||
@@ -619,7 +621,7 @@ public class Block extends UnlockableContent{
|
|||||||
public ItemStack[] researchRequirements(){
|
public ItemStack[] researchRequirements(){
|
||||||
ItemStack[] out = new ItemStack[requirements.length];
|
ItemStack[] out = new ItemStack[requirements.length];
|
||||||
for(int i = 0; i < out.length; i++){
|
for(int i = 0; i < out.length; i++){
|
||||||
int quantity = 40 + Mathf.round(Mathf.pow(requirements[i].amount, 1.25f) * 20, 10);
|
int quantity = 40 + Mathf.round(Mathf.pow(requirements[i].amount, 1.25f) * 20 * researchCostMultiplier, 10);
|
||||||
|
|
||||||
out[i] = new ItemStack(requirements[i].item, UI.roundAmount(quantity));
|
out[i] = new ItemStack(requirements[i].item, UI.roundAmount(quantity));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class ConstructBlock extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server)
|
@Remote(called = Loc.server)
|
||||||
public static void constructFinish(Tile tile, Block block, Unit builder, byte rotation, Team team, Object config){
|
public static void constructFinish(Tile tile, Block block, @Nullable Unit builder, byte rotation, Team team, Object config){
|
||||||
if(tile == null) return;
|
if(tile == null) return;
|
||||||
|
|
||||||
float healthf = tile.build == null ? 1f : tile.build.healthf();
|
float healthf = tile.build == null ? 1f : tile.build.healthf();
|
||||||
@@ -76,6 +76,10 @@ public class ConstructBlock extends Block{
|
|||||||
if(prev != null && prev.size > 0){
|
if(prev != null && prev.size > 0){
|
||||||
tile.build.overwrote(prev);
|
tile.build.overwrote(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(builder != null && builder.isPlayer()){
|
||||||
|
tile.build.lastAccessed = builder.getPlayer().name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//last builder was this local client player, call placed()
|
//last builder was this local client player, call placed()
|
||||||
@@ -142,6 +146,9 @@ public class ConstructBlock extends Block{
|
|||||||
public Block previous;
|
public Block previous;
|
||||||
public Object lastConfig;
|
public Object lastConfig;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Unit lastBuilder;
|
||||||
|
|
||||||
private float[] accumulator;
|
private float[] accumulator;
|
||||||
private float[] totalAccumulator;
|
private float[] totalAccumulator;
|
||||||
|
|
||||||
@@ -214,6 +221,10 @@ public class ConstructBlock extends Block{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(builder.isPlayer()){
|
||||||
|
lastBuilder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
lastConfig = config;
|
lastConfig = config;
|
||||||
|
|
||||||
if(cblock.requirements.length != accumulator.length || totalAccumulator.length != cblock.requirements.length){
|
if(cblock.requirements.length != accumulator.length || totalAccumulator.length != cblock.requirements.length){
|
||||||
@@ -233,13 +244,18 @@ public class ConstructBlock extends Block{
|
|||||||
progress = Mathf.clamp(progress + maxProgress);
|
progress = Mathf.clamp(progress + maxProgress);
|
||||||
|
|
||||||
if(progress >= 1f || state.rules.infiniteResources){
|
if(progress >= 1f || state.rules.infiniteResources){
|
||||||
constructed(tile, cblock, builder, (byte)rotation, builder.team, config);
|
if(lastBuilder == null) lastBuilder = builder;
|
||||||
|
constructed(tile, cblock, lastBuilder, (byte)rotation, builder.team, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deconstruct(Unit builder, @Nullable Building core, float amount){
|
public void deconstruct(Unit builder, @Nullable Building core, float amount){
|
||||||
float deconstructMultiplier = state.rules.deconstructRefundMultiplier;
|
float deconstructMultiplier = state.rules.deconstructRefundMultiplier;
|
||||||
|
|
||||||
|
if(builder.isPlayer()){
|
||||||
|
lastBuilder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
if(cblock != null){
|
if(cblock != null){
|
||||||
ItemStack[] requirements = cblock.requirements;
|
ItemStack[] requirements = cblock.requirements;
|
||||||
if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){
|
if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){
|
||||||
@@ -271,7 +287,8 @@ public class ConstructBlock extends Block{
|
|||||||
progress = Mathf.clamp(progress - amount);
|
progress = Mathf.clamp(progress - amount);
|
||||||
|
|
||||||
if(progress <= 0 || state.rules.infiniteResources){
|
if(progress <= 0 || state.rules.infiniteResources){
|
||||||
Call.deconstructFinish(tile, this.cblock == null ? previous : this.cblock, builder);
|
if(lastBuilder == null) lastBuilder = builder;
|
||||||
|
Call.deconstructFinish(tile, this.cblock == null ? previous : this.cblock, lastBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class Wall extends Block{
|
|||||||
solid = true;
|
solid = true;
|
||||||
destructible = true;
|
destructible = true;
|
||||||
group = BlockGroup.walls;
|
group = BlockGroup.walls;
|
||||||
buildCostMultiplier = 5f;
|
buildCostMultiplier = 6f;
|
||||||
canOverdrive = false;
|
canOverdrive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package mindustry.world.blocks.defense.turrets;
|
package mindustry.world.blocks.defense.turrets;
|
||||||
|
|
||||||
|
import arc.audio.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -14,6 +17,7 @@ public class ChargeTurret extends PowerTurret{
|
|||||||
public float chargeMaxDelay = 10f;
|
public float chargeMaxDelay = 10f;
|
||||||
public Effect chargeEffect = Fx.none;
|
public Effect chargeEffect = Fx.none;
|
||||||
public Effect chargeBeginEffect = Fx.none;
|
public Effect chargeBeginEffect = Fx.none;
|
||||||
|
public Sound chargeSound = Sounds.none;
|
||||||
|
|
||||||
public ChargeTurret(String name){
|
public ChargeTurret(String name){
|
||||||
super(name);
|
super(name);
|
||||||
@@ -28,7 +32,8 @@ public class ChargeTurret extends PowerTurret{
|
|||||||
|
|
||||||
tr.trns(rotation, size * tilesize / 2f);
|
tr.trns(rotation, size * tilesize / 2f);
|
||||||
chargeBeginEffect.at(x + tr.x, y + tr.y, rotation);
|
chargeBeginEffect.at(x + tr.x, y + tr.y, rotation);
|
||||||
|
chargeSound.at(x + tr.x, y + tr.y, 1);
|
||||||
|
|
||||||
for(int i = 0; i < chargeEffects; i++){
|
for(int i = 0; i < chargeEffects; i++){
|
||||||
Time.run(Mathf.random(chargeMaxDelay), () -> {
|
Time.run(Mathf.random(chargeMaxDelay), () -> {
|
||||||
if(!isValid()) return;
|
if(!isValid()) return;
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ public abstract class Turret extends Block{
|
|||||||
|
|
||||||
fshootEffect.at(x + tr.x, y + tr.y, rotation);
|
fshootEffect.at(x + tr.x, y + tr.y, rotation);
|
||||||
fsmokeEffect.at(x + tr.x, y + tr.y, rotation);
|
fsmokeEffect.at(x + tr.x, y + tr.y, rotation);
|
||||||
shootSound.at(tile, Mathf.random(0.9f, 1.1f));
|
shootSound.at(x + tr.x, y + tr.y, Mathf.random(0.9f, 1.1f));
|
||||||
|
|
||||||
if(shootShake > 0){
|
if(shootShake > 0){
|
||||||
Effect.shake(shootShake, shootShake, this);
|
Effect.shake(shootShake, shootShake, this);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package mindustry.world.blocks.logic;
|
package mindustry.world.blocks.logic;
|
||||||
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.graphics.g2d.*;
|
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.Bits;
|
import arc.struct.Bits;
|
||||||
@@ -9,7 +8,6 @@ import arc.struct.*;
|
|||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.ai.types.*;
|
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
@@ -425,7 +423,6 @@ public class LogicBlock extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildConfiguration(Table table){
|
public void buildConfiguration(Table table){
|
||||||
|
|
||||||
table.button(Icon.pencil, Styles.clearTransi, () -> {
|
table.button(Icon.pencil, Styles.clearTransi, () -> {
|
||||||
Vars.ui.logic.show(code, code -> {
|
Vars.ui.logic.show(code, code -> {
|
||||||
configure(compress(code, relativeConnections()));
|
configure(compress(code, relativeConnections()));
|
||||||
@@ -433,19 +430,6 @@ public class LogicBlock extends Block{
|
|||||||
}).size(40);
|
}).size(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(){
|
|
||||||
super.draw();
|
|
||||||
|
|
||||||
if(ui.hudfrag.blockfrag.hover() instanceof Unit unit && unit.controller() instanceof LogicAI ai && ai.controller == this){
|
|
||||||
Draw.z(Layer.overlayUI);
|
|
||||||
Drawf.square(x, y, size * tilesize/2f + 2f);
|
|
||||||
if(!unit.within(this, unit.hitSize * 2f)){
|
|
||||||
Drawf.arrow(unit.x, unit.y, x, y, unit.hitSize *2f, 4f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onConfigureTileTapped(Building other){
|
public boolean onConfigureTileTapped(Building other){
|
||||||
if(this == other){
|
if(this == other){
|
||||||
|
|||||||
@@ -112,6 +112,12 @@ public class PowerNode extends PowerBlock{
|
|||||||
(UI.formatAmount((int)entity.power.graph.getLastPowerStored())), UI.formatAmount((int)entity.power.graph.getLastCapacity())),
|
(UI.formatAmount((int)entity.power.graph.getLastPowerStored())), UI.formatAmount((int)entity.power.graph.getLastCapacity())),
|
||||||
() -> Pal.powerBar,
|
() -> Pal.powerBar,
|
||||||
() -> Mathf.clamp(entity.power.graph.getLastPowerStored() / entity.power.graph.getLastCapacity())));
|
() -> Mathf.clamp(entity.power.graph.getLastPowerStored() / entity.power.graph.getLastCapacity())));
|
||||||
|
|
||||||
|
bars.add("connections", entity -> new Bar(() ->
|
||||||
|
Core.bundle.format("bar.powerlines", entity.power.links.size, maxNodes),
|
||||||
|
() -> Pal.items,
|
||||||
|
() -> (float)entity.power.links.size / (float)maxNodes
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import mindustry.game.EventType.*;
|
|||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.logic.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
@@ -157,6 +158,13 @@ public class CoreBlock extends StorageBlock{
|
|||||||
public int storageCapacity;
|
public int storageCapacity;
|
||||||
//note that this unit is never actually used for control; the possession handler makes the player respawn when this unit is controlled
|
//note that this unit is never actually used for control; the possession handler makes the player respawn when this unit is controlled
|
||||||
public BlockUnitc unit = Nulls.blockUnit;
|
public BlockUnitc unit = Nulls.blockUnit;
|
||||||
|
public boolean noEffect = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double sense(LAccess sensor){
|
||||||
|
if(sensor == LAccess.itemCapacity) return storageCapacity;
|
||||||
|
return super.sense(sensor);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void created(){
|
public void created(){
|
||||||
@@ -195,7 +203,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Building source, Item item){
|
public boolean acceptItem(Building source, Item item){
|
||||||
return items.get(item) < getMaximumAccepted(item);
|
return items.get(item) < getMaximumAccepted(item) || incinerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -264,6 +272,10 @@ public class CoreBlock extends StorageBlock{
|
|||||||
return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == core || ((StorageBuild)tile).linkedCore == null);
|
return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == core || ((StorageBuild)tile).linkedCore == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean incinerate(){
|
||||||
|
return state.isCampaign();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float handleDamage(float amount){
|
public float handleDamage(float amount){
|
||||||
if(player != null && team == player.team()){
|
if(player != null && team == player.team()){
|
||||||
@@ -298,16 +310,51 @@ public class CoreBlock extends StorageBlock{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyed(){
|
||||||
|
super.onDestroyed();
|
||||||
|
|
||||||
|
if(state.isCampaign() && team == state.rules.waveTeam){
|
||||||
|
//do not recache
|
||||||
|
world.setGenerating(true);
|
||||||
|
tile.setOverlay(Blocks.spawn);
|
||||||
|
world.setGenerating(false);
|
||||||
|
|
||||||
|
if(!spawner.getSpawns().contains(tile)){
|
||||||
|
spawner.getSpawns().add(tile);
|
||||||
|
}
|
||||||
|
spawner.doShockwave(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void placed(){
|
public void placed(){
|
||||||
super.placed();
|
super.placed();
|
||||||
state.teams.registerCore(this);
|
state.teams.registerCore(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void itemTaken(Item item){
|
||||||
|
if(state.isCampaign()){
|
||||||
|
//update item taken amount
|
||||||
|
state.secinfo.handleCoreItem(item, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleItem(Building source, Item item){
|
public void handleItem(Building source, Item item){
|
||||||
if(net.server() || !net.active()){
|
if(net.server() || !net.active()){
|
||||||
super.handleItem(source, item);
|
|
||||||
|
if(items.get(item) >= getMaximumAccepted(item)){
|
||||||
|
//create item incineration effect at random intervals
|
||||||
|
if(!noEffect){
|
||||||
|
incinerateEffect(this, source);
|
||||||
|
}
|
||||||
|
noEffect = false;
|
||||||
|
}else{
|
||||||
|
super.handleItem(source, item);
|
||||||
|
}
|
||||||
|
|
||||||
if(state.rules.tutorial){
|
if(state.rules.tutorial){
|
||||||
Events.fire(new CoreItemDeliverEvent());
|
Events.fire(new CoreItemDeliverEvent());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package mindustry.world.blocks.storage;
|
package mindustry.world.blocks.storage;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.content.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
public class StorageBlock extends Block{
|
public class StorageBlock extends Block{
|
||||||
@@ -22,6 +25,16 @@ public class StorageBlock extends Block{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void incinerateEffect(Building self, Building source){
|
||||||
|
if(Mathf.chance(0.1)){
|
||||||
|
Tile edge = Edges.getFacingEdge(source, self);
|
||||||
|
Tile edge2 = Edges.getFacingEdge(self, source);
|
||||||
|
if(edge != null && edge2 != null){
|
||||||
|
Fx.fuelburn.at((edge.worldx() + edge2.worldx())/2f, (edge.worldy() + edge2.worldy())/2f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class StorageBuild extends Building{
|
public class StorageBuild extends Building{
|
||||||
protected @Nullable Building linkedCore;
|
protected @Nullable Building linkedCore;
|
||||||
|
|
||||||
@@ -30,6 +43,17 @@ public class StorageBlock extends Block{
|
|||||||
return linkedCore != null ? linkedCore.acceptItem(source, item) : items.get(item) < getMaximumAccepted(item);
|
return linkedCore != null ? linkedCore.acceptItem(source, item) : items.get(item) < getMaximumAccepted(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleItem(Building source, Item item){
|
||||||
|
if(linkedCore != null){
|
||||||
|
incinerateEffect(this, source);
|
||||||
|
((CoreBuild)linkedCore).noEffect = true;
|
||||||
|
linkedCore.handleItem(source, item);
|
||||||
|
}else{
|
||||||
|
super.handleItem(source, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaximumAccepted(Item item){
|
public int getMaximumAccepted(Item item){
|
||||||
return itemCapacity;
|
return itemCapacity;
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public class Unloader extends Block{
|
|||||||
}else{
|
}else{
|
||||||
other.items.remove(item, 1);
|
other.items.remove(item, 1);
|
||||||
}
|
}
|
||||||
|
other.itemTaken(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
{
|
{
|
||||||
"address": "aamindustry.play.ai:6568"
|
"address": "aamindustry.play.ai:6568"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"address": "aamindustry.play.ai:6569"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"address": "aamindustry.play.ai:6570"
|
"address": "aamindustry.play.ai:6570"
|
||||||
},
|
},
|
||||||
@@ -74,6 +77,9 @@
|
|||||||
{
|
{
|
||||||
"address": "pandorum.su:9999"
|
"address": "pandorum.su:9999"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"address": "mindustryranked.ddns.net"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"address": "attack.pearkin.net"
|
"address": "attack.pearkin.net"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "md.surrealment.com"
|
"address": "md.surrealment.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "routerchain.ddns.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "mindustry.pl:6660"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "be.wayzer.cf"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user