Merge branch 'continuous-sectors' of https://github.com/Anuken/Mindustry
# Conflicts: # core/assets/bundles/bundle.properties
This commit is contained in:
@@ -5,10 +5,6 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
|
||||||
* Goal: To create a system to send events to the server from the client and vice versa, without creating a new packet type each time.<br>
|
|
||||||
* These events may optionally also trigger on the caller client/server as well.<br>
|
|
||||||
*/
|
|
||||||
public class Annotations{
|
public class Annotations{
|
||||||
|
|
||||||
/** Marks a class as serializable.*/
|
/** Marks a class as serializable.*/
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ text.level.delete.title=Confirm Delete
|
|||||||
text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"?
|
text.map.delete=Are you sure you want to delete the map "[orange]{0}[]"?
|
||||||
text.level.select=Level Select
|
text.level.select=Level Select
|
||||||
text.level.mode=Gamemode:
|
text.level.mode=Gamemode:
|
||||||
text.construction.desktop=Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[].
|
text.construction.desktop=To deselect a block or stop building, [accent]use space[].
|
||||||
text.construction.title=Block Construction Guide
|
text.construction.title=Block Construction Guide
|
||||||
text.construction=\
|
text.construction=\
|
||||||
You've just selected [accent]block construction mode[].\n\n\
|
You've just selected [accent]block construction mode[].\n\n\
|
||||||
@@ -58,11 +58,20 @@ text.sector.resume=Resume
|
|||||||
text.sector.locked=[scarlet][[Incomplete]
|
text.sector.locked=[scarlet][[Incomplete]
|
||||||
text.sector.unexplored=[accent][[Unexplored]
|
text.sector.unexplored=[accent][[Unexplored]
|
||||||
text.mission=Mission:[LIGHT_GRAY] {0}
|
text.mission=Mission:[LIGHT_GRAY] {0}
|
||||||
|
text.mission.info=Mission Info
|
||||||
text.mission.complete=Mission complete!
|
text.mission.complete=Mission complete!
|
||||||
text.mission.complete.body=Sector {0},{1} has been conquered.
|
text.mission.complete.body=Sector {0},{1} has been conquered.
|
||||||
text.mission.wave=Survive [accent]{0}[] waves.
|
text.mission.wave=Survive[accent] {0}/{1} []waves\nWave in {2}
|
||||||
text.mission.battle=Destroy the enemy base.
|
text.mission.wave.enemies=Survive[accent] {0}/{1} []waves\n{2} Enemies
|
||||||
text.mission.resource=Obtain {0} x{1}
|
text.mission.wave.enemy=Survive[accent] {0}/{1} []waves\n{2} Enemy
|
||||||
|
text.mission.wave.menu=Survive[accent] {0} []waves
|
||||||
|
text.mission.battle=Destroy the enemy core
|
||||||
|
text.mission.resource.menu=Obtain {0} x{1}
|
||||||
|
text.mission.resource=Obtain {0}:\n[accent]{1}/{2}[]
|
||||||
|
text.mission.block=Create {0}
|
||||||
|
text.mission.unit=Create {0} Unit
|
||||||
|
text.mission.linknode=Link Power Node
|
||||||
|
text.mission.display=[accent]Mission:\n[LIGHT_GRAY]{0}
|
||||||
text.none=<none>
|
text.none=<none>
|
||||||
text.close=Close
|
text.close=Close
|
||||||
text.quit=Quit
|
text.quit=Quit
|
||||||
@@ -276,7 +285,7 @@ text.settings.clearall=Clear All
|
|||||||
text.paused=Paused
|
text.paused=Paused
|
||||||
text.yes=Yes
|
text.yes=Yes
|
||||||
text.no=No
|
text.no=No
|
||||||
text.info.title=[accent]Info
|
text.info.title=Info
|
||||||
text.error.title=[crimson]An error has occured
|
text.error.title=[crimson]An error has occured
|
||||||
text.error.crashtitle=An error has occured
|
text.error.crashtitle=An error has occured
|
||||||
text.blocks.blockinfo=Block Info
|
text.blocks.blockinfo=Block Info
|
||||||
@@ -596,9 +605,9 @@ block.spirit-factory.name=Spirit Drone Factory
|
|||||||
block.phantom-factory.name=Phantom Drone Factory
|
block.phantom-factory.name=Phantom Drone Factory
|
||||||
block.wraith-factory.name=Wraith Fighter Factory
|
block.wraith-factory.name=Wraith Fighter Factory
|
||||||
block.ghoul-factory.name=Ghoul Bomber Factory
|
block.ghoul-factory.name=Ghoul Bomber Factory
|
||||||
block.dagger-factory.name=Dagger Factory
|
block.dagger-factory.name=Dagger Mech Factory
|
||||||
block.titan-factory.name=Titan Factory
|
block.titan-factory.name=Titan Mech Factory
|
||||||
block.revenant-factory.name=Revenant Factory
|
block.revenant-factory.name=Revenant Fighter Factory
|
||||||
block.repair-point.name=Repair Point
|
block.repair-point.name=Repair Point
|
||||||
block.resupply-point.name=Resupply Point
|
block.resupply-point.name=Resupply Point
|
||||||
block.pulse-conduit.name=Pulse Conduit
|
block.pulse-conduit.name=Pulse Conduit
|
||||||
@@ -611,7 +620,7 @@ block.rotary-pump.name=Rotary Pump
|
|||||||
block.thorium-reactor.name=Thorium Reactor
|
block.thorium-reactor.name=Thorium Reactor
|
||||||
block.command-center.name=Command Center
|
block.command-center.name=Command Center
|
||||||
block.mass-driver.name=Mass Driver
|
block.mass-driver.name=Mass Driver
|
||||||
block.blast-drill.name=Blast Drill
|
block.blast-drill.name=Airblast Drill
|
||||||
block.thermal-pump.name=Thermal Pump
|
block.thermal-pump.name=Thermal Pump
|
||||||
block.thermal-generator.name=Thermal Generator
|
block.thermal-generator.name=Thermal Generator
|
||||||
block.alloy-smelter.name=Alloy Smelter
|
block.alloy-smelter.name=Alloy Smelter
|
||||||
@@ -645,3 +654,25 @@ unit.fortress.name=Fortress
|
|||||||
unit.fortress.description=A heavy artillery ground unit.
|
unit.fortress.description=A heavy artillery ground unit.
|
||||||
unit.revenant.name=Revenant
|
unit.revenant.name=Revenant
|
||||||
unit.revenant.description=A heavy laser platform.
|
unit.revenant.description=A heavy laser platform.
|
||||||
|
|
||||||
|
tutorial.begin=Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this.
|
||||||
|
tutorial.drill=Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein.
|
||||||
|
tutorial.conveyor=[accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core.
|
||||||
|
tutorial.morecopper=More copper is required.\n\nEither mine it manually, or place more drills.
|
||||||
|
tutorial.turret=Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base.
|
||||||
|
tutorial.drillturret=Duo turrets require[accent] copper ammo []to shoot.\nPlace a drill next to the turret to supply it with mined copper.
|
||||||
|
tutorial.waves=The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets.
|
||||||
|
tutorial.lead=More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources.
|
||||||
|
tutorial.smelter=Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one.
|
||||||
|
tutorial.densealloy=The smelter will now produce alloy.\nGet some.\nImprove the production if necessary.
|
||||||
|
tutorial.siliconsmelter=The core will now create a[accent] spirit drone[] for mining and repairing blocks.\n\nFactories for other units can be created with [accent] silicon.\nMake a silicon smelter.
|
||||||
|
tutorial.silicondrill=Silicon requires[accent] coal[] and[accent] sand[].\nStart by making drills.
|
||||||
|
tutorial.generator=This technology requires power.\nCreate a[accent] combustion generator[] for it.
|
||||||
|
tutorial.generatordrill=Combustion generators need fuel.\nFuel it with coal from a drill.
|
||||||
|
tutorial.node=Power requires transport.\nCreate a[accent] power node[] next to your combustion generator to transfer its power.
|
||||||
|
tutorial.nodelink=Power can be transferred through contacting power blocks and generators, or by linked power nodes.\n\nLink power by tapping the node and selecting the generator and silicon smelter.
|
||||||
|
tutorial.silicon=Silicon is being produced. Get some.\n\nImproving the production system is advised.
|
||||||
|
tutorial.daggerfactory=Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs.
|
||||||
|
tutorial.router=Factories need resources to function.\nCreate a router to split conveyor resources.
|
||||||
|
tutorial.dagger=Link power nodes to the factory.\nOnce requirements are met, a mech will be created.\n\nCreate more drills, generators and conveyors as necessary.
|
||||||
|
tutorial.battle=The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs.
|
||||||
@@ -41,6 +41,7 @@ TintedDrawable: {
|
|||||||
loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} },
|
loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} },
|
||||||
chatfield: {name: white, color: {r: 0, g: 0, b: 0, a: 0.2}},
|
chatfield: {name: white, color: {r: 0, g: 0, b: 0, a: 0.2}},
|
||||||
clear: {name: white, color: {r: 0.1, g: 0.1, b: 0.1, a: 0.75}},
|
clear: {name: white, color: {r: 0.1, g: 0.1, b: 0.1, a: 0.75}},
|
||||||
|
none: {name: white, color: {r: 0, g: 0, b: 0, a: 0}},
|
||||||
clear-over: {name: white, color: {r: 1, g: 1, b: 1, a: 0.2} },
|
clear-over: {name: white, color: {r: 1, g: 1, b: 1, a: 0.2} },
|
||||||
clear-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} }
|
clear-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} }
|
||||||
},
|
},
|
||||||
@@ -64,7 +65,7 @@ ImageButtonStyle: {
|
|||||||
static: {up: button },
|
static: {up: button },
|
||||||
static-down: {up: button-down },
|
static-down: {up: button-down },
|
||||||
toggle: {checked: button-down, down: button-down, up: button, imageDisabledColor: gray, imageUpColor: white },
|
toggle: {checked: button-down, down: button-down, up: button, imageDisabledColor: gray, imageUpColor: white },
|
||||||
select: {checked: button-select, up: clear },
|
select: {checked: button-select, up: none },
|
||||||
clear: {down: clear-down, up: clear, over: clear-over},
|
clear: {down: clear-down, up: clear, over: clear-over},
|
||||||
},
|
},
|
||||||
ScrollPaneStyle: {
|
ScrollPaneStyle: {
|
||||||
|
|||||||
@@ -36,19 +36,19 @@ public class Vars{
|
|||||||
//time between waves in frames (on normal mode)
|
//time between waves in frames (on normal mode)
|
||||||
public static final float wavespace = 60 * 60 * 1.5f;
|
public static final float wavespace = 60 * 60 * 1.5f;
|
||||||
|
|
||||||
public static final float mineTransferRange = 310f;
|
public static final float mineTransferRange = 220f;
|
||||||
//set ridiculously high for now
|
//set ridiculously high for now
|
||||||
public static final float coreBuildRange = 999999f;
|
public static final float coreBuildRange = 999999f;
|
||||||
//team of the player by default
|
//team of the player by default
|
||||||
public static final Team defaultTeam = Team.blue;
|
public static final Team defaultTeam = Team.blue;
|
||||||
//team of the enemy in waves
|
//team of the enemy in waves
|
||||||
public static final Team waveTeam = Team.red;
|
public static final Team waveTeam = Team.red;
|
||||||
public static final float unlockResourceScaling = 1.5f;
|
public static final float unlockResourceScaling = 1f;
|
||||||
public static final int maxTextLength = 150;
|
public static final int maxTextLength = 150;
|
||||||
public static final int maxNameLength = 40;
|
public static final int maxNameLength = 40;
|
||||||
public static final float itemSize = 5f;
|
public static final float itemSize = 5f;
|
||||||
public static final int tilesize = 8;
|
public static final int tilesize = 8;
|
||||||
public static final int sectorSize = 300;
|
public static final int sectorSize = 120;
|
||||||
public static final int mapPadding = 3;
|
public static final int mapPadding = 3;
|
||||||
public static final int invalidSector = Integer.MAX_VALUE;
|
public static final int invalidSector = Integer.MAX_VALUE;
|
||||||
public static Locale[] locales;
|
public static Locale[] locales;
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ public class Pathfinder{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void activateTeamPath(Team team){
|
||||||
|
createFor(team);
|
||||||
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
if(Net.client()) return;
|
if(Net.client()) return;
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ public class Recipes implements ContentList{
|
|||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
//DEBUG
|
//DEBUG
|
||||||
new Recipe(distribution, DebugBlocks.itemSource).setMode(GameMode.sandbox).setHidden(true);
|
new Recipe(distribution, DebugBlocks.itemSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||||
new Recipe(distribution, DebugBlocks.itemVoid).setMode(GameMode.sandbox).setHidden(true);
|
new Recipe(distribution, DebugBlocks.itemVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||||
new Recipe(liquid, DebugBlocks.liquidSource).setMode(GameMode.sandbox).setHidden(true);
|
new Recipe(liquid, DebugBlocks.liquidSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||||
new Recipe(power, DebugBlocks.powerVoid).setMode(GameMode.sandbox).setHidden(true);
|
new Recipe(power, DebugBlocks.powerVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||||
new Recipe(power, DebugBlocks.powerInfinite).setMode(GameMode.sandbox).setHidden(true);
|
new Recipe(power, DebugBlocks.powerInfinite).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||||
|
|
||||||
//DEFENSE
|
//DEFENSE
|
||||||
|
|
||||||
//walls
|
//walls
|
||||||
new Recipe(defense, DefenseBlocks.copperWall, new ItemStack(Items.copper, 12));
|
new Recipe(defense, DefenseBlocks.copperWall, new ItemStack(Items.copper, 12)).setAlwaysUnlocked(true);
|
||||||
new Recipe(defense, DefenseBlocks.copperWallLarge, new ItemStack(Items.copper, 12 * 4));
|
new Recipe(defense, DefenseBlocks.copperWallLarge, new ItemStack(Items.copper, 12 * 4)).setAlwaysUnlocked(true);
|
||||||
|
|
||||||
new Recipe(defense, DefenseBlocks.denseAlloyWall, new ItemStack(Items.densealloy, 12));
|
new Recipe(defense, DefenseBlocks.denseAlloyWall, new ItemStack(Items.densealloy, 12));
|
||||||
new Recipe(defense, DefenseBlocks.denseAlloyWallLarge, new ItemStack(Items.densealloy, 12 * 4));
|
new Recipe(defense, DefenseBlocks.denseAlloyWallLarge, new ItemStack(Items.densealloy, 12 * 4));
|
||||||
@@ -51,7 +51,7 @@ public class Recipes implements ContentList{
|
|||||||
.setDependencies(Items.blastCompound);
|
.setDependencies(Items.blastCompound);
|
||||||
|
|
||||||
//TURRETS
|
//TURRETS
|
||||||
new Recipe(weapon, TurretBlocks.duo, new ItemStack(Items.copper, 40));
|
new Recipe(weapon, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true);
|
||||||
new Recipe(weapon, TurretBlocks.arc, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 30), new ItemStack(Items.silicon, 20));
|
new Recipe(weapon, TurretBlocks.arc, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 30), new ItemStack(Items.silicon, 20));
|
||||||
new Recipe(weapon, TurretBlocks.hail, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 35));
|
new Recipe(weapon, TurretBlocks.hail, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 35));
|
||||||
new Recipe(weapon, TurretBlocks.lancer, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 90));
|
new Recipe(weapon, TurretBlocks.lancer, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 90));
|
||||||
@@ -65,13 +65,13 @@ public class Recipes implements ContentList{
|
|||||||
new Recipe(weapon, TurretBlocks.meltdown, new ItemStack(Items.copper, 500), new ItemStack(Items.lead, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 650), new ItemStack(Items.silicon, 650));
|
new Recipe(weapon, TurretBlocks.meltdown, new ItemStack(Items.copper, 500), new ItemStack(Items.lead, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 650), new ItemStack(Items.silicon, 650));
|
||||||
|
|
||||||
//DISTRIBUTION
|
//DISTRIBUTION
|
||||||
new Recipe(distribution, DistributionBlocks.conveyor, new ItemStack(Items.copper, 1));
|
new Recipe(distribution, DistributionBlocks.conveyor, new ItemStack(Items.copper, 1)).setAlwaysUnlocked(true);
|
||||||
new Recipe(distribution, DistributionBlocks.titaniumconveyor, new ItemStack(Items.copper, 2), new ItemStack(Items.titanium, 1));
|
new Recipe(distribution, DistributionBlocks.titaniumconveyor, new ItemStack(Items.copper, 2), new ItemStack(Items.titanium, 1));
|
||||||
new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20));
|
new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20));
|
||||||
|
|
||||||
//starter lead transportation
|
//starter lead transportation
|
||||||
new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2));
|
new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2)).setAlwaysUnlocked(true);
|
||||||
new Recipe(distribution, DistributionBlocks.router, new ItemStack(Items.copper, 6));
|
new Recipe(distribution, DistributionBlocks.router, new ItemStack(Items.copper, 6)).setAlwaysUnlocked(true);
|
||||||
|
|
||||||
//advanced densealloy transporation
|
//advanced densealloy transporation
|
||||||
new Recipe(distribution, DistributionBlocks.distributor, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8));
|
new Recipe(distribution, DistributionBlocks.distributor, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8));
|
||||||
@@ -140,7 +140,7 @@ public class Recipes implements ContentList{
|
|||||||
);
|
);
|
||||||
|
|
||||||
//DRILLS, PRODUCERS
|
//DRILLS, PRODUCERS
|
||||||
new Recipe(production, ProductionBlocks.mechanicalDrill, new ItemStack(Items.copper, 50));
|
new Recipe(production, ProductionBlocks.mechanicalDrill, new ItemStack(Items.copper, 45)).setAlwaysUnlocked(true);
|
||||||
new Recipe(production, ProductionBlocks.pneumaticDrill, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50));
|
new Recipe(production, ProductionBlocks.pneumaticDrill, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50));
|
||||||
new Recipe(production, ProductionBlocks.laserdrill, new ItemStack(Items.copper, 70), new ItemStack(Items.densealloy, 90), new ItemStack(Items.silicon, 60), new ItemStack(Items.titanium, 50));
|
new Recipe(production, ProductionBlocks.laserdrill, new ItemStack(Items.copper, 70), new ItemStack(Items.densealloy, 90), new ItemStack(Items.silicon, 60), new ItemStack(Items.titanium, 50));
|
||||||
new Recipe(production, ProductionBlocks.blastdrill, new ItemStack(Items.copper, 130), new ItemStack(Items.densealloy, 180), new ItemStack(Items.silicon, 120), new ItemStack(Items.titanium, 100), new ItemStack(Items.thorium, 60));
|
new Recipe(production, ProductionBlocks.blastdrill, new ItemStack(Items.copper, 130), new ItemStack(Items.densealloy, 180), new ItemStack(Items.silicon, 120), new ItemStack(Items.titanium, 100), new ItemStack(Items.thorium, 60));
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class UnitTypes implements ContentList{
|
|||||||
speed = 0.2f;
|
speed = 0.2f;
|
||||||
maxVelocity = 0.8f;
|
maxVelocity = 0.8f;
|
||||||
range = 50f;
|
range = 50f;
|
||||||
healSpeed = 0.25f;
|
healSpeed = 0.22f;
|
||||||
health = 60;
|
health = 60;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class UnitTypes implements ContentList{
|
|||||||
drag = 0.4f;
|
drag = 0.4f;
|
||||||
range = 40f;
|
range = 40f;
|
||||||
weapon = Weapons.chainBlaster;
|
weapon = Weapons.chainBlaster;
|
||||||
health = 150;
|
health = 130;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
titan = new UnitType("titan", Titan.class, Titan::new){{
|
titan = new UnitType("titan", Titan.class, Titan::new){{
|
||||||
@@ -108,7 +108,7 @@ public class UnitTypes implements ContentList{
|
|||||||
health = 220;
|
health = 220;
|
||||||
buildPower = 0.9f;
|
buildPower = 0.9f;
|
||||||
minePower = 1.1f;
|
minePower = 1.1f;
|
||||||
healSpeed = 0.55f;
|
healSpeed = 0.5f;
|
||||||
toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium);
|
toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
Table cont = new Table();
|
Table cont = new Table();
|
||||||
|
|
||||||
for(int i = 0; i < items.size; i++){
|
for(int i = 0; i < items.size; i++){
|
||||||
if(i == 0) continue;
|
|
||||||
final int f = i;
|
final int f = i;
|
||||||
ImageButton button = cont.addImageButton("liquid-icon-" + items.get(i).name, "toggle", 24, () -> {
|
ImageButton button = cont.addImageButton("liquid-icon-" + items.get(i).name, "toggle", 24, () -> {
|
||||||
Call.setLiquidSourceLiquid(null, tile, items.get(f));
|
Call.setLiquidSourceLiquid(null, tile, items.get(f));
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class StorageBlocks extends BlockList implements ContentList{
|
|||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
core = new CoreBlock("core"){{
|
core = new CoreBlock("core"){{
|
||||||
health = 1400;
|
health = 1100;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
vault = new Vault("vault"){{
|
vault = new Vault("vault"){{
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
|||||||
produceTime = 1700;
|
produceTime = 1700;
|
||||||
size = 2;
|
size = 2;
|
||||||
consumes.power(0.05f);
|
consumes.power(0.05f);
|
||||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 10), new ItemStack(Items.copper, 10)});
|
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 10)});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
titanFactory = new UnitFactory("titan-factory"){{
|
titanFactory = new UnitFactory("titan-factory"){{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import io.anuke.mindustry.entities.TileEntity;
|
|||||||
import io.anuke.mindustry.game.Content;
|
import io.anuke.mindustry.game.Content;
|
||||||
import io.anuke.mindustry.game.ContentDatabase;
|
import io.anuke.mindustry.game.ContentDatabase;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
|
import io.anuke.mindustry.game.GameMode;
|
||||||
import io.anuke.mindustry.game.Saves;
|
import io.anuke.mindustry.game.Saves;
|
||||||
import io.anuke.mindustry.input.DefaultKeybinds;
|
import io.anuke.mindustry.input.DefaultKeybinds;
|
||||||
import io.anuke.mindustry.input.DesktopInput;
|
import io.anuke.mindustry.input.DesktopInput;
|
||||||
@@ -315,29 +316,20 @@ public class Control extends Module{
|
|||||||
|
|
||||||
Platform.instance.updateRPC();
|
Platform.instance.updateRPC();
|
||||||
|
|
||||||
if(!Settings.has("4.0-warning")){
|
if(!Settings.getBool("4.0-warning-2", false)){
|
||||||
Settings.putBool("4.0-warning", true);
|
|
||||||
|
|
||||||
Timers.run(5f, () -> {
|
Timers.run(5f, () -> {
|
||||||
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
||||||
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
dialog.buttons().addButton("$text.ok", () -> {
|
||||||
dialog.content().add("The beta version you are about to play should be considered very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
|
dialog.hide();
|
||||||
"A large portion of content is still unimplemented. \nAll current art and UI is temporary, and will be re-drawn before release. " +
|
Settings.putBool("4.0-warning-2", true);
|
||||||
"\n\n[accent]Saves and maps may be corrupted without warning between updates.[] You have been warned!").wrap().width(400f);
|
Settings.save();
|
||||||
|
}).size(100f, 60f);
|
||||||
|
dialog.content().add("Reminder: The beta version you are about to play is very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
|
||||||
|
"\nThere is currently[scarlet] no sound implemented[]; this is intentional.\n" +
|
||||||
|
"All current art and UI is temporary, and will be re-drawn before release. " +
|
||||||
|
"\n\n[accent]Saves and maps may be corrupted without warning between updates.").wrap().width(400f);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!Settings.has("4.0-no-sound")){
|
|
||||||
Settings.putBool("4.0-no-sound", true);
|
|
||||||
|
|
||||||
Timers.run(4f, () -> {
|
|
||||||
FloatingDialog dialog = new FloatingDialog("[orange]Attention![]");
|
|
||||||
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
|
||||||
dialog.content().add("You might have noticed that 4.0 does not have any sound.\nThis is [orange]intentional![] Sound will be added in a later update.\n\n[LIGHT_GRAY](now stop reporting this as a bug)").wrap().width(400f);
|
|
||||||
dialog.show();
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,6 +341,32 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSectors(){
|
||||||
|
if(world.getSector() == null) return;
|
||||||
|
|
||||||
|
world.getSector().currentMission().update();
|
||||||
|
|
||||||
|
//TODO move sector code into logic class
|
||||||
|
//check unlocked sectors
|
||||||
|
while(!world.getSector().complete && world.getSector().currentMission().isComplete()){
|
||||||
|
world.getSector().currentMission().onComplete();
|
||||||
|
world.getSector().completedMissions ++;
|
||||||
|
|
||||||
|
state.mode = world.getSector().currentMission().getMode();
|
||||||
|
world.getSector().currentMission().onBegin();
|
||||||
|
world.sectors().save();
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if all assigned missions are complete
|
||||||
|
if(!world.getSector().complete && world.getSector().completedMissions >= world.getSector().missions.size){
|
||||||
|
state.mode = GameMode.victory;
|
||||||
|
|
||||||
|
world.sectors().completeSector(world.getSector().x, world.getSector().y);
|
||||||
|
world.sectors().save();
|
||||||
|
ui.missions.show(world.getSector());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
|
|
||||||
@@ -374,19 +392,7 @@ public class Control extends Module{
|
|||||||
Platform.instance.updateRPC();
|
Platform.instance.updateRPC();
|
||||||
}
|
}
|
||||||
|
|
||||||
//check unlocked sectors
|
updateSectors();
|
||||||
if(world.getSector() != null && !world.getSector().complete){
|
|
||||||
//all assigned missions are complete
|
|
||||||
if(world.getSector().completedMissions >= world.getSector().missions.size){
|
|
||||||
|
|
||||||
world.sectors().completeSector(world.getSector().x, world.getSector().y);
|
|
||||||
world.sectors().save();
|
|
||||||
ui.missions.show(world.getSector());
|
|
||||||
}else if(world.getSector().currentMission().isComplete()){
|
|
||||||
//increment completed missions, check next index next frame
|
|
||||||
world.getSector().completedMissions ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//check unlocks every 2 seconds
|
//check unlocks every 2 seconds
|
||||||
if(world.getSector() != null && Timers.get("timerCheckUnlock", 120)){
|
if(world.getSector() != null && Timers.get("timerCheckUnlock", 120)){
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public class Logic extends Module{
|
|||||||
Entities.update(fireGroup);
|
Entities.update(fireGroup);
|
||||||
Entities.update(playerGroup);
|
Entities.update(playerGroup);
|
||||||
|
|
||||||
//effect group only contains item drops in the headless version, update it!
|
//effect group only contains item transfers in the headless version, update it!
|
||||||
if(headless){
|
if(headless){
|
||||||
Entities.update(effectGroup);
|
Entities.update(effectGroup);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,11 +210,11 @@ public class UI extends SceneModule{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAnd(Runnable call){
|
public void loadGraphics(Runnable call){
|
||||||
loadAnd("$text.loading", call);
|
loadGraphics("$text.loading", call);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAnd(String text, Runnable call){
|
public void loadGraphics(String text, Runnable call){
|
||||||
loadfrag.show(text);
|
loadfrag.show(text);
|
||||||
Timers.runTask(7f, () -> {
|
Timers.runTask(7f, () -> {
|
||||||
call.run();
|
call.run();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.maps.*;
|
|||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.maps.generation.WorldGenerator;
|
import io.anuke.mindustry.maps.generation.WorldGenerator;
|
||||||
|
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.entities.EntityPhysics;
|
import io.anuke.ucore.entities.EntityPhysics;
|
||||||
@@ -195,6 +196,12 @@ public class World extends Module{
|
|||||||
generating = true;
|
generating = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Call to signal the beginning of loading the map with a custom set of tiles.*/
|
||||||
|
public void beginMapLoad(Tile[][] tiles){
|
||||||
|
this.tiles = tiles;
|
||||||
|
generating = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call to signify the end of map loading. Updates tile occlusions and sets up physics for the world.
|
* Call to signify the end of map loading. Updates tile occlusions and sets up physics for the world.
|
||||||
* A WorldLoadEvent will be fire.
|
* A WorldLoadEvent will be fire.
|
||||||
@@ -202,10 +209,15 @@ public class World extends Module{
|
|||||||
public void endMapLoad(){
|
public void endMapLoad(){
|
||||||
for(int x = 0; x < tiles.length; x++){
|
for(int x = 0; x < tiles.length; x++){
|
||||||
for(int y = 0; y < tiles[0].length; y++){
|
for(int y = 0; y < tiles[0].length; y++){
|
||||||
tiles[x][y].updateOcclusion();
|
Tile tile = tiles[x][y];
|
||||||
|
tile.updateOcclusion();
|
||||||
|
|
||||||
if(tiles[x][y].entity != null){
|
if(tile.floor() instanceof OreBlock && tile.hasCliffs()){
|
||||||
tiles[x][y].entity.updateProximity();
|
tile.setFloor(((OreBlock) tile.floor()).base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tile.entity != null){
|
||||||
|
tile.entity.updateProximity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +244,7 @@ public class World extends Module{
|
|||||||
|
|
||||||
beginMapLoad();
|
beginMapLoad();
|
||||||
|
|
||||||
int width = sectorSize * sector.size, height = sectorSize * sector.size;
|
int width = sectorSize * sector.width, height = sectorSize * sector.height;
|
||||||
|
|
||||||
Tile[][] tiles = createTiles(width, height);
|
Tile[][] tiles = createTiles(width, height);
|
||||||
|
|
||||||
@@ -322,6 +334,15 @@ public class World extends Module{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int transform(int packed, int oldWidth, int oldHeight, int newWidth, int shiftX, int shiftY){
|
||||||
|
int x = packed % oldWidth;
|
||||||
|
int y = packed / oldWidth;
|
||||||
|
if(!Mathf.inBounds(x, y, oldWidth, oldHeight)) return -1;
|
||||||
|
x += shiftX;
|
||||||
|
y += shiftY;
|
||||||
|
return y*newWidth + x;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raycast, but with world coordinates.
|
* Raycast, but with world coordinates.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
"$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show,
|
"$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show,
|
||||||
"$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () -> {
|
"$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () -> {
|
||||||
Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> {
|
Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> {
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
try{
|
try{
|
||||||
DataInputStream stream = new DataInputStream(file.read());
|
DataInputStream stream = new DataInputStream(file.read());
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
ui.showError("$text.web.unsupported");
|
ui.showError("$text.web.unsupported");
|
||||||
}else {
|
}else {
|
||||||
Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> {
|
Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> {
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
try{
|
try{
|
||||||
MapTileData data = MapIO.readPixmap(new Pixmap(file));
|
MapTileData data = MapIO.readPixmap(new Pixmap(file));
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> {
|
Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> {
|
||||||
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
|
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
|
||||||
FileHandle result = file;
|
FileHandle result = file;
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
|
|
||||||
try{
|
try{
|
||||||
if(!editor.getTags().containsKey("name")){
|
if(!editor.getTags().containsKey("name")){
|
||||||
@@ -168,7 +168,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
Platform.instance.showFileChooser("$text.saveimage", "Image Files", file -> {
|
Platform.instance.showFileChooser("$text.saveimage", "Image Files", file -> {
|
||||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||||
FileHandle result = file;
|
FileHandle result = file;
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
try{
|
try{
|
||||||
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
|
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
@@ -194,7 +194,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
|
|
||||||
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
|
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
|
||||||
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
|
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
editor.resize(x, y);
|
editor.resize(x, y);
|
||||||
view.clearStack();
|
view.clearStack();
|
||||||
});
|
});
|
||||||
@@ -203,7 +203,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
|
|
||||||
loadDialog = new MapLoadDialog(map -> {
|
loadDialog = new MapLoadDialog(map -> {
|
||||||
|
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
try(DataInputStream stream = new DataInputStream(map.stream.get())){
|
try(DataInputStream stream = new DataInputStream(map.stream.get())){
|
||||||
MapMeta meta = MapIO.readMapMeta(stream);
|
MapMeta meta = MapIO.readMapMeta(stream);
|
||||||
MapTileData data = MapIO.readTileData(stream, meta, false);
|
MapTileData data = MapIO.readTileData(stream, meta, false);
|
||||||
@@ -338,7 +338,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void beginEditMap(InputStream is){
|
public void beginEditMap(InputStream is){
|
||||||
ui.loadAnd(() -> {
|
ui.loadGraphics(() -> {
|
||||||
try{
|
try{
|
||||||
shownWithMap = true;
|
shownWithMap = true;
|
||||||
DataInputStream stream = new DataInputStream(is);
|
DataInputStream stream = new DataInputStream(is);
|
||||||
|
|||||||
@@ -311,9 +311,6 @@ public interface BuilderTrait extends Entity{
|
|||||||
|
|
||||||
Draw.alpha(0.3f + Mathf.absin(Timers.time(), 0.9f, 0.2f));
|
Draw.alpha(0.3f + Mathf.absin(Timers.time(), 0.9f, 0.2f));
|
||||||
|
|
||||||
Fill.tri(px, py, x2, y2, x1, y1);
|
|
||||||
Fill.tri(px, py, x2, y2, x3, y3);
|
|
||||||
|
|
||||||
Draw.alpha(1f);
|
Draw.alpha(1f);
|
||||||
|
|
||||||
Lines.line(px, py, x1, y1);
|
Lines.line(px, py, x1, y1);
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
this.spawner = tile.packedPosition();
|
this.spawner = tile.packedPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIntSpawner(int pos){
|
||||||
|
this.spawner = pos;
|
||||||
|
}
|
||||||
|
|
||||||
/**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/
|
/**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/
|
||||||
public void setWave(){
|
public void setWave(){
|
||||||
isWave = true;
|
isWave = true;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class ContentDatabase{
|
|||||||
* @return whether or not this content was newly unlocked.
|
* @return whether or not this content was newly unlocked.
|
||||||
*/
|
*/
|
||||||
public boolean unlockContent(UnlockableContent content){
|
public boolean unlockContent(UnlockableContent content){
|
||||||
if(!content.canBeUnlocked()) return false;
|
if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false;
|
||||||
|
|
||||||
if(!unlocked.containsKey(content.getContentType())){
|
if(!unlocked.containsKey(content.getContentType())){
|
||||||
unlocked.put(content.getContentType(), new ObjectSet<>());
|
unlocked.put(content.getContentType(), new ObjectSet<>());
|
||||||
|
|||||||
@@ -42,9 +42,7 @@ public class EventType{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**Called from the logic thread. Do not access graphics here!*/
|
||||||
* Called from the logic thread. Do not access graphics here!
|
|
||||||
*/
|
|
||||||
public static class TileChangeEvent implements Event{
|
public static class TileChangeEvent implements Event{
|
||||||
public final Tile tile;
|
public final Tile tile;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ public enum GameMode{
|
|||||||
enemyCheat = true;
|
enemyCheat = true;
|
||||||
showPads = true;
|
showPads = true;
|
||||||
}},
|
}},
|
||||||
|
victory{{
|
||||||
|
disableWaves = true;
|
||||||
|
hidden = true;
|
||||||
|
enemyCheat = false;
|
||||||
|
showPads = true;
|
||||||
|
showMission = false;
|
||||||
|
}},
|
||||||
pvp{{
|
pvp{{
|
||||||
showPads = true;
|
showPads = true;
|
||||||
disableWaves = true;
|
disableWaves = true;
|
||||||
@@ -26,7 +33,7 @@ public enum GameMode{
|
|||||||
respawnTime = 60 * 10;
|
respawnTime = 60 * 10;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public boolean infiniteResources, disableWaveTimer, disableWaves, hidden, enemyCheat, isPvp, showPads;
|
public boolean infiniteResources, disableWaveTimer, disableWaves, showMission = true, hidden, enemyCheat, isPvp, showPads;
|
||||||
public float enemyCoreBuildRadius = 400f;
|
public float enemyCoreBuildRadius = 400f;
|
||||||
public float respawnTime = 60 * 4;
|
public float respawnTime = 60 * 4;
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class Saves{
|
|||||||
if(time > Settings.getInt("saveinterval") * 60){
|
if(time > Settings.getInt("saveinterval") * 60){
|
||||||
saving = true;
|
saving = true;
|
||||||
|
|
||||||
Timers.run(2f, () -> {
|
Timers.runTask(2f, () -> {
|
||||||
try{
|
try{
|
||||||
current.save();
|
current.save();
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ public class SpawnGroup{
|
|||||||
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
|
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
float scaling = this.groupScaling;
|
|
||||||
|
|
||||||
return Math.min(groupAmount - 1 + Math.max((int) ((wave / spacing) / groupScaling), 1), max);
|
return Math.min(groupAmount - 1 + Math.max((int) ((wave / spacing) / groupScaling), 1), max);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class Waves{
|
|||||||
return Array.with(
|
return Array.with(
|
||||||
new SpawnGroup(UnitTypes.dagger){{
|
new SpawnGroup(UnitTypes.dagger){{
|
||||||
end = 8;
|
end = 8;
|
||||||
unitScaling = 1;
|
unitScaling = 3;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.wraith){{
|
new SpawnGroup(UnitTypes.wraith){{
|
||||||
|
|||||||
@@ -40,21 +40,40 @@ public class FogRenderer implements Disposable{
|
|||||||
private Rectangle rect = new Rectangle();
|
private Rectangle rect = new Rectangle();
|
||||||
private boolean dirty;
|
private boolean dirty;
|
||||||
|
|
||||||
|
private boolean isOffseted;
|
||||||
|
private int offsettedX, offsettedY;
|
||||||
|
|
||||||
public FogRenderer(){
|
public FogRenderer(){
|
||||||
Events.on(WorldLoadGraphicsEvent.class, event -> {
|
Events.on(WorldLoadGraphicsEvent.class, event -> {
|
||||||
dispose();
|
if(!isOffseted){
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
padding = world.getSector() != null ? mapPadding + extraPadding : 0;
|
padding = world.getSector() != null ? mapPadding + extraPadding : 0;
|
||||||
shadowPadding = world.getSector() != null ? fshadowPadding : -1;
|
shadowPadding = world.getSector() != null ? fshadowPadding : -1;
|
||||||
|
|
||||||
|
FrameBuffer lastBuffer = buffer;
|
||||||
|
|
||||||
buffer = new FrameBuffer(Format.RGBA8888, world.width() + padding*2, world.height() + padding*2, false);
|
buffer = new FrameBuffer(Format.RGBA8888, world.width() + padding*2, world.height() + padding*2, false);
|
||||||
changeQueue.clear();
|
changeQueue.clear();
|
||||||
|
|
||||||
//clear buffer to black
|
//clear buffer to black
|
||||||
buffer.begin();
|
buffer.begin();
|
||||||
Graphics.clear(0, 0, 0, 1f);
|
Graphics.clear(0, 0, 0, 1f);
|
||||||
|
|
||||||
|
if(isOffseted){
|
||||||
|
Core.batch.getProjectionMatrix().setToOrtho2D(-padding, -padding, buffer.getWidth(), buffer.getHeight());
|
||||||
|
Core.batch.begin();
|
||||||
|
Core.batch.draw(lastBuffer.getColorBufferTexture(), offsettedX, offsettedY + lastBuffer.getColorBufferTexture().getHeight(),
|
||||||
|
lastBuffer.getColorBufferTexture().getWidth(), -lastBuffer.getColorBufferTexture().getHeight());
|
||||||
|
Core.batch.end();
|
||||||
|
}
|
||||||
buffer.end();
|
buffer.end();
|
||||||
|
|
||||||
|
if(isOffseted){
|
||||||
|
lastBuffer.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
for(int x = 0; x < world.width(); x++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
for(int y = 0; y < world.height(); y++){
|
for(int y = 0; y < world.height(); y++){
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
@@ -66,6 +85,8 @@ public class FogRenderer implements Disposable{
|
|||||||
|
|
||||||
pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 4);
|
pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 4);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
|
isOffseted = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(TileChangeEvent.class, event -> threads.runGraphics(() -> {
|
Events.on(TileChangeEvent.class, event -> threads.runGraphics(() -> {
|
||||||
@@ -75,6 +96,12 @@ public class FogRenderer implements Disposable{
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLoadingOffset(int x, int y){
|
||||||
|
isOffseted = true;
|
||||||
|
offsettedX = x;
|
||||||
|
offsettedY = y;
|
||||||
|
}
|
||||||
|
|
||||||
public void writeFog(){
|
public void writeFog(){
|
||||||
if(buffer == null) return;
|
if(buffer == null) return;
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ public class OverlayRenderer{
|
|||||||
for(Player player : players){
|
for(Player player : players){
|
||||||
InputHandler input = control.input(player.playerIndex);
|
InputHandler input = control.input(player.playerIndex);
|
||||||
|
|
||||||
|
if(world.getSector() != null){
|
||||||
|
world.getSector().currentMission().drawOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
if(!input.isDrawing() || player.isDead()) continue;
|
if(!input.isDrawing() || player.isDead()) continue;
|
||||||
|
|
||||||
Shaders.outline.color.set(Palette.accent);
|
Shaders.outline.color.set(Palette.accent);
|
||||||
|
|||||||
@@ -206,6 +206,10 @@ public class DesktopInput extends InputHandler{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Inputs.keyTap(section, "deselect")){
|
||||||
|
player.setMineTile(null);
|
||||||
|
}
|
||||||
|
|
||||||
if(!ui.hasMouse()){
|
if(!ui.hasMouse()){
|
||||||
if(Inputs.keyTap(section, "select")){
|
if(Inputs.keyTap(section, "select")){
|
||||||
if(isPlacing()){
|
if(isPlacing()){
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.zip.InflaterInputStream;
|
|||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class SaveIO{
|
public class SaveIO{
|
||||||
public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52);
|
public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56);
|
||||||
public static final IntMap<SaveFileVersion> versions = new IntMap<>();
|
public static final IntMap<SaveFileVersion> versions = new IntMap<>();
|
||||||
public static final Array<SaveFileVersion> versionArray = Array.with(
|
public static final Array<SaveFileVersion> versionArray = Array.with(
|
||||||
new Save16()
|
new Save16()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.anuke.mindustry.game.Difficulty;
|
|||||||
import io.anuke.mindustry.game.Saves.SaveSlot;
|
import io.anuke.mindustry.game.Saves.SaveSlot;
|
||||||
import io.anuke.mindustry.game.SpawnGroup;
|
import io.anuke.mindustry.game.SpawnGroup;
|
||||||
import io.anuke.mindustry.maps.missions.Mission;
|
import io.anuke.mindustry.maps.missions.Mission;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.maps.missions.VictoryMission;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.ucore.util.Bits;
|
import io.anuke.ucore.util.Bits;
|
||||||
|
|
||||||
@@ -15,6 +15,8 @@ import static io.anuke.mindustry.Vars.control;
|
|||||||
|
|
||||||
@Serialize
|
@Serialize
|
||||||
public class Sector{
|
public class Sector{
|
||||||
|
private static final Mission victoryMission = new VictoryMission();
|
||||||
|
|
||||||
/**Position on the map, can be positive or negative.*/
|
/**Position on the map, can be positive or negative.*/
|
||||||
public short x, y;
|
public short x, y;
|
||||||
/**Whether this sector has already been completed.*/
|
/**Whether this sector has already been completed.*/
|
||||||
@@ -22,7 +24,7 @@ public class Sector{
|
|||||||
/**Slot ID of this sector's save. -1 means no save has been created.*/
|
/**Slot ID of this sector's save. -1 means no save has been created.*/
|
||||||
public int saveID = -1;
|
public int saveID = -1;
|
||||||
/**Sector size; if more than 1, the coordinates are the bottom left corner.*/
|
/**Sector size; if more than 1, the coordinates are the bottom left corner.*/
|
||||||
public int size = 1;
|
public int width = 1, height = 1;
|
||||||
/**Num of missions in this sector that have been completed so far.*/
|
/**Num of missions in this sector that have been completed so far.*/
|
||||||
public int completedMissions;
|
public int completedMissions;
|
||||||
/**Display texture. Needs to be disposed.*/
|
/**Display texture. Needs to be disposed.*/
|
||||||
@@ -31,8 +33,6 @@ public class Sector{
|
|||||||
public transient Array<Mission> missions = new Array<>();
|
public transient Array<Mission> missions = new Array<>();
|
||||||
/**Enemies spawned at this sector.*/
|
/**Enemies spawned at this sector.*/
|
||||||
public transient Array<SpawnGroup> spawns;
|
public transient Array<SpawnGroup> spawns;
|
||||||
/**Ores that appear in this sector.*/
|
|
||||||
public transient Array<Item> ores = new Array<>();
|
|
||||||
/**Difficulty of the sector, measured by calculating distance from origin and applying scaling.*/
|
/**Difficulty of the sector, measured by calculating distance from origin and applying scaling.*/
|
||||||
public transient int difficulty;
|
public transient int difficulty;
|
||||||
/**Items the player starts with on this sector.*/
|
/**Items the player starts with on this sector.*/
|
||||||
@@ -41,7 +41,9 @@ public class Sector{
|
|||||||
/**Returns scaled difficulty. This is not just the difficulty ordinal.*/
|
/**Returns scaled difficulty. This is not just the difficulty ordinal.*/
|
||||||
public Difficulty getDifficulty(){
|
public Difficulty getDifficulty(){
|
||||||
if(difficulty == 0){
|
if(difficulty == 0){
|
||||||
return Difficulty.easy;
|
//yes, this means insane tutorial difficulty
|
||||||
|
//(((have fun)))
|
||||||
|
return Difficulty.hard;
|
||||||
}else if(difficulty < 4){
|
}else if(difficulty < 4){
|
||||||
return Difficulty.normal;
|
return Difficulty.normal;
|
||||||
}else if(difficulty < 9){
|
}else if(difficulty < 9){
|
||||||
@@ -52,7 +54,7 @@ public class Sector{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Mission currentMission(){
|
public Mission currentMission(){
|
||||||
return missions.get(Math.min(completedMissions, missions.size - 1));
|
return completedMissions >= missions.size ? victoryMission : missions.get(completedMissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSeed(){
|
public int getSeed(){
|
||||||
|
|||||||
@@ -3,19 +3,24 @@ package io.anuke.mindustry.maps;
|
|||||||
import com.badlogic.gdx.graphics.Pixmap;
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
import com.badlogic.gdx.math.GridPoint2;
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.content.Items;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.SaveIO;
|
||||||
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
||||||
import io.anuke.mindustry.maps.missions.BattleMission;
|
import io.anuke.mindustry.maps.missions.BattleMission;
|
||||||
|
import io.anuke.mindustry.maps.missions.Mission;
|
||||||
import io.anuke.mindustry.maps.missions.WaveMission;
|
import io.anuke.mindustry.maps.missions.WaveMission;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.mindustry.world.ColorMapper;
|
import io.anuke.mindustry.world.ColorMapper;
|
||||||
import io.anuke.mindustry.world.Edges;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
|
import io.anuke.ucore.entities.trait.Entity;
|
||||||
import io.anuke.ucore.util.Bits;
|
import io.anuke.ucore.util.Bits;
|
||||||
import io.anuke.ucore.util.GridMap;
|
import io.anuke.ucore.util.GridMap;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
@@ -25,6 +30,7 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
public class Sectors{
|
public class Sectors{
|
||||||
private static final int sectorImageSize = 32;
|
private static final int sectorImageSize = 32;
|
||||||
|
private static final boolean checkExpansion = false;
|
||||||
private static final float sectorLargeChance = 0.24f;
|
private static final float sectorLargeChance = 0.24f;
|
||||||
|
|
||||||
private GridMap<Sector> grid = new GridMap<>();
|
private GridMap<Sector> grid = new GridMap<>();
|
||||||
@@ -36,17 +42,22 @@ public class Sectors{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!sector.hasSave()){
|
if(!sector.hasSave()){
|
||||||
|
for(Mission mission : sector.missions){
|
||||||
|
mission.reset();
|
||||||
|
}
|
||||||
world.loadSector(sector);
|
world.loadSector(sector);
|
||||||
logic.play();
|
logic.play();
|
||||||
sector.saveID = control.getSaves().addSave("sector-" + sector.packedPosition()).index;
|
sector.saveID = control.getSaves().addSave("sector-" + sector.packedPosition()).index;
|
||||||
world.sectors().save();
|
world.sectors().save();
|
||||||
world.setSector(sector);
|
world.setSector(sector);
|
||||||
|
sector.currentMission().onBegin();
|
||||||
}else if(SaveIO.breakingVersions.contains(sector.getSave().getBuild())){
|
}else if(SaveIO.breakingVersions.contains(sector.getSave().getBuild())){
|
||||||
ui.showInfo("$text.save.old");
|
ui.showInfo("$text.save.old");
|
||||||
}else try{
|
}else try{
|
||||||
sector.getSave().load();
|
sector.getSave().load();
|
||||||
world.setSector(sector);
|
world.setSector(sector);
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
|
sector.currentMission().onBegin();
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
sector.getSave().delete();
|
sector.getSave().delete();
|
||||||
@@ -69,25 +80,145 @@ public class Sectors{
|
|||||||
return grid.get(Bits.getLeftShort(position), Bits.getRightShort(position));
|
return grid.get(Bits.getLeftShort(position), Bits.getRightShort(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Tries to a sector in a specific direciton, specified by expandX and expandY.
|
||||||
|
* The player *must* currently be playing in this sector.
|
||||||
|
* If a sector is in that direction, this method will return false (failure)
|
||||||
|
* @param sector the sector to expand
|
||||||
|
* @param expandX spaces in X coordinate to expand, can be negative
|
||||||
|
* @param expandY spaces in Y coordinate to expand, can be negative*/
|
||||||
|
public boolean expandSector(Sector sector, int expandX, int expandY){
|
||||||
|
if(world.getSector() != sector){
|
||||||
|
throw new IllegalArgumentException("Sector is not being played in!");
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove old sector data to clear things up
|
||||||
|
for(int x = sector.x; x < sector.x+sector.width; x++){
|
||||||
|
for(int y = sector.y; y < sector.y+sector.height; y++){
|
||||||
|
grid.put(x, y, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(expandX < 0) sector.x += expandX;
|
||||||
|
if(expandY < 0) sector.y += expandY;
|
||||||
|
|
||||||
|
sector.width += Math.abs(expandX);
|
||||||
|
sector.height += Math.abs(expandY);
|
||||||
|
|
||||||
|
if(checkExpansion) {
|
||||||
|
for (int x = sector.x; x < sector.x + sector.width; x++) {
|
||||||
|
for (int y = sector.y; y < sector.y + sector.height; y++) {
|
||||||
|
if (grid.get(x, y) != null && grid.get(x, y).complete) {
|
||||||
|
//if a completed sector is hit, expansion failed
|
||||||
|
if (expandX < 0) sector.x -= expandX;
|
||||||
|
if (expandY < 0) sector.y -= expandY;
|
||||||
|
sector.width -= Math.abs(expandX);
|
||||||
|
sector.height -= Math.abs(expandY);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add new sector spaces
|
||||||
|
for(int x = sector.x; x < sector.x+sector.width; x++){
|
||||||
|
for(int y = sector.y; y < sector.y+sector.height; y++){
|
||||||
|
grid.put(x, y, sector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//sector map data should now be shifted and generated
|
||||||
|
int shiftX = expandX < 0 ? -expandX*sectorSize : 0;
|
||||||
|
int shiftY = expandY < 0 ? -expandY*sectorSize : 0;
|
||||||
|
|
||||||
|
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||||
|
for(Entity entity : group.all()){
|
||||||
|
entity.set(entity.getX() + shiftX * tilesize, entity.getY() + shiftY * tilesize);
|
||||||
|
|
||||||
|
if(entity instanceof BaseUnit){
|
||||||
|
Tile spawner = ((BaseUnit) entity).getSpawner();
|
||||||
|
if(spawner == null) continue;
|
||||||
|
int i = spawner.packedPosition();
|
||||||
|
((BaseUnit) entity).setIntSpawner(world.transform(i, world.width(), world.height(), sector.width*sectorSize, shiftX, shiftY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!headless){
|
||||||
|
renderer.fog().setLoadingOffset(shiftX, shiftY);
|
||||||
|
}
|
||||||
|
|
||||||
|
//create *new* tile array
|
||||||
|
Tile[][] newTiles = new Tile[sector.width * sectorSize][sector.height * sectorSize];
|
||||||
|
|
||||||
|
//shift existing tiles to new array
|
||||||
|
for (int x = 0; x < (sector.width - Math.abs(expandX))*sectorSize; x++) {
|
||||||
|
for (int y = 0; y < (sector.height - Math.abs(expandY))*sectorSize; y++) {
|
||||||
|
Tile tile = world.rawTile(x, y);
|
||||||
|
tile.x = (short)(x + shiftX);
|
||||||
|
tile.y = (short)(y + shiftY);
|
||||||
|
newTiles[x + shiftX][y + shiftY] = tile;
|
||||||
|
tile.block().transformLinks(tile, world.width(), world.height(), sector.width*sectorSize, sector.height*sectorSize, shiftX, shiftY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
world.beginMapLoad(newTiles);
|
||||||
|
|
||||||
|
//create new tiles
|
||||||
|
for (int sx = 0; sx < sector.width; sx++) {
|
||||||
|
for (int sy = 0; sy < sector.height; sy++) {
|
||||||
|
//if this sector is a 'new sector (not part of the current save data...)
|
||||||
|
if(sx < -expandX || sy < -expandY || sx >= sector.width - expandX || sy >= sector.height - expandY){
|
||||||
|
GenResult result = new GenResult();
|
||||||
|
Array<Item> ores = getOres(sx + sector.x, sy + sector.y);
|
||||||
|
//gen tiles in sector
|
||||||
|
for (int x = 0; x < sectorSize; x++) {
|
||||||
|
for (int y = 0; y < sectorSize; y++) {
|
||||||
|
world.generator().generateTile(result, sx + sector.x, sy + sector.y, x, y, true, null, ores);
|
||||||
|
newTiles[sx * sectorSize + x][sy * sectorSize + y] = new Tile(x + sx * sectorSize, y + sy*sectorSize, result.floor.id, result.wall.id, (byte)0, (byte)0, result.elevation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//end loading of map
|
||||||
|
world.endMapLoad();
|
||||||
|
|
||||||
|
threads.runGraphics(() -> createTexture(sector));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<Item> getOres(int x, int y){
|
||||||
|
if(x == 0 && y == 0){
|
||||||
|
return Array.with(Items.copper);
|
||||||
|
}else if(x == 1 && y == 0){
|
||||||
|
return Array.with(Items.copper, Items.lead, Items.coal);
|
||||||
|
}
|
||||||
|
return Array.with(Items.copper);
|
||||||
|
}
|
||||||
|
|
||||||
/**Unlocks a sector. This shows nearby sectors.*/
|
/**Unlocks a sector. This shows nearby sectors.*/
|
||||||
public void completeSector(int x, int y){
|
public void completeSector(int x, int y){
|
||||||
createSector(x, y);
|
createSector(x, y);
|
||||||
Sector sector = get(x, y);
|
Sector sector = get(x, y);
|
||||||
sector.complete = true;
|
sector.complete = true;
|
||||||
|
|
||||||
for(GridPoint2 point : Edges.getEdges(sector.size)){
|
for(int sx = 0; sx < sector.width + 2; sx++){
|
||||||
createSector(sector.x + point.x, sector.y + point.y);
|
for(int sy = 0; sy < sector.height + 2; sy++){
|
||||||
|
if((sx == 0 || sy == 0 || sx == sector.width + 1 || sy == sector.height + 1) &&
|
||||||
|
!((sx == 0 && sy == 0)
|
||||||
|
|| (sx == 0 && sy == sector.height+1)
|
||||||
|
|| (sx == sector.width+1 && sy == 0)
|
||||||
|
|| (sx == sector.width+1 && sy == sector.height+1))){
|
||||||
|
createSector(sector.x + sx - 1, sector.y + sy - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Creates a sector at a location if it is not present, but does not unlock it.*/
|
/**Creates a sector at a location if it is not present, but does not unlock it.*/
|
||||||
public void createSector(int x, int y){
|
public void createSector(int x, int y){
|
||||||
boolean isLarge = Mathf.randomSeed(3+Bits.packInt((short)round2(x), (short)round2(y))) < sectorLargeChance;
|
|
||||||
|
|
||||||
if(isLarge){
|
|
||||||
x = round2(x);
|
|
||||||
y = round2(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(grid.containsKey(x, y)) return;
|
if(grid.containsKey(x, y)) return;
|
||||||
|
|
||||||
@@ -95,11 +226,11 @@ public class Sectors{
|
|||||||
sector.x = (short)x;
|
sector.x = (short)x;
|
||||||
sector.y = (short)y;
|
sector.y = (short)y;
|
||||||
sector.complete = false;
|
sector.complete = false;
|
||||||
sector.size = isLarge ? 2 : 1;
|
sector.width = sector.height = 1;
|
||||||
initSector(sector);
|
initSector(sector);
|
||||||
|
|
||||||
for(int cx = 0; cx < sector.size; cx++){
|
for(int cx = 0; cx < sector.width; cx++){
|
||||||
for(int cy = 0; cy < sector.size; cy++){
|
for(int cy = 0; cy < sector.height; cy++){
|
||||||
grid.put(x + cx, y + cy, sector);
|
grid.put(x + cx, y + cy, sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,8 +249,8 @@ public class Sectors{
|
|||||||
for(Sector sector : out){
|
for(Sector sector : out){
|
||||||
createTexture(sector);
|
createTexture(sector);
|
||||||
initSector(sector);
|
initSector(sector);
|
||||||
for(int cx = 0; cx < sector.size; cx++){
|
for(int cx = 0; cx < sector.width; cx++){
|
||||||
for(int cy = 0; cy < sector.size; cy++){
|
for(int cy = 0; cy < sector.height; cy++){
|
||||||
grid.put(sector.x + cx, sector.y + cy, sector);
|
grid.put(sector.x + cx, sector.y + cy, sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,16 +278,20 @@ public class Sectors{
|
|||||||
sector.difficulty = (int)(Mathf.dst(sector.x, sector.y));
|
sector.difficulty = (int)(Mathf.dst(sector.x, sector.y));
|
||||||
|
|
||||||
if(sector.difficulty == 0){
|
if(sector.difficulty == 0){
|
||||||
sector.missions.add(new WaveMission(10));
|
//TODO make specfic expansion sector have specific ores
|
||||||
|
sector.missions.addAll(TutorialSector.getMissions());
|
||||||
}else{
|
}else{
|
||||||
sector.missions.add(Mathf.randomSeed(sector.getSeed() + 1) < waveChance ? new WaveMission(Math.min(sector.difficulty*5 + Mathf.randomSeed(sector.getSeed(), 0, 3)*5, 100))
|
sector.missions.add(Mathf.randomSeed(sector.getSeed() + 1) < waveChance ? new WaveMission(Math.min(sector.difficulty*5 + Mathf.randomSeed(sector.getSeed(), 0, 3)*5, 100))
|
||||||
: new BattleMission());
|
: new BattleMission());
|
||||||
}
|
}
|
||||||
|
|
||||||
sector.spawns = sector.missions.first().getWaves(sector);
|
sector.spawns = new Array<>();
|
||||||
|
|
||||||
//add all ores for now since material differences aren't well handled yet
|
for(Mission mission : sector.missions){
|
||||||
sector.ores.addAll(Items.copper, Items.coal, Items.lead, Items.thorium, Items.titanium);
|
sector.spawns.addAll(mission.getWaves(sector));
|
||||||
|
}
|
||||||
|
|
||||||
|
//sector.ores.addAll(Items.copper);
|
||||||
|
|
||||||
//set starter items
|
//set starter items
|
||||||
if(sector.difficulty > 12){ //now with titanium
|
if(sector.difficulty > 12){ //now with titanium
|
||||||
@@ -169,20 +304,20 @@ public class Sectors{
|
|||||||
sector.startingItems = Array.with(new ItemStack(Items.copper, 700), new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 130));
|
sector.startingItems = Array.with(new ItemStack(Items.copper, 700), new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 130));
|
||||||
}else if(sector.difficulty > 1){ //more starter items for faster start
|
}else if(sector.difficulty > 1){ //more starter items for faster start
|
||||||
sector.startingItems = Array.with(new ItemStack(Items.copper, 400), new ItemStack(Items.lead, 100));
|
sector.startingItems = Array.with(new ItemStack(Items.copper, 400), new ItemStack(Items.lead, 100));
|
||||||
}else{ //base starting items to prevent grinding much
|
}else{ //empty default
|
||||||
sector.startingItems = Array.with(new ItemStack(Items.copper, 130));
|
sector.startingItems = Array.with();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int round2(int i){
|
|
||||||
if(i < 0) i --;
|
|
||||||
return i/2*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createTexture(Sector sector){
|
private void createTexture(Sector sector){
|
||||||
if(headless) return; //obviously not created or needed on server
|
if(headless) return; //obviously not created or needed on server
|
||||||
|
|
||||||
Pixmap pixmap = new Pixmap(sectorImageSize * sector.size, sectorImageSize * sector.size, Format.RGBA8888);
|
if(sector.texture != null){
|
||||||
|
sector.texture.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Pixmap pixmap = new Pixmap(sectorImageSize * sector.width, sectorImageSize * sector.height, Format.RGBA8888);
|
||||||
|
GenResult secResult = new GenResult();
|
||||||
|
|
||||||
for(int x = 0; x < pixmap.getWidth(); x++){
|
for(int x = 0; x < pixmap.getWidth(); x++){
|
||||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||||
@@ -190,8 +325,9 @@ public class Sectors{
|
|||||||
int toY = y * sectorSize / sectorImageSize;
|
int toY = y * sectorSize / sectorImageSize;
|
||||||
|
|
||||||
GenResult result = world.generator().generateTile(sector.x, sector.y, toX, toY, false);
|
GenResult result = world.generator().generateTile(sector.x, sector.y, toX, toY, false);
|
||||||
|
world.generator().generateTile(secResult, sector.x, sector.y, toX, toY + sectorSize / sectorImageSize, false, null, null);
|
||||||
|
|
||||||
int color = ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, (byte)0);
|
int color = ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, secResult.elevation > result.elevation ? (byte)(1 << 6) : (byte)0);
|
||||||
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color);
|
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
176
core/src/io/anuke/mindustry/maps/TutorialSector.java
Normal file
176
core/src/io/anuke/mindustry/maps/TutorialSector.java
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package io.anuke.mindustry.maps;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import io.anuke.mindustry.content.Items;
|
||||||
|
import io.anuke.mindustry.content.UnitTypes;
|
||||||
|
import io.anuke.mindustry.content.blocks.*;
|
||||||
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
|
import io.anuke.mindustry.maps.generation.Generation;
|
||||||
|
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
||||||
|
import io.anuke.mindustry.maps.missions.*;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.blocks.Floor;
|
||||||
|
import io.anuke.ucore.core.Events;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
|
/**Just a class for returning the list of tutorial missions.*/
|
||||||
|
public class TutorialSector{
|
||||||
|
private static int droneIndex;
|
||||||
|
|
||||||
|
public static Array<Mission> getMissions(){
|
||||||
|
//int x = sectorSize/2, y = sectorSize/2;
|
||||||
|
|
||||||
|
Array<Mission> missions = Array.with(
|
||||||
|
new ItemMission(Items.copper, 60).setMessage("$tutorial.begin"),
|
||||||
|
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 55, 62).setMessage("$tutorial.drill"),
|
||||||
|
|
||||||
|
new BlockLocMission(DistributionBlocks.conveyor, 57, 62, 0).setShowComplete(false).setMessage("$tutorial.conveyor"),
|
||||||
|
new BlockLocMission(DistributionBlocks.conveyor, 58, 62, 0).setShowComplete(false),
|
||||||
|
new BlockLocMission(DistributionBlocks.conveyor, 59, 62, 0).setShowComplete(false),
|
||||||
|
new BlockLocMission(DistributionBlocks.conveyor, 60, 62, 3).setShowComplete(false),
|
||||||
|
|
||||||
|
new ItemMission(Items.copper, 100).setMessage("$tutorial.morecopper"),
|
||||||
|
|
||||||
|
new BlockLocMission(TurretBlocks.duo, 56, 59).setMessage("$tutorial.turret"),
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 55, 60).setMessage("$tutorial.drillturret"),
|
||||||
|
|
||||||
|
new WaveMission(2).setMessage("$tutorial.waves"),
|
||||||
|
|
||||||
|
new ActionMission(() -> {
|
||||||
|
Timers.runTask(30f, () -> {
|
||||||
|
Runnable r = () -> {
|
||||||
|
Array<Item> ores = Array.with(Items.copper, Items.coal, Items.lead);
|
||||||
|
GenResult res = new GenResult();
|
||||||
|
for(int x = 0; x < world.width(); x++){
|
||||||
|
for(int y = 0; y < world.height(); y++){
|
||||||
|
Tile tile = world.tile(x, y);
|
||||||
|
world.generator().generateTile(res, 0, 0, x, y, true, null, ores);
|
||||||
|
if(!tile.hasCliffs()){
|
||||||
|
tile.setFloor((Floor) res.floor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Events.fire(new WorldLoadEvent());
|
||||||
|
};
|
||||||
|
|
||||||
|
if(headless){
|
||||||
|
ui.loadLogic(r);
|
||||||
|
}else{
|
||||||
|
threads.run(r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
new ItemMission(Items.lead, 150).setMessage("$tutorial.lead"),
|
||||||
|
new ItemMission(Items.copper, 250).setMessage("$tutorial.morecopper"),
|
||||||
|
|
||||||
|
new BlockLocMission(CraftingBlocks.smelter, 58, 69).setMessage("$tutorial.smelter"),
|
||||||
|
|
||||||
|
//drills for smelter
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 62, 86),
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 58, 89),
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 54, 68),
|
||||||
|
|
||||||
|
//conveyors for smelter
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 58, 88, 58, 70, 3),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 61, 86, 61, 70, 3),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 61, 69, 59, 69, 2),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 56, 69, 57, 69, 0),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 58, 68, 58, 63, 3),
|
||||||
|
new BlockLocMission(DistributionBlocks.junction, 58, 62, 0),
|
||||||
|
new BlockLocMission(DistributionBlocks.conveyor, 58, 61, 0),
|
||||||
|
|
||||||
|
new ItemMission(Items.densealloy, 20).setMessage("$tutorial.densealloy"),
|
||||||
|
|
||||||
|
new MarkerBlockMission(CraftingBlocks.siliconsmelter, 54, 52).setMessage("$tutorial.siliconsmelter"),
|
||||||
|
|
||||||
|
//coal line
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 47, 52).setMessage("$tutorial.silicondrill"),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 49, 52, 53, 52, 0),
|
||||||
|
|
||||||
|
//sand line
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 53, 49),
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 56, 49),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 55, 50, 55, 51, 1),
|
||||||
|
|
||||||
|
//silicon line
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 56, 53, 59, 53, 0),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 60, 53, 60, 58, 1),
|
||||||
|
|
||||||
|
new BlockLocMission(PowerBlocks.combustionGenerator, 49, 54).setMessage("$tutorial.generator"),
|
||||||
|
new BlockLocMission(ProductionBlocks.mechanicalDrill, 47, 54).setMessage("$tutorial.generatordrill"),
|
||||||
|
new BlockLocMission(PowerBlocks.powerNode, 52, 54).setMessage("$tutorial.node"),
|
||||||
|
new ConditionMission(Bundles.get("text.mission.linknode"), () -> world.tile(54, 52).entity != null && world.tile(54, 52).entity.power != null && world.tile(54, 52).entity.power.amount >= 0.01f)
|
||||||
|
.setMessage("$tutorial.nodelink"),
|
||||||
|
|
||||||
|
new ItemMission(Items.silicon, 70).setMessage("$tutorial.silicon"),
|
||||||
|
|
||||||
|
new BlockLocMission(UnitBlocks.daggerFactory, 64, 59).setMessage("$tutorial.daggerfactory"),
|
||||||
|
|
||||||
|
//silicon lines for dagger factory
|
||||||
|
new BlockLocMission(DistributionBlocks.router, 60, 57).setMessage("$tutorial.router"),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 61, 57, 63, 57, 0),
|
||||||
|
new LineBlockMission(DistributionBlocks.conveyor, 64, 57, 64, 58, 1),
|
||||||
|
|
||||||
|
//power for dagger factory
|
||||||
|
new BlockLocMission(PowerBlocks.powerNode, 57, 54),
|
||||||
|
new BlockLocMission(PowerBlocks.powerNode, 62, 54),
|
||||||
|
|
||||||
|
new UnitMission(UnitTypes.dagger).setMessage("$tutorial.dagger"),
|
||||||
|
new ExpandMission(1, 0){
|
||||||
|
@Override
|
||||||
|
public void onComplete(){
|
||||||
|
super.onComplete();
|
||||||
|
generateBase();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new BattleMission(){
|
||||||
|
public void generate(Generation gen){} //no
|
||||||
|
}.setMessage("$tutorial.battle")
|
||||||
|
);
|
||||||
|
|
||||||
|
//find drone marker mission
|
||||||
|
for(int i = 0; i < missions.size; i++){
|
||||||
|
if(missions.get(i) instanceof MarkerBlockMission){
|
||||||
|
droneIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return missions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean supressDrone(){
|
||||||
|
return world.getSector() != null && world.getSector().x == 0 && world.getSector().y == 0 && world.getSector().completedMissions < droneIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void generateBase(){
|
||||||
|
int x = sectorSize/2 + sectorSize, y = sectorSize/2;
|
||||||
|
world.setBlock(world.tile(x, y), StorageBlocks.core, waveTeam);
|
||||||
|
// world.setBlock(world.tile(x + 1, y + 2), TurretBlocks.duo, waveTeam);
|
||||||
|
//world.setBlock(world.tile(x + 1, y - 2), TurretBlocks.duo, waveTeam);
|
||||||
|
world.setBlock(world.tile(x - 1, y + 2), UnitBlocks.daggerFactory, waveTeam);
|
||||||
|
world.setBlock(world.tile(x - 1, y - 3), UnitBlocks.daggerFactory, waveTeam);
|
||||||
|
|
||||||
|
//fill turret ammo
|
||||||
|
//world.tile(x + 1, y + 2).block().handleStack(Items.copper, 1, world.tile(x + 1, y + 2), null);
|
||||||
|
//world.tile(x + 1, y - 2).block().handleStack(Items.copper, 1, world.tile(x + 1, y - 2), null);
|
||||||
|
|
||||||
|
//since placed() is not called here, add core manually
|
||||||
|
if(!state.teams.get(waveTeam).cores.contains(world.tile(x, y), true)){
|
||||||
|
state.teams.get(waveTeam).cores.add(world.tile(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MarkerBlockMission extends BlockLocMission{
|
||||||
|
public MarkerBlockMission(Block block, int x, int y){
|
||||||
|
super(block, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ public class FortressGenerator{
|
|||||||
gen.setBlock(enemyX, enemyY, StorageBlocks.core, team);
|
gen.setBlock(enemyX, enemyY, StorageBlocks.core, team);
|
||||||
|
|
||||||
float difficultyScl = Mathf.clamp(gen.sector.difficulty / 20f + gen.random.range(1f/2f), 0f, 0.9999f);
|
float difficultyScl = Mathf.clamp(gen.sector.difficulty / 20f + gen.random.range(1f/2f), 0f, 0.9999f);
|
||||||
int coreDst = FortressGenerator.coreDst*gen.sector.size;
|
int coreDst = FortressGenerator.coreDst*gen.sector.width;
|
||||||
|
|
||||||
Array<Block> turrets = find(b -> b instanceof ItemTurret);
|
Array<Block> turrets = find(b -> b instanceof ItemTurret);
|
||||||
Array<Block> powerTurrets = find(b -> b instanceof PowerTurret);
|
Array<Block> powerTurrets = find(b -> b instanceof PowerTurret);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.badlogic.gdx.utils.ObjectMap;
|
|||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.content.Items;
|
||||||
import io.anuke.mindustry.content.blocks.Blocks;
|
import io.anuke.mindustry.content.blocks.Blocks;
|
||||||
import io.anuke.mindustry.content.blocks.OreBlocks;
|
import io.anuke.mindustry.content.blocks.OreBlocks;
|
||||||
import io.anuke.mindustry.content.blocks.StorageBlocks;
|
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.maps.MapTileData;
|
import io.anuke.mindustry.maps.MapTileData;
|
||||||
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
|
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
|
||||||
@@ -21,12 +20,12 @@ import io.anuke.mindustry.world.blocks.Floor;
|
|||||||
import io.anuke.mindustry.world.blocks.OreBlock;
|
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||||
import io.anuke.ucore.noise.RidgedPerlin;
|
import io.anuke.ucore.noise.RidgedPerlin;
|
||||||
import io.anuke.ucore.noise.Simplex;
|
import io.anuke.ucore.noise.Simplex;
|
||||||
import io.anuke.ucore.noise.VoronoiNoise;
|
|
||||||
import io.anuke.ucore.util.Geometry;
|
import io.anuke.ucore.util.Geometry;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
import io.anuke.ucore.util.SeedRandom;
|
import io.anuke.ucore.util.SeedRandom;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.sectorSize;
|
||||||
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
|
|
||||||
public class WorldGenerator{
|
public class WorldGenerator{
|
||||||
@@ -37,15 +36,12 @@ public class WorldGenerator{
|
|||||||
private Simplex sim2 = new Simplex(baseSeed + 1);
|
private Simplex sim2 = new Simplex(baseSeed + 1);
|
||||||
private Simplex sim3 = new Simplex(baseSeed + 2);
|
private Simplex sim3 = new Simplex(baseSeed + 2);
|
||||||
private RidgedPerlin rid = new RidgedPerlin(baseSeed + 4, 1);
|
private RidgedPerlin rid = new RidgedPerlin(baseSeed + 4, 1);
|
||||||
private VoronoiNoise vn = new VoronoiNoise(baseSeed + 2, (short)0);
|
|
||||||
private SeedRandom random = new SeedRandom(baseSeed + 3);
|
private SeedRandom random = new SeedRandom(baseSeed + 3);
|
||||||
|
|
||||||
private GenResult result = new GenResult();
|
private GenResult result = new GenResult();
|
||||||
private ObjectMap<Block, Block> decoration;
|
private ObjectMap<Block, Block> decoration;
|
||||||
|
|
||||||
public WorldGenerator(){
|
public WorldGenerator(){
|
||||||
vn.setUseDistance(true);
|
|
||||||
|
|
||||||
decoration = Mathf.map(
|
decoration = Mathf.map(
|
||||||
Blocks.grass, Blocks.shrub,
|
Blocks.grass, Blocks.shrub,
|
||||||
Blocks.stone, Blocks.rock,
|
Blocks.stone, Blocks.rock,
|
||||||
@@ -73,6 +69,11 @@ public class WorldGenerator{
|
|||||||
generateOres(tiles, seed, genOres, null);
|
generateOres(tiles, seed, genOres, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**'Prepares' a tile array by:<br>
|
||||||
|
* - setting up multiblocks<br>
|
||||||
|
* - updating cliff data<br>
|
||||||
|
* - removing ores on cliffs<br>
|
||||||
|
* Usually used before placing structures on a tile array.*/
|
||||||
public void prepareTiles(Tile[][] tiles){
|
public void prepareTiles(Tile[][] tiles){
|
||||||
|
|
||||||
//find multiblocks
|
//find multiblocks
|
||||||
@@ -82,14 +83,8 @@ public class WorldGenerator{
|
|||||||
for(int y = 0; y < tiles[0].length; y++){
|
for(int y = 0; y < tiles[0].length; y++){
|
||||||
Tile tile = tiles[x][y];
|
Tile tile = tiles[x][y];
|
||||||
|
|
||||||
Team team = tile.getTeam();
|
if(tile.block().isMultiblock()){
|
||||||
|
multiblocks.add(tile.packedPosition());
|
||||||
if(tile.block() == StorageBlocks.core){
|
|
||||||
state.teams.get(team).cores.add(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tiles[x][y].block().isMultiblock()){
|
|
||||||
multiblocks.add(tiles[x][y].packedPosition());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,6 +129,7 @@ public class WorldGenerator{
|
|||||||
tile.setBlock(Blocks.air);
|
tile.setBlock(Blocks.air);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//remove ore veins on cliffs
|
||||||
if(tile.floor() instanceof OreBlock && tile.hasCliffs()){
|
if(tile.floor() instanceof OreBlock && tile.hasCliffs()){
|
||||||
tile.setFloor(((OreBlock)tile.floor()).base);
|
tile.setFloor(((OreBlock)tile.floor()).base);
|
||||||
}
|
}
|
||||||
@@ -190,11 +186,12 @@ public class WorldGenerator{
|
|||||||
SeedRandom rnd = new SeedRandom(sector.getSeed());
|
SeedRandom rnd = new SeedRandom(sector.getSeed());
|
||||||
Generation gena = new Generation(sector, tiles, tiles.length, tiles[0].length, rnd);
|
Generation gena = new Generation(sector, tiles, tiles.length, tiles[0].length, rnd);
|
||||||
Array<GridPoint2> spawnpoints = sector.currentMission().getSpawnPoints(gena);
|
Array<GridPoint2> spawnpoints = sector.currentMission().getSpawnPoints(gena);
|
||||||
|
Array<Item> ores = world.sectors().getOres(sector.x, sector.y);
|
||||||
|
|
||||||
for(int x = 0; x < width; x++){
|
for(int x = 0; x < width; x++){
|
||||||
for(int y = 0; y < height; y++){
|
for(int y = 0; y < height; y++){
|
||||||
GenResult result = generateTile(this.result, sector.x, sector.y, x, y, true, spawnpoints);
|
GenResult result = generateTile(this.result, sector.x, sector.y, x, y, true, spawnpoints, ores);
|
||||||
Tile tile = new Tile(x, y, (byte)result.floor.id, (byte)result.wall.id, (byte)0, (byte)0, result.elevation);
|
Tile tile = new Tile(x, y, result.floor.id, result.wall.id, (byte)0, (byte)0, result.elevation);
|
||||||
tiles[x][y] = tile;
|
tiles[x][y] = tile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,8 +215,6 @@ public class WorldGenerator{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateOres(tiles, sector.getSeed(), true, sector.ores);
|
|
||||||
|
|
||||||
for(int x = 0; x < tiles.length; x++){
|
for(int x = 0; x < tiles.length; x++){
|
||||||
for(int y = 0; y < tiles[0].length; y++){
|
for(int y = 0; y < tiles[0].length; y++){
|
||||||
Tile tile = tiles[x][y];
|
Tile tile = tiles[x][y];
|
||||||
@@ -242,10 +237,21 @@ public class WorldGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GenResult generateTile(int sectorX, int sectorY, int localX, int localY, boolean detailed){
|
public GenResult generateTile(int sectorX, int sectorY, int localX, int localY, boolean detailed){
|
||||||
return generateTile(result, sectorX, sectorY, localX, localY, detailed, null);
|
return generateTile(result, sectorX, sectorY, localX, localY, detailed, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenResult generateTile(GenResult result, int sectorX, int sectorY, int localX, int localY, boolean detailed, Array<GridPoint2> spawnpoints){
|
/**
|
||||||
|
* Gets the generation result from a specific sector at specific coordinates.
|
||||||
|
* @param result where to put the generation results
|
||||||
|
* @param sectorX X of the sector in terms of sector coordinates
|
||||||
|
* @param sectorY Y of the sector in terms of sector coordinates
|
||||||
|
* @param localX X in terms of local sector tile coordinates
|
||||||
|
* @param localY Y in terms of local sector tile coordinates
|
||||||
|
* @param detailed whether the tile result is 'detailed' (e.g. previews should not be detailed)
|
||||||
|
* @param spawnpoints list of player spawnpoints, can be null
|
||||||
|
* @return the GenResult passed in with its values modified
|
||||||
|
*/
|
||||||
|
public GenResult generateTile(GenResult result, int sectorX, int sectorY, int localX, int localY, boolean detailed, Array<GridPoint2> spawnpoints, Array<Item> ores){
|
||||||
int x = sectorX * sectorSize + localX + Short.MAX_VALUE;
|
int x = sectorX * sectorSize + localX + Short.MAX_VALUE;
|
||||||
int y = sectorY * sectorSize + localY + Short.MAX_VALUE;
|
int y = sectorY * sectorSize + localY + Short.MAX_VALUE;
|
||||||
|
|
||||||
@@ -255,8 +261,8 @@ public class WorldGenerator{
|
|||||||
double ridge = rid.getValue(x, y, 1f / 400f);
|
double ridge = rid.getValue(x, y, 1f / 400f);
|
||||||
double iceridge = rid.getValue(x+99999, y, 1f / 300f) + sim3.octaveNoise2D(2, 1f, 1f/14f, x, y)/11f;
|
double iceridge = rid.getValue(x+99999, y, 1f / 300f) + sim3.octaveNoise2D(2, 1f, 1f/14f, x, y)/11f;
|
||||||
double elevation = elevationOf(x, y, detailed);
|
double elevation = elevationOf(x, y, detailed);
|
||||||
double temp = vn.noise(x, y, 1f / 300f) * sim3.octaveNoise2D(detailed ? 2 : 1, 1, 1f / 13f, x, y)/13f
|
double temp =
|
||||||
+ sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x, y);
|
+ sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x - 120, y);
|
||||||
|
|
||||||
int lerpDst = 20;
|
int lerpDst = 20;
|
||||||
lerpDst *= lerpDst;
|
lerpDst *= lerpDst;
|
||||||
@@ -313,6 +319,19 @@ public class WorldGenerator{
|
|||||||
wall = decoration.get(floor);
|
wall = decoration.get(floor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ores != null && ((Floor) floor).hasOres){
|
||||||
|
int offsetX = x - 4, offsetY = y + 23;
|
||||||
|
for(int i = ores.size - 1; i >= 0; i--){
|
||||||
|
Item entry = ores.get(i);
|
||||||
|
if(
|
||||||
|
Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY)) > 0.23f &&
|
||||||
|
Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY)) > 0.32f){
|
||||||
|
floor = OreBlocks.get(floor, entry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.wall = wall;
|
result.wall = wall;
|
||||||
result.floor = floor;
|
result.floor = floor;
|
||||||
result.elevation = (byte) Math.max(elevation, 0);
|
result.elevation = (byte) Math.max(elevation, 0);
|
||||||
@@ -321,7 +340,7 @@ public class WorldGenerator{
|
|||||||
|
|
||||||
double elevationOf(int x, int y, boolean detailed){
|
double elevationOf(int x, int y, boolean detailed){
|
||||||
double ridge = rid.getValue(x, y, 1f / 400f);
|
double ridge = rid.getValue(x, y, 1f / 400f);
|
||||||
return sim.octaveNoise2D(detailed ? 7 : 4, 0.62, 1f / 800, x, y) * 6.1 - 1 - ridge;
|
return sim.octaveNoise2D(detailed ? 7 : 5, 0.62, 1f / 800, x, y) * 6.1 - 1 - ridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GenResult{
|
public static class GenResult{
|
||||||
|
|||||||
32
core/src/io/anuke/mindustry/maps/missions/ActionMission.java
Normal file
32
core/src/io/anuke/mindustry/maps/missions/ActionMission.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.threads;
|
||||||
|
|
||||||
|
/**A mission which simply runs a single action and is completed instantly.*/
|
||||||
|
public class ActionMission extends Mission{
|
||||||
|
protected Runnable runner;
|
||||||
|
|
||||||
|
public ActionMission(Runnable runner){
|
||||||
|
this.runner = runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionMission(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(){
|
||||||
|
threads.run(runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
return Bundles.get("text.loading");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,15 +7,10 @@ import io.anuke.mindustry.game.GameMode;
|
|||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.maps.generation.FortressGenerator;
|
import io.anuke.mindustry.maps.generation.FortressGenerator;
|
||||||
import io.anuke.mindustry.maps.generation.Generation;
|
import io.anuke.mindustry.maps.generation.Generation;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
public class BattleMission implements Mission{
|
public class BattleMission extends Mission{
|
||||||
private final static int coreX = 60, coreY = 60;
|
private final static int coreX = 60, coreY = 60;
|
||||||
@Override
|
|
||||||
public void display(Table table){
|
|
||||||
table.add("$text.mission.battle");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GameMode getMode(){
|
public GameMode getMode(){
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.graphics.Draw;
|
||||||
|
import io.anuke.ucore.graphics.Lines;
|
||||||
|
import io.anuke.ucore.util.Angles;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.players;
|
||||||
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
|
public class BlockLocMission extends Mission{
|
||||||
|
private final Block block;
|
||||||
|
private final int x, y, rotation;
|
||||||
|
|
||||||
|
public BlockLocMission(Block block, int x, int y, int rotation){
|
||||||
|
this.block = block;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockLocMission(Block block, int x, int y){
|
||||||
|
this.block = block;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.rotation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawOverlay(){
|
||||||
|
Lines.stroke(2f);
|
||||||
|
|
||||||
|
Draw.color(Palette.accent.r * 0.8f,Palette.accent.g * 0.8f,Palette.accent.b * 0.8f);
|
||||||
|
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1f, block.size * tilesize/2f + 1f+ Mathf.absin(Timers.time(), 6f, 2f));
|
||||||
|
|
||||||
|
Draw.color(Palette.accent);
|
||||||
|
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize/2f + 1f+ Mathf.absin(Timers.time(), 6f, 2f));
|
||||||
|
|
||||||
|
|
||||||
|
if(block.rotate){
|
||||||
|
Draw.colorl(0.4f);
|
||||||
|
Draw.rect("icon-arrow", x * tilesize + block.offset(), y * tilesize + block.offset() - 1f, rotation*90);
|
||||||
|
Draw.colorl(0.6f);
|
||||||
|
Draw.rect("icon-arrow", x * tilesize + block.offset(), y * tilesize + block.offset(), rotation*90);
|
||||||
|
}
|
||||||
|
|
||||||
|
float rot = players[0].angleTo(x * tilesize + block.offset(), y * tilesize + block.offset());
|
||||||
|
float len = 12f;
|
||||||
|
|
||||||
|
Draw.color(Palette.accent.r * 0.8f,Palette.accent.g * 0.8f,Palette.accent.b * 0.8f);
|
||||||
|
Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len), rot);
|
||||||
|
Draw.color(Palette.accent);
|
||||||
|
Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len) + 1f, rot);
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
return world.tile(x, y).block() == block && (!block.rotate || world.tile(x,y).getRotation() == rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
return Bundles.format("text.mission.block", block.formalName);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
core/src/io/anuke/mindustry/maps/missions/BlockMission.java
Normal file
55
core/src/io/anuke/mindustry/maps/missions/BlockMission.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
||||||
|
import io.anuke.mindustry.game.GameMode;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.ucore.core.Events;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.defaultTeam;
|
||||||
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
|
/**A mission in which the player must place a block.*/
|
||||||
|
@Deprecated
|
||||||
|
public class BlockMission extends Mission{
|
||||||
|
private final Block block;
|
||||||
|
private boolean complete;
|
||||||
|
|
||||||
|
static{
|
||||||
|
Events.on(BlockBuildEvent.class, event -> {
|
||||||
|
if(world.getSector() != null && event.team == defaultTeam){
|
||||||
|
Mission mission = world.getSector().currentMission();
|
||||||
|
if(mission instanceof BlockMission){
|
||||||
|
BlockMission block = (BlockMission)world.getSector().currentMission();
|
||||||
|
if(block.block == event.tile.block()){
|
||||||
|
block.complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockMission(Block block){
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset(){
|
||||||
|
complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
return complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
return Bundles.format("text.mission.block", block.formalName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameMode getMode(){
|
||||||
|
return GameMode.noWaves;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.ucore.function.BooleanProvider;
|
||||||
|
|
||||||
|
public class ConditionMission extends Mission{
|
||||||
|
private final BooleanProvider complete;
|
||||||
|
private final String display;
|
||||||
|
|
||||||
|
public ConditionMission(String display, BooleanProvider complete){
|
||||||
|
this.complete = complete;
|
||||||
|
this.display = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
return complete.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
core/src/io/anuke/mindustry/maps/missions/ExpandMission.java
Normal file
37
core/src/io/anuke/mindustry/maps/missions/ExpandMission.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
|
/**An action mission which simply expands the sector.*/
|
||||||
|
public class ExpandMission extends ActionMission{
|
||||||
|
private boolean done = false;
|
||||||
|
|
||||||
|
public ExpandMission(int expandX, int expandY){
|
||||||
|
runner = () -> {
|
||||||
|
if(headless){
|
||||||
|
world.sectors().expandSector(world.getSector(), expandX, expandY);
|
||||||
|
done = true;
|
||||||
|
}else{
|
||||||
|
ui.loadLogic(() -> {
|
||||||
|
world.sectors().expandSector(world.getSector(), expandX, expandY);
|
||||||
|
done = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBegin(){
|
||||||
|
runner.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(){
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
core/src/io/anuke/mindustry/maps/missions/ItemMission.java
Normal file
42
core/src/io/anuke/mindustry/maps/missions/ItemMission.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.state;
|
||||||
|
|
||||||
|
/**A mission that is completed when the player obtains items in their core.*/
|
||||||
|
public class ItemMission extends Mission{
|
||||||
|
private final Item item;
|
||||||
|
private final int amount;
|
||||||
|
|
||||||
|
public ItemMission(Item item, int amount){
|
||||||
|
this.item = item;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
for(Tile tile : state.teams.get(Vars.defaultTeam).cores){
|
||||||
|
if(tile.entity.items.has(item, amount)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
TileEntity core = Vars.players[0].getClosestCore();
|
||||||
|
if(core == null) return "imminent doom";
|
||||||
|
return Bundles.format("text.mission.resource", item.localizedName(), core.items.get(item), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String menuDisplayString(){
|
||||||
|
return Bundles.format("text.mission.resource.menu", item.localizedName(), amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.Bresenham2;
|
||||||
|
import com.badlogic.gdx.math.GridPoint2;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
|
||||||
|
public class LineBlockMission extends Mission{
|
||||||
|
private Array<BlockLocMission> points = new Array<>();
|
||||||
|
private int completeIndex;
|
||||||
|
|
||||||
|
public LineBlockMission(Block block, int x1, int y1, int x2, int y2, int rotation){
|
||||||
|
Array<GridPoint2> points = new Bresenham2().line(x1, y1, x2, y2);
|
||||||
|
for(GridPoint2 point : points){
|
||||||
|
this.points.add(new BlockLocMission(block, point.x, point.y, rotation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
while(completeIndex < points.size && points.get(completeIndex).isComplete()){
|
||||||
|
completeIndex ++;
|
||||||
|
}
|
||||||
|
return completeIndex >= points.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawOverlay(){
|
||||||
|
if(completeIndex < points.size){
|
||||||
|
points.get(completeIndex).drawOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset(){
|
||||||
|
completeIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
if(completeIndex < points.size){
|
||||||
|
return points.get(completeIndex).displayString();
|
||||||
|
}
|
||||||
|
return points.first().displayString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
|
||||||
|
/**A mission that just displays some text.*/
|
||||||
|
public class MessageMission extends ActionMission{
|
||||||
|
|
||||||
|
public MessageMission(String text){
|
||||||
|
super(() -> {
|
||||||
|
if(!Vars.headless){
|
||||||
|
Vars.ui.showInfo(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,25 +8,91 @@ import io.anuke.mindustry.game.SpawnGroup;
|
|||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.maps.Sector;
|
import io.anuke.mindustry.maps.Sector;
|
||||||
import io.anuke.mindustry.maps.generation.Generation;
|
import io.anuke.mindustry.maps.generation.Generation;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
public interface Mission{
|
import static io.anuke.mindustry.Vars.headless;
|
||||||
boolean isComplete();
|
import static io.anuke.mindustry.Vars.ui;
|
||||||
String displayString();
|
|
||||||
GameMode getMode();
|
|
||||||
void display(Table table);
|
|
||||||
|
|
||||||
default Array<SpawnGroup> getWaves(Sector sector){
|
public abstract class Mission{
|
||||||
|
private String extraMessage;
|
||||||
|
private boolean showComplete =true;
|
||||||
|
|
||||||
|
public abstract boolean isComplete();
|
||||||
|
|
||||||
|
/**Returns the string that is displayed in-game near the menu.*/
|
||||||
|
public abstract String displayString();
|
||||||
|
|
||||||
|
/**Returns the info string displayed in the sector dialog (menu)*/
|
||||||
|
public String menuDisplayString(){
|
||||||
|
return displayString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameMode getMode(){
|
||||||
|
return GameMode.noWaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Sets the message displayed on mission begin. Returns this mission for chaining.*/
|
||||||
|
public Mission setMessage(String message){
|
||||||
|
this.extraMessage = message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mission setShowComplete(boolean complete){
|
||||||
|
this.showComplete = complete;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Draw mission overlay.*/
|
||||||
|
public void drawOverlay(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Shows the unique sector message.*/
|
||||||
|
public void showMessage(){
|
||||||
|
if(!headless && extraMessage != null){
|
||||||
|
ui.hudfrag.showTextDialog(extraMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasMessage(){
|
||||||
|
return extraMessage != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBegin(){
|
||||||
|
Timers.runTask(60f, this::showMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onComplete(){
|
||||||
|
if(showComplete && !headless){
|
||||||
|
ui.hudfrag.showText("[LIGHT_GRAY]"+menuDisplayString() + ":\n" + Bundles.get("text.mission.complete"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void display(Table table){
|
||||||
|
table.add(displayString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<SpawnGroup> getWaves(Sector sector){
|
||||||
return new Array<>();
|
return new Array<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
default Array<GridPoint2> getSpawnPoints(Generation gen){
|
public Array<GridPoint2> getSpawnPoints(Generation gen){
|
||||||
return Array.with();
|
return Array.with();
|
||||||
}
|
}
|
||||||
|
|
||||||
default void generate(Generation gen){}
|
public void generate(Generation gen){}
|
||||||
|
|
||||||
default void generateCoreAt(Generation gen, int coreX, int coreY, Team team){
|
public void generateCoreAt(Generation gen, int coreX, int coreY, Team team){
|
||||||
gen.tiles[coreX][coreY].setBlock(StorageBlocks.core);
|
gen.tiles[coreX][coreY].setBlock(StorageBlocks.core);
|
||||||
gen.tiles[coreX][coreY].setTeam(team);
|
gen.tiles[coreX][coreY].setTeam(team);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package io.anuke.mindustry.maps.missions;
|
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
|
||||||
import io.anuke.mindustry.game.GameMode;
|
|
||||||
import io.anuke.mindustry.type.Item;
|
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
|
||||||
import io.anuke.ucore.util.Bundles;
|
|
||||||
|
|
||||||
public class ResourceMission implements Mission{
|
|
||||||
private final Item item;
|
|
||||||
private final int amount;
|
|
||||||
|
|
||||||
public ResourceMission(Item item, int amount){
|
|
||||||
this.item = item;
|
|
||||||
this.amount = amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void display(Table table){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GameMode getMode(){
|
|
||||||
return GameMode.waves;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isComplete(){
|
|
||||||
return Vars.state.teams.get(Vars.defaultTeam).cores.first().entity.items.has(item, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String displayString(){
|
|
||||||
return Bundles.format("text.mission.resource", item.localizedName(), amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
29
core/src/io/anuke/mindustry/maps/missions/UnitMission.java
Normal file
29
core/src/io/anuke/mindustry/maps/missions/UnitMission.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
|
import io.anuke.mindustry.entities.units.UnitType;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
|
public class UnitMission extends Mission{
|
||||||
|
private final UnitType type;
|
||||||
|
|
||||||
|
public UnitMission(UnitType type){
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
for(BaseUnit unit : Vars.unitGroups[Vars.defaultTeam.ordinal()].all()){
|
||||||
|
if(unit.getType() == type){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
return Bundles.format("text.mission.unit", type.localizedName());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package io.anuke.mindustry.maps.missions;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.game.GameMode;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
|
||||||
|
public class VictoryMission extends Mission{
|
||||||
|
@Override
|
||||||
|
public boolean isComplete(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String displayString(){
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameMode getMode(){
|
||||||
|
return GameMode.victory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void display(Table table){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,15 +2,20 @@ package io.anuke.mindustry.maps.missions;
|
|||||||
|
|
||||||
import com.badlogic.gdx.math.GridPoint2;
|
import com.badlogic.gdx.math.GridPoint2;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.game.GameMode;
|
||||||
|
import io.anuke.mindustry.game.SpawnGroup;
|
||||||
|
import io.anuke.mindustry.game.Team;
|
||||||
|
import io.anuke.mindustry.game.Waves;
|
||||||
import io.anuke.mindustry.maps.Sector;
|
import io.anuke.mindustry.maps.Sector;
|
||||||
import io.anuke.mindustry.maps.generation.Generation;
|
import io.anuke.mindustry.maps.generation.Generation;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.state;
|
import static io.anuke.mindustry.Vars.state;
|
||||||
|
import static io.anuke.mindustry.Vars.waveTeam;
|
||||||
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class WaveMission implements Mission{
|
public class WaveMission extends Mission{
|
||||||
private final int target;
|
private final int target;
|
||||||
|
|
||||||
public WaveMission(int target){
|
public WaveMission(int target){
|
||||||
@@ -29,8 +34,10 @@ public class WaveMission implements Mission{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void display(Table table){
|
public void onBegin(){
|
||||||
table.add(Bundles.format("text.mission.wave", target));
|
super.onBegin();
|
||||||
|
|
||||||
|
world.pathfinder().activateTeamPath(waveTeam);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -40,12 +47,29 @@ public class WaveMission implements Mission{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String displayString(){
|
public String displayString(){
|
||||||
return Bundles.format("text.mission.wave", target);
|
return state.wave > target ?
|
||||||
|
Bundles.format(
|
||||||
|
Vars.unitGroups[Vars.waveTeam.ordinal()].size() > 1 ?
|
||||||
|
"text.mission.wave.enemies" :
|
||||||
|
"text.mission.wave.enemy", target, target, Vars.unitGroups[Vars.waveTeam.ordinal()].size()) :
|
||||||
|
Bundles.format("text.mission.wave", state.wave, target, (int)(state.wavetime/60));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String menuDisplayString(){
|
||||||
|
return Bundles.format("text.mission.wave.menu", target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
if(state.wave > target){
|
||||||
|
state.mode = GameMode.noWaves;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete(){
|
public boolean isComplete(){
|
||||||
return state.wave >= target;
|
return state.wave > target && Vars.unitGroups[Vars.waveTeam.ordinal()].size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class Recipe extends UnlockableContent{
|
|||||||
public GameMode mode;
|
public GameMode mode;
|
||||||
public boolean isPad;
|
public boolean isPad;
|
||||||
public boolean hidden;
|
public boolean hidden;
|
||||||
|
public boolean alwaysUnlocked;
|
||||||
|
|
||||||
private UnlockableContent[] dependencies;
|
private UnlockableContent[] dependencies;
|
||||||
private Block[] blockDependencies;
|
private Block[] blockDependencies;
|
||||||
@@ -58,15 +59,16 @@ public class Recipe extends UnlockableContent{
|
|||||||
* Returns unlocked recipes in a category.
|
* Returns unlocked recipes in a category.
|
||||||
* Do not call on the server backend, as unlocking does not exist!
|
* Do not call on the server backend, as unlocking does not exist!
|
||||||
*/
|
*/
|
||||||
public static void getUnlockedByCategory(Category category, Array<Recipe> r){
|
public static void getUnlockedByCategory(Category category, Array<Recipe> arr){
|
||||||
if(headless){
|
if(headless){
|
||||||
throw new RuntimeException("Not implemented on the headless backend!");
|
throw new RuntimeException("Not implemented on the headless backend!");
|
||||||
}
|
}
|
||||||
|
|
||||||
r.clear();
|
arr.clear();
|
||||||
for(Recipe recipe : content.recipes()){
|
for(Recipe r : content.recipes()){
|
||||||
if(recipe.category == category && (control.database().isUnlocked(recipe))){
|
if(r.category == category && (control.database().isUnlocked(r)) &&
|
||||||
r.add(recipe);
|
!((r.mode != null && r.mode != state.mode) || (r.desktopOnly && mobile) || (r.isPad && !state.mode.showPads))){
|
||||||
|
arr.add(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,9 +109,15 @@ public class Recipe extends UnlockableContent{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Recipe setAlwaysUnlocked(boolean unlocked){
|
||||||
|
this.alwaysUnlocked = unlocked;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean alwaysUnlocked(){
|
public boolean alwaysUnlocked(){
|
||||||
return hidden;
|
return alwaysUnlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.graphics.Pixmap;
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
||||||
|
import io.anuke.mindustry.content.Items;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.world.ColorMapper;
|
import io.anuke.mindustry.world.ColorMapper;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.scene.Element;
|
import io.anuke.ucore.scene.Element;
|
||||||
@@ -20,6 +23,7 @@ import static io.anuke.mindustry.Vars.sectorSize;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class GenViewDialog extends FloatingDialog{
|
public class GenViewDialog extends FloatingDialog{
|
||||||
|
Array<Item> ores = Array.with(Items.copper, Items.lead, Items.coal);
|
||||||
|
|
||||||
public GenViewDialog(){
|
public GenViewDialog(){
|
||||||
super("generate view");
|
super("generate view");
|
||||||
@@ -81,7 +85,7 @@ public class GenViewDialog extends FloatingDialog{
|
|||||||
Pixmap pixmap = new Pixmap(sectorSize, sectorSize, Format.RGBA8888);
|
Pixmap pixmap = new Pixmap(sectorSize, sectorSize, Format.RGBA8888);
|
||||||
for(int i = 0; i < sectorSize; i++){
|
for(int i = 0; i < sectorSize; i++){
|
||||||
for(int j = 0; j < sectorSize; j++){
|
for(int j = 0; j < sectorSize; j++){
|
||||||
world.generator().generateTile(result, wx, wy, i, j, true, null);
|
world.generator().generateTile(result, wx, wy, i, j, true, null, ores);
|
||||||
pixmap.drawPixel(i, sectorSize - 1 - j, ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, (byte)0));
|
pixmap.drawPixel(i, sectorSize - 1 - j, ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, (byte)0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class SaveDialog extends LoadDialog{
|
|||||||
slots.row();
|
slots.row();
|
||||||
slots.addImageTextButton("$text.save.new", "icon-add", "clear", 14 * 3, () ->
|
slots.addImageTextButton("$text.save.new", "icon-add", "clear", 14 * 3, () ->
|
||||||
ui.showTextInput("$text.save", "$text.save.newslot", "", text -> {
|
ui.showTextInput("$text.save", "$text.save.newslot", "", text -> {
|
||||||
ui.loadAnd("$text.saving", () -> {
|
ui.loadGraphics("$text.saving", () -> {
|
||||||
control.getSaves().addSave(text);
|
control.getSaves().addSave(text);
|
||||||
threads.runGraphics(() -> threads.run(() -> threads.runGraphics(this::setup)));
|
threads.runGraphics(() -> threads.run(() -> threads.runGraphics(this::setup)));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ public class SectorsDialog extends FloatingDialog{
|
|||||||
(selected.hasSave() ? " [accent]/[white] " + Bundles.format("text.sector.time", selected.getSave().getPlayTime()) : ""))));
|
(selected.hasSave() ? " [accent]/[white] " + Bundles.format("text.sector.time", selected.getSave().getPlayTime()) : ""))));
|
||||||
content().row();
|
content().row();
|
||||||
content().label(() -> Bundles.format("text.mission", selected == null || selected.completedMissions >= selected.missions.size
|
content().label(() -> Bundles.format("text.mission", selected == null || selected.completedMissions >= selected.missions.size
|
||||||
? Bundles.get("text.none") : selected.missions.get(selected.completedMissions).displayString())
|
? Bundles.get("text.none") : selected.missions.get(selected.completedMissions).menuDisplayString())
|
||||||
+ "[WHITE] " + (selected == null ? "" : Bundles.format("text.save.difficulty", "[LIGHT_GRAY]" + selected.getDifficulty().toString())));
|
+ "[WHITE] " /*+ (selected == null ? "" : Bundles.format("text.save.difficulty", "[LIGHT_GRAY]" + selected.getDifficulty().toString()))*/);
|
||||||
content().row();
|
content().row();
|
||||||
content().add(new SectorView()).grow();
|
content().add(new SectorView()).grow();
|
||||||
content().row();
|
content().row();
|
||||||
@@ -113,9 +113,9 @@ public class SectorsDialog extends FloatingDialog{
|
|||||||
|
|
||||||
float padSectorSize = sectorSize + sectorPadding;
|
float padSectorSize = sectorSize + sectorPadding;
|
||||||
|
|
||||||
float clipSize = Math.min(width, height);
|
int shownSectorsX = (int)(width/padSectorSize);
|
||||||
int shownSectors = (int)(clipSize/padSectorSize);
|
int shownSectorsY = (int)(height/padSectorSize);
|
||||||
clip.setSize(clipSize).setCenter(x + width/2f, y + height/2f);
|
clip.setSize(width, height).setCenter(x + width/2f, y + height/2f);
|
||||||
Graphics.flush();
|
Graphics.flush();
|
||||||
boolean clipped = ScissorStack.pushScissors(clip);
|
boolean clipped = ScissorStack.pushScissors(clip);
|
||||||
|
|
||||||
@@ -124,8 +124,8 @@ public class SectorsDialog extends FloatingDialog{
|
|||||||
|
|
||||||
Vector2 mouse = Graphics.mouse();
|
Vector2 mouse = Graphics.mouse();
|
||||||
|
|
||||||
for(int x = -shownSectors; x <= shownSectors; x++){
|
for(int x = -shownSectorsX; x <= shownSectorsX; x++){
|
||||||
for(int y = -shownSectors; y <= shownSectors; y++){
|
for(int y = -shownSectorsY; y <= shownSectorsY; y++){
|
||||||
int sectorX = offsetX + x;
|
int sectorX = offsetX + x;
|
||||||
int sectorY = offsetY + y;
|
int sectorY = offsetY + y;
|
||||||
|
|
||||||
@@ -133,19 +133,21 @@ public class SectorsDialog extends FloatingDialog{
|
|||||||
float drawY = y + height/2f + sectorY * padSectorSize - offsetY * padSectorSize - panY % padSectorSize;
|
float drawY = y + height/2f + sectorY * padSectorSize - offsetY * padSectorSize - panY % padSectorSize;
|
||||||
|
|
||||||
Sector sector = world.sectors().get(sectorX, sectorY);
|
Sector sector = world.sectors().get(sectorX, sectorY);
|
||||||
int size = (sector == null ? 1 : sector.size);
|
int width = (sector == null ? 1 : sector.width);
|
||||||
float padding = (size-1) * sectorPadding;
|
int height = (sector == null ? 1 : sector.height);
|
||||||
|
float paddingx = (width-1) * sectorPadding;
|
||||||
|
float paddingy = (height-1) * sectorPadding;
|
||||||
|
|
||||||
if(sector != null && (sector.x != sectorX || sector.y != sectorY)){
|
if(sector != null && (sector.x != sectorX || sector.y != sectorY)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawX += (size-1)/2f*padSectorSize;
|
drawX += (width-1)/2f*padSectorSize;
|
||||||
drawY += (size-1)/2f*padSectorSize;
|
drawY += (height-1)/2f*padSectorSize;
|
||||||
|
|
||||||
if(sector != null && sector.texture != null){
|
if(sector != null && sector.texture != null){
|
||||||
Draw.color(Color.WHITE);
|
Draw.color(Color.WHITE);
|
||||||
Draw.rect(sector.texture, drawX, drawY, sectorSize * size + padding, sectorSize * size + padding);
|
Draw.rect(sector.texture, drawX, drawY, sectorSize * width + paddingx, sectorSize * height + paddingy);
|
||||||
}
|
}
|
||||||
|
|
||||||
float stroke = 4f;
|
float stroke = 4f;
|
||||||
@@ -155,8 +157,8 @@ public class SectorsDialog extends FloatingDialog{
|
|||||||
}else if(sector == selected){
|
}else if(sector == selected){
|
||||||
Draw.color(Palette.place);
|
Draw.color(Palette.place);
|
||||||
stroke = 6f;
|
stroke = 6f;
|
||||||
}else if(Mathf.inRect(mouse.x, mouse.y, drawX - padSectorSize/2f * size, drawY - padSectorSize/2f * size,
|
}else if(Mathf.inRect(mouse.x, mouse.y, drawX - padSectorSize/2f * width, drawY - padSectorSize/2f * height,
|
||||||
drawX + padSectorSize/2f * size, drawY + padSectorSize/2f * size)){
|
drawX + padSectorSize/2f * width, drawY + padSectorSize/2f * height)){
|
||||||
if(clicked){
|
if(clicked){
|
||||||
selectSector(sector);
|
selectSector(sector);
|
||||||
}
|
}
|
||||||
@@ -168,13 +170,13 @@ public class SectorsDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Lines.stroke(Unit.dp.scl(stroke));
|
Lines.stroke(Unit.dp.scl(stroke));
|
||||||
Lines.crect(drawX, drawY, sectorSize * size + padding, sectorSize * size + padding, (int)stroke);
|
Lines.crect(drawX, drawY, sectorSize * width + paddingx, sectorSize * height + paddingy, (int)stroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.stroke(Unit.dp.scl(4f));
|
Lines.stroke(Unit.dp.scl(4f));
|
||||||
Lines.crect(x + width/2f, y + height/2f, clipSize, clipSize);
|
Lines.crect(x + width/2f, y + height/2f, width, height);
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
Graphics.flush();
|
Graphics.flush();
|
||||||
|
|||||||
@@ -81,14 +81,16 @@ public class BlocksFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
container.add(descTable).fillX().uniformX();
|
float w = 246f;
|
||||||
|
|
||||||
container.row();
|
main.add(descTable).width(w);
|
||||||
|
|
||||||
|
main.row();
|
||||||
|
|
||||||
//now add the block selection menu
|
//now add the block selection menu
|
||||||
selectTable = main.table("pane", select -> {})
|
selectTable = main.table("pane", select -> {})
|
||||||
.margin(10f).marginLeft(0f).marginRight(0f).marginTop(-5)
|
.margin(10f).marginLeft(0f).marginRight(0f).marginTop(-5)
|
||||||
.touchable(Touchable.enabled).right().bottom().get();
|
.touchable(Touchable.enabled).right().bottom().width(w).get();
|
||||||
|
|
||||||
}).bottom().right().get();
|
}).bottom().right().get();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.math.Interpolation;
|
import com.badlogic.gdx.math.Interpolation;
|
||||||
|
import com.badlogic.gdx.utils.Align;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.Scaling;
|
import com.badlogic.gdx.utils.Scaling;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
@@ -15,15 +16,14 @@ import io.anuke.mindustry.net.Packets.AdminAction;
|
|||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.ui.IntFormat;
|
import io.anuke.mindustry.ui.IntFormat;
|
||||||
import io.anuke.mindustry.ui.Minimap;
|
import io.anuke.mindustry.ui.Minimap;
|
||||||
|
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||||
import io.anuke.ucore.core.*;
|
import io.anuke.ucore.core.*;
|
||||||
import io.anuke.ucore.graphics.Hue;
|
import io.anuke.ucore.graphics.Hue;
|
||||||
import io.anuke.ucore.scene.Element;
|
import io.anuke.ucore.scene.Element;
|
||||||
import io.anuke.ucore.scene.Group;
|
import io.anuke.ucore.scene.Group;
|
||||||
import io.anuke.ucore.scene.actions.Actions;
|
import io.anuke.ucore.scene.actions.Actions;
|
||||||
import io.anuke.ucore.scene.event.Touchable;
|
import io.anuke.ucore.scene.event.Touchable;
|
||||||
import io.anuke.ucore.scene.ui.Image;
|
import io.anuke.ucore.scene.ui.*;
|
||||||
import io.anuke.ucore.scene.ui.ImageButton;
|
|
||||||
import io.anuke.ucore.scene.ui.Label;
|
|
||||||
import io.anuke.ucore.scene.ui.layout.Stack;
|
import io.anuke.ucore.scene.ui.layout.Stack;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
@@ -103,7 +103,8 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
cont.row();
|
cont.row();
|
||||||
|
|
||||||
Table waves = cont.table(this::addWaveTable).touchable(Touchable.enabled).fillX().height(66f).get();
|
TextButton waves = cont.addButton("", ()->{}).fillX().height(66f).get();
|
||||||
|
addWaveTable(waves);
|
||||||
|
|
||||||
cont.row();
|
cont.row();
|
||||||
|
|
||||||
@@ -182,6 +183,27 @@ public class HudFragment extends Fragment{
|
|||||||
blockfrag.build(Core.scene.getRoot());
|
blockfrag.build(Core.scene.getRoot());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showText(String text){
|
||||||
|
Table table = new Table("button");
|
||||||
|
table.update(() -> {
|
||||||
|
if(state.is(State.menu)){
|
||||||
|
table.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
table.margin(12);
|
||||||
|
table.addImage("icon-check").size(16*2).pad(3);
|
||||||
|
table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center);
|
||||||
|
table.pack();
|
||||||
|
|
||||||
|
//create container table which will align and move
|
||||||
|
Table container = Core.scene.table();
|
||||||
|
container.top().add(table);
|
||||||
|
container.setTranslation(0, table.getPrefHeight());
|
||||||
|
container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(4f),
|
||||||
|
//nesting actions() calls is necessary so the right prefHeight() is used
|
||||||
|
Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.removeActor())));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show unlock notification for a new recipe.
|
* Show unlock notification for a new recipe.
|
||||||
*/
|
*/
|
||||||
@@ -281,6 +303,16 @@ public class HudFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showTextDialog(String str){
|
||||||
|
new FloatingDialog("$text.mission.info"){{
|
||||||
|
shouldPause = true;
|
||||||
|
setFillParent(false);
|
||||||
|
getCell(content()).growX();
|
||||||
|
content().margin(15).add(str).width(400f).wrap().get().setAlignment(Align.left, Align.left);
|
||||||
|
buttons().addButton("$text.continue", this::hide).size(140, 60).pad(4);
|
||||||
|
}}.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void toggleMenus(){
|
private void toggleMenus(){
|
||||||
wavetable.clearActions();
|
wavetable.clearActions();
|
||||||
infolabel.clearActions();
|
infolabel.clearActions();
|
||||||
@@ -312,27 +344,30 @@ public class HudFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addWaveTable(Table table){
|
private void addWaveTable(TextButton table){
|
||||||
wavetable = table;
|
wavetable = table;
|
||||||
float uheight = 66f;
|
float uheight = 66f;
|
||||||
|
|
||||||
IntFormat wavef = new IntFormat("text.wave");
|
IntFormat wavef = new IntFormat("text.wave");
|
||||||
IntFormat timef = new IntFormat("text.wave.waiting");
|
IntFormat timef = new IntFormat("text.wave.waiting");
|
||||||
|
|
||||||
|
table.clearChildren();
|
||||||
|
table.setTouchable(Touchable.enabled);
|
||||||
|
|
||||||
table.background("button");
|
table.background("button");
|
||||||
table.left().table(text -> {
|
table.labelWrap(() -> world.getSector() == null ? wavef.get(state.wave) :
|
||||||
text.left();
|
Bundles.format("text.mission.display", world.getSector().currentMission().displayString())).growX();
|
||||||
text.label(() -> wavef.get(state.wave)).left().get().setFontScale(fontScale * 1.5f);
|
|
||||||
text.row();
|
table.clicked(() -> {
|
||||||
text.label(() -> unitGroups[Team.red.ordinal()].size() > 0 && state.mode.disableWaveTimer ?
|
if(world.getSector() != null && world.getSector().currentMission().hasMessage()){
|
||||||
getEnemiesRemaining() : (state.mode.disableWaveTimer) ? "$text.waiting" :
|
world.getSector().currentMission().showMessage();
|
||||||
timef.get((int) (state.wavetime / 60f))).minWidth(126).left();
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
table.add().growX();
|
table.setDisabled(() -> !(world.getSector() != null && world.getSector().currentMission().hasMessage()));
|
||||||
table.visible(() -> !state.mode.disableWaves);
|
table.visible(() -> !((world.getSector() == null && state.mode.disableWaves) || !state.mode.showMission));
|
||||||
|
|
||||||
playButton(uheight);
|
//playButton(uheight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void playButton(float uheight){
|
private void playButton(float uheight){
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class MenuFragment extends Fragment{
|
|||||||
maps = new MobileButton("icon-map", isize, "$text.maps", ui.maps::show),
|
maps = new MobileButton("icon-map", isize, "$text.maps", ui.maps::show),
|
||||||
load = new MobileButton("icon-load", isize, "$text.load", ui.load::show),
|
load = new MobileButton("icon-load", isize, "$text.load", ui.load::show),
|
||||||
join = new MobileButton("icon-add", isize, "$text.joingame", ui.join::show),
|
join = new MobileButton("icon-add", isize, "$text.joingame", ui.join::show),
|
||||||
editor = new MobileButton("icon-editor", isize, "$text.editor", () -> ui.loadAnd(ui.editor::show)),
|
editor = new MobileButton("icon-editor", isize, "$text.editor", () -> ui.loadGraphics(ui.editor::show)),
|
||||||
tools = new MobileButton("icon-tools", isize, "$text.settings", ui.settings::show),
|
tools = new MobileButton("icon-tools", isize, "$text.settings", ui.settings::show),
|
||||||
unlocks = new MobileButton("icon-unlocks", isize, "$text.unlocks", ui.unlocks::show),
|
unlocks = new MobileButton("icon-unlocks", isize, "$text.unlocks", ui.unlocks::show),
|
||||||
donate = new MobileButton("icon-donate", isize, "$text.donate", Platform.instance::openDonations);
|
donate = new MobileButton("icon-donate", isize, "$text.donate", Platform.instance::openDonations);
|
||||||
@@ -114,7 +114,7 @@ public class MenuFragment extends Fragment{
|
|||||||
|
|
||||||
out.row();
|
out.row();
|
||||||
|
|
||||||
out.add(new MenuButton("icon-editor", "$text.editor", () -> ui.loadAnd(ui.editor::show)));
|
out.add(new MenuButton("icon-editor", "$text.editor", () -> ui.loadGraphics(ui.editor::show)));
|
||||||
|
|
||||||
out.add(new MenuButton("icon-map", "$text.maps", ui.maps::show));
|
out.add(new MenuButton("icon-map", "$text.maps", ui.maps::show));
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package io.anuke.mindustry.world;
|
|||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import io.anuke.mindustry.entities.Damage;
|
import io.anuke.mindustry.entities.Damage;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
@@ -252,6 +253,19 @@ public class Block extends BaseBlock {
|
|||||||
region = Draw.region(name);
|
region = Draw.region(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Called when the world is resized.
|
||||||
|
* Call super!*/
|
||||||
|
public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){
|
||||||
|
if(tile.entity != null && tile.entity.power != null){
|
||||||
|
IntArray links = tile.entity.power.links;
|
||||||
|
IntArray out = new IntArray();
|
||||||
|
for(int i = 0; i < links.size; i++){
|
||||||
|
out.add(world.transform(links.get(i), oldWidth, oldHeight, newWidth, shiftX, shiftY));
|
||||||
|
}
|
||||||
|
tile.entity.power.links = out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when the block is tapped. */
|
/** Called when the block is tapped. */
|
||||||
public void tapped(Tile tile, Player player){
|
public void tapped(Tile tile, Player player){
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import com.badlogic.gdx.utils.ObjectIntMap;
|
|||||||
import io.anuke.mindustry.game.ContentList;
|
import io.anuke.mindustry.game.ContentList;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.type.ContentType;
|
import io.anuke.mindustry.type.ContentType;
|
||||||
import io.anuke.ucore.util.Mathf;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import static io.anuke.mindustry.Vars.content;
|
||||||
|
|
||||||
@@ -34,8 +33,8 @@ public class ColorMapper implements ContentList{
|
|||||||
Color tmpColor = tmpColors.get();
|
Color tmpColor = tmpColors.get();
|
||||||
tmpColor.set(color);
|
tmpColor.set(color);
|
||||||
float maxMult = 1f/Math.max(Math.max(tmpColor.r, tmpColor.g), tmpColor.b) ;
|
float maxMult = 1f/Math.max(Math.max(tmpColor.r, tmpColor.g), tmpColor.b) ;
|
||||||
float mul = Math.min(1.1f + elevation / 4f, maxMult);
|
float mul = Math.min(0.7f + elevation / 5f, maxMult);
|
||||||
if((cliffs & Mathf.pow2(6)) != 0){
|
if((cliffs & ((1 << 6))) != 0){
|
||||||
mul -= 0.5f;
|
mul -= 0.5f;
|
||||||
}
|
}
|
||||||
tmpColor.mul(mul, mul, mul, 1f);
|
tmpColor.mul(mul, mul, mul, 1f);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class OreBlock extends Floor{
|
|||||||
this.base = base;
|
this.base = base;
|
||||||
this.variants = 3;
|
this.variants = 3;
|
||||||
this.minimapColor = ore.color;
|
this.minimapColor = ore.color;
|
||||||
this.blends = block -> block instanceof OreBlock && ((OreBlock) block).base != base;
|
this.blends = block -> (block instanceof OreBlock && ((OreBlock) block).base != base) || (!(block instanceof OreBlock) && block != base);
|
||||||
this.tileBlends = (tile, other) -> tile.getElevation() < other.getElevation();
|
this.tileBlends = (tile, other) -> tile.getElevation() < other.getElevation();
|
||||||
this.edge = base.name;
|
this.edge = base.name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ public class MendProjector extends Block{
|
|||||||
protected float reload = 250f;
|
protected float reload = 250f;
|
||||||
protected float range = 50f;
|
protected float range = 50f;
|
||||||
protected float healPercent = 6f;
|
protected float healPercent = 6f;
|
||||||
protected float phaseBoost = 10f;
|
protected float phaseBoost = 12f;
|
||||||
|
protected float phaseRangeBoost = 40f;
|
||||||
protected float useTime = 300f;
|
protected float useTime = 300f;
|
||||||
|
|
||||||
public MendProjector(String name){
|
public MendProjector(String name){
|
||||||
@@ -65,7 +66,7 @@ public class MendProjector extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(entity.charge >= reload){
|
if(entity.charge >= reload){
|
||||||
float realRange = range + entity.phaseHeat * 20f;
|
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||||
|
|
||||||
Effects.effect(BlockFx.healWaveMend, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange);
|
Effects.effect(BlockFx.healWaveMend, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange);
|
||||||
entity.charge = 0f;
|
entity.charge = 0f;
|
||||||
|
|||||||
@@ -286,6 +286,14 @@ public class ItemBridge extends Block{
|
|||||||
return rel != rel2;
|
return rel != rel2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){
|
||||||
|
super.transformLinks(tile, oldWidth, oldHeight, newWidth, newHeight, shiftX, shiftY);
|
||||||
|
|
||||||
|
ItemBridgeEntity entity = tile.entity();
|
||||||
|
entity.link = world.transform(entity.link, oldWidth, oldHeight, newWidth, shiftX, shiftY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileEntity newEntity(){
|
public TileEntity newEntity(){
|
||||||
return new ItemBridgeEntity();
|
return new ItemBridgeEntity();
|
||||||
|
|||||||
@@ -233,6 +233,14 @@ public class MassDriver extends Block{
|
|||||||
return tile.entity.items.total() < itemCapacity;
|
return tile.entity.items.total() < itemCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){
|
||||||
|
super.transformLinks(tile, oldWidth, oldHeight, newWidth, newHeight, shiftX, shiftY);
|
||||||
|
|
||||||
|
MassDriverEntity entity = tile.entity();
|
||||||
|
entity.link = world.transform(entity.link, oldWidth, oldHeight, newWidth, shiftX, shiftY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileEntity newEntity(){
|
public TileEntity newEntity(){
|
||||||
return new MassDriverEntity();
|
return new MassDriverEntity();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import io.anuke.mindustry.entities.units.UnitType;
|
|||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.graphics.Shaders;
|
import io.anuke.mindustry.graphics.Shaders;
|
||||||
|
import io.anuke.mindustry.maps.TutorialSector;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemType;
|
import io.anuke.mindustry.type.ItemType;
|
||||||
@@ -79,6 +80,14 @@ public class CoreBlock extends StorageBlock{
|
|||||||
if(entity != null) entity.solid = solid;
|
if(entity != null) entity.solid = solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProximityUpdate(Tile tile) {
|
||||||
|
//add cores
|
||||||
|
if(!state.teams.get(tile.getTeam()).cores.contains(tile, true)){
|
||||||
|
state.teams.get(tile.getTeam()).cores.add(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBreak(Tile tile){
|
public boolean canBreak(Tile tile){
|
||||||
return state.teams.get(tile.getTeam()).cores.size > 1;
|
return state.teams.get(tile.getTeam()).cores.size > 1;
|
||||||
@@ -217,7 +226,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found){
|
if(!found && !TutorialSector.supressDrone()){
|
||||||
BaseUnit unit = droneType.create(tile.getTeam());
|
BaseUnit unit = droneType.create(tile.getTeam());
|
||||||
unit.setSpawner(tile);
|
unit.setSpawner(tile);
|
||||||
unit.setDead(true);
|
unit.setDead(true);
|
||||||
|
|||||||
@@ -298,6 +298,14 @@ public class Reconstructor extends Block{
|
|||||||
Call.reconstructPlayer(player, tile);
|
Call.reconstructPlayer(player, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){
|
||||||
|
super.transformLinks(tile, oldWidth, oldHeight, newWidth, newHeight, shiftX, shiftY);
|
||||||
|
|
||||||
|
ReconstructorEntity entity = tile.entity();
|
||||||
|
entity.link = world.transform(entity.link, oldWidth, oldHeight, newWidth, shiftX, shiftY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileEntity newEntity(){
|
public TileEntity newEntity(){
|
||||||
return new ReconstructorEntity();
|
return new ReconstructorEntity();
|
||||||
|
|||||||
@@ -913,6 +913,7 @@ public class ServerControl extends Module{
|
|||||||
|
|
||||||
playSectorMap();
|
playSectorMap();
|
||||||
}else if(world.getSector().currentMission().isComplete()){
|
}else if(world.getSector().currentMission().isComplete()){
|
||||||
|
world.getSector().currentMission().onComplete();
|
||||||
//increment completed missions, check next index next frame
|
//increment completed missions, check next index next frame
|
||||||
world.getSector().completedMissions ++;
|
world.getSector().completedMissions ++;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user