mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-04-27 16:00:51 -07:00
Merge branch 'continuous-sectors' of https://github.com/Anuken/Mindustry
# Conflicts: # core/assets/bundles/bundle.properties
This commit is contained in:
commit
d5bb1b72b9
62 changed files with 1218 additions and 263 deletions
|
|
@ -5,10 +5,6 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
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{
|
||||
|
||||
/** 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.level.select=Level Select
|
||||
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=\
|
||||
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.unexplored=[accent][[Unexplored]
|
||||
text.mission=Mission:[LIGHT_GRAY] {0}
|
||||
text.mission.info=Mission Info
|
||||
text.mission.complete=Mission complete!
|
||||
text.mission.complete.body=Sector {0},{1} has been conquered.
|
||||
text.mission.wave=Survive [accent]{0}[] waves.
|
||||
text.mission.battle=Destroy the enemy base.
|
||||
text.mission.resource=Obtain {0} x{1}
|
||||
text.mission.wave=Survive[accent] {0}/{1} []waves\nWave in {2}
|
||||
text.mission.wave.enemies=Survive[accent] {0}/{1} []waves\n{2} Enemies
|
||||
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.close=Close
|
||||
text.quit=Quit
|
||||
|
|
@ -276,7 +285,7 @@ text.settings.clearall=Clear All
|
|||
text.paused=Paused
|
||||
text.yes=Yes
|
||||
text.no=No
|
||||
text.info.title=[accent]Info
|
||||
text.info.title=Info
|
||||
text.error.title=[crimson]An error has occured
|
||||
text.error.crashtitle=An error has occured
|
||||
text.blocks.blockinfo=Block Info
|
||||
|
|
@ -596,9 +605,9 @@ block.spirit-factory.name=Spirit Drone Factory
|
|||
block.phantom-factory.name=Phantom Drone Factory
|
||||
block.wraith-factory.name=Wraith Fighter Factory
|
||||
block.ghoul-factory.name=Ghoul Bomber Factory
|
||||
block.dagger-factory.name=Dagger Factory
|
||||
block.titan-factory.name=Titan Factory
|
||||
block.revenant-factory.name=Revenant Factory
|
||||
block.dagger-factory.name=Dagger Mech Factory
|
||||
block.titan-factory.name=Titan Mech Factory
|
||||
block.revenant-factory.name=Revenant Fighter Factory
|
||||
block.repair-point.name=Repair Point
|
||||
block.resupply-point.name=Resupply Point
|
||||
block.pulse-conduit.name=Pulse Conduit
|
||||
|
|
@ -611,7 +620,7 @@ block.rotary-pump.name=Rotary Pump
|
|||
block.thorium-reactor.name=Thorium Reactor
|
||||
block.command-center.name=Command Center
|
||||
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-generator.name=Thermal Generator
|
||||
block.alloy-smelter.name=Alloy Smelter
|
||||
|
|
@ -645,3 +654,25 @@ unit.fortress.name=Fortress
|
|||
unit.fortress.description=A heavy artillery ground unit.
|
||||
unit.revenant.name=Revenant
|
||||
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} },
|
||||
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}},
|
||||
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-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} }
|
||||
},
|
||||
|
|
@ -64,7 +65,7 @@ ImageButtonStyle: {
|
|||
static: {up: button },
|
||||
static-down: {up: button-down },
|
||||
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},
|
||||
},
|
||||
ScrollPaneStyle: {
|
||||
|
|
|
|||
|
|
@ -36,19 +36,19 @@ public class Vars{
|
|||
//time between waves in frames (on normal mode)
|
||||
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
|
||||
public static final float coreBuildRange = 999999f;
|
||||
//team of the player by default
|
||||
public static final Team defaultTeam = Team.blue;
|
||||
//team of the enemy in waves
|
||||
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 maxNameLength = 40;
|
||||
public static final float itemSize = 5f;
|
||||
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 invalidSector = Integer.MAX_VALUE;
|
||||
public static Locale[] locales;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ public class Pathfinder{
|
|||
});
|
||||
}
|
||||
|
||||
public void activateTeamPath(Team team){
|
||||
createFor(team);
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(Net.client()) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,17 +14,17 @@ public class Recipes implements ContentList{
|
|||
@Override
|
||||
public void load(){
|
||||
//DEBUG
|
||||
new Recipe(distribution, DebugBlocks.itemSource).setMode(GameMode.sandbox).setHidden(true);
|
||||
new Recipe(distribution, DebugBlocks.itemVoid).setMode(GameMode.sandbox).setHidden(true);
|
||||
new Recipe(liquid, DebugBlocks.liquidSource).setMode(GameMode.sandbox).setHidden(true);
|
||||
new Recipe(power, DebugBlocks.powerVoid).setMode(GameMode.sandbox).setHidden(true);
|
||||
new Recipe(power, DebugBlocks.powerInfinite).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).setAlwaysUnlocked(true);
|
||||
new Recipe(liquid, DebugBlocks.liquidSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(power, DebugBlocks.powerVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
new Recipe(power, DebugBlocks.powerInfinite).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true);
|
||||
|
||||
//DEFENSE
|
||||
|
||||
//walls
|
||||
new Recipe(defense, DefenseBlocks.copperWall, new ItemStack(Items.copper, 12));
|
||||
new Recipe(defense, DefenseBlocks.copperWallLarge, new ItemStack(Items.copper, 12 * 4));
|
||||
new Recipe(defense, DefenseBlocks.copperWall, new ItemStack(Items.copper, 12)).setAlwaysUnlocked(true);
|
||||
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.denseAlloyWallLarge, new ItemStack(Items.densealloy, 12 * 4));
|
||||
|
|
@ -51,7 +51,7 @@ public class Recipes implements ContentList{
|
|||
.setDependencies(Items.blastCompound);
|
||||
|
||||
//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.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));
|
||||
|
|
@ -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));
|
||||
|
||||
//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.phaseConveyor, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20));
|
||||
|
||||
//starter lead transportation
|
||||
new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2));
|
||||
new Recipe(distribution, DistributionBlocks.router, new ItemStack(Items.copper, 6));
|
||||
new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2)).setAlwaysUnlocked(true);
|
||||
new Recipe(distribution, DistributionBlocks.router, new ItemStack(Items.copper, 6)).setAlwaysUnlocked(true);
|
||||
|
||||
//advanced densealloy transporation
|
||||
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
|
||||
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.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));
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class UnitTypes implements ContentList{
|
|||
speed = 0.2f;
|
||||
maxVelocity = 0.8f;
|
||||
range = 50f;
|
||||
healSpeed = 0.25f;
|
||||
healSpeed = 0.22f;
|
||||
health = 60;
|
||||
}};
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ public class UnitTypes implements ContentList{
|
|||
drag = 0.4f;
|
||||
range = 40f;
|
||||
weapon = Weapons.chainBlaster;
|
||||
health = 150;
|
||||
health = 130;
|
||||
}};
|
||||
|
||||
titan = new UnitType("titan", Titan.class, Titan::new){{
|
||||
|
|
@ -108,7 +108,7 @@ public class UnitTypes implements ContentList{
|
|||
health = 220;
|
||||
buildPower = 0.9f;
|
||||
minePower = 1.1f;
|
||||
healSpeed = 0.55f;
|
||||
healSpeed = 0.5f;
|
||||
toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium);
|
||||
}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,6 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||
Table cont = new Table();
|
||||
|
||||
for(int i = 0; i < items.size; i++){
|
||||
if(i == 0) continue;
|
||||
final int f = i;
|
||||
ImageButton button = cont.addImageButton("liquid-icon-" + items.get(i).name, "toggle", 24, () -> {
|
||||
Call.setLiquidSourceLiquid(null, tile, items.get(f));
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class StorageBlocks extends BlockList implements ContentList{
|
|||
@Override
|
||||
public void load(){
|
||||
core = new CoreBlock("core"){{
|
||||
health = 1400;
|
||||
health = 1100;
|
||||
}};
|
||||
|
||||
vault = new Vault("vault"){{
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
|||
produceTime = 1700;
|
||||
size = 2;
|
||||
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"){{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import io.anuke.mindustry.entities.TileEntity;
|
|||
import io.anuke.mindustry.game.Content;
|
||||
import io.anuke.mindustry.game.ContentDatabase;
|
||||
import io.anuke.mindustry.game.EventType.*;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.Saves;
|
||||
import io.anuke.mindustry.input.DefaultKeybinds;
|
||||
import io.anuke.mindustry.input.DesktopInput;
|
||||
|
|
@ -315,29 +316,20 @@ public class Control extends Module{
|
|||
|
||||
Platform.instance.updateRPC();
|
||||
|
||||
if(!Settings.has("4.0-warning")){
|
||||
Settings.putBool("4.0-warning", true);
|
||||
if(!Settings.getBool("4.0-warning-2", false)){
|
||||
|
||||
Timers.run(5f, () -> {
|
||||
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
||||
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
||||
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 " +
|
||||
"A large portion of content is still unimplemented. \nAll 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.[] You have been warned!").wrap().width(400f);
|
||||
dialog.buttons().addButton("$text.ok", () -> {
|
||||
dialog.hide();
|
||||
Settings.putBool("4.0-warning-2", true);
|
||||
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();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
public void update(){
|
||||
|
||||
|
|
@ -374,19 +392,7 @@ public class Control extends Module{
|
|||
Platform.instance.updateRPC();
|
||||
}
|
||||
|
||||
//check unlocked sectors
|
||||
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 ++;
|
||||
}
|
||||
}
|
||||
updateSectors();
|
||||
|
||||
//check unlocks every 2 seconds
|
||||
if(world.getSector() != null && Timers.get("timerCheckUnlock", 120)){
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ public class Logic extends Module{
|
|||
Entities.update(fireGroup);
|
||||
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){
|
||||
Entities.update(effectGroup);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,11 +210,11 @@ public class UI extends SceneModule{
|
|||
}
|
||||
}
|
||||
|
||||
public void loadAnd(Runnable call){
|
||||
loadAnd("$text.loading", call);
|
||||
public void loadGraphics(Runnable call){
|
||||
loadGraphics("$text.loading", call);
|
||||
}
|
||||
|
||||
public void loadAnd(String text, Runnable call){
|
||||
public void loadGraphics(String text, Runnable call){
|
||||
loadfrag.show(text);
|
||||
Timers.runTask(7f, () -> {
|
||||
call.run();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import io.anuke.mindustry.maps.*;
|
|||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
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.Timers;
|
||||
import io.anuke.ucore.entities.EntityPhysics;
|
||||
|
|
@ -195,6 +196,12 @@ public class World extends Module{
|
|||
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.
|
||||
* A WorldLoadEvent will be fire.
|
||||
|
|
@ -202,10 +209,15 @@ public class World extends Module{
|
|||
public void endMapLoad(){
|
||||
for(int x = 0; x < tiles.length; x++){
|
||||
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){
|
||||
tiles[x][y].entity.updateProximity();
|
||||
if(tile.floor() instanceof OreBlock && tile.hasCliffs()){
|
||||
tile.setFloor(((OreBlock) tile.floor()).base);
|
||||
}
|
||||
|
||||
if(tile.entity != null){
|
||||
tile.entity.updateProximity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +244,7 @@ public class World extends Module{
|
|||
|
||||
beginMapLoad();
|
||||
|
||||
int width = sectorSize * sector.size, height = sectorSize * sector.size;
|
||||
int width = sectorSize * sector.width, height = sectorSize * sector.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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () -> {
|
||||
Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> {
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
try{
|
||||
DataInputStream stream = new DataInputStream(file.read());
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||
ui.showError("$text.web.unsupported");
|
||||
}else {
|
||||
Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> {
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
try{
|
||||
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 -> {
|
||||
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
|
||||
FileHandle result = file;
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
|
||||
try{
|
||||
if(!editor.getTags().containsKey("name")){
|
||||
|
|
@ -168,7 +168,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||
Platform.instance.showFileChooser("$text.saveimage", "Image Files", file -> {
|
||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||
FileHandle result = file;
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
try{
|
||||
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
|
||||
}catch (Exception e){
|
||||
|
|
@ -194,7 +194,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||
|
||||
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
|
||||
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
editor.resize(x, y);
|
||||
view.clearStack();
|
||||
});
|
||||
|
|
@ -203,7 +203,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||
|
||||
loadDialog = new MapLoadDialog(map -> {
|
||||
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
try(DataInputStream stream = new DataInputStream(map.stream.get())){
|
||||
MapMeta meta = MapIO.readMapMeta(stream);
|
||||
MapTileData data = MapIO.readTileData(stream, meta, false);
|
||||
|
|
@ -338,7 +338,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||
}
|
||||
|
||||
public void beginEditMap(InputStream is){
|
||||
ui.loadAnd(() -> {
|
||||
ui.loadGraphics(() -> {
|
||||
try{
|
||||
shownWithMap = true;
|
||||
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));
|
||||
|
||||
Fill.tri(px, py, x2, y2, x1, y1);
|
||||
Fill.tri(px, py, x2, y2, x3, y3);
|
||||
|
||||
Draw.alpha(1f);
|
||||
|
||||
Lines.line(px, py, x1, y1);
|
||||
|
|
|
|||
|
|
@ -121,6 +121,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||
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.*/
|
||||
public void setWave(){
|
||||
isWave = true;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class ContentDatabase{
|
|||
* @return whether or not this content was newly unlocked.
|
||||
*/
|
||||
public boolean unlockContent(UnlockableContent content){
|
||||
if(!content.canBeUnlocked()) return false;
|
||||
if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false;
|
||||
|
||||
if(!unlocked.containsKey(content.getContentType())){
|
||||
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 final Tile tile;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ public enum GameMode{
|
|||
enemyCheat = true;
|
||||
showPads = true;
|
||||
}},
|
||||
victory{{
|
||||
disableWaves = true;
|
||||
hidden = true;
|
||||
enemyCheat = false;
|
||||
showPads = true;
|
||||
showMission = false;
|
||||
}},
|
||||
pvp{{
|
||||
showPads = true;
|
||||
disableWaves = true;
|
||||
|
|
@ -26,7 +33,7 @@ public enum GameMode{
|
|||
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 respawnTime = 60 * 4;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class Saves{
|
|||
if(time > Settings.getInt("saveinterval") * 60){
|
||||
saving = true;
|
||||
|
||||
Timers.run(2f, () -> {
|
||||
Timers.runTask(2f, () -> {
|
||||
try{
|
||||
current.save();
|
||||
}catch(Exception e){
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ public class SpawnGroup{
|
|||
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
|
||||
return 0;
|
||||
}
|
||||
float scaling = this.groupScaling;
|
||||
|
||||
return Math.min(groupAmount - 1 + Math.max((int) ((wave / spacing) / groupScaling), 1), max);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public class Waves{
|
|||
return Array.with(
|
||||
new SpawnGroup(UnitTypes.dagger){{
|
||||
end = 8;
|
||||
unitScaling = 1;
|
||||
unitScaling = 3;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.wraith){{
|
||||
|
|
|
|||
|
|
@ -40,21 +40,40 @@ public class FogRenderer implements Disposable{
|
|||
private Rectangle rect = new Rectangle();
|
||||
private boolean dirty;
|
||||
|
||||
private boolean isOffseted;
|
||||
private int offsettedX, offsettedY;
|
||||
|
||||
public FogRenderer(){
|
||||
Events.on(WorldLoadGraphicsEvent.class, event -> {
|
||||
dispose();
|
||||
if(!isOffseted){
|
||||
dispose();
|
||||
}
|
||||
|
||||
padding = world.getSector() != null ? mapPadding + extraPadding : 0;
|
||||
shadowPadding = world.getSector() != null ? fshadowPadding : -1;
|
||||
|
||||
FrameBuffer lastBuffer = buffer;
|
||||
|
||||
buffer = new FrameBuffer(Format.RGBA8888, world.width() + padding*2, world.height() + padding*2, false);
|
||||
changeQueue.clear();
|
||||
|
||||
//clear buffer to black
|
||||
buffer.begin();
|
||||
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();
|
||||
|
||||
if(isOffseted){
|
||||
lastBuffer.dispose();
|
||||
}
|
||||
|
||||
for(int x = 0; x < world.width(); x++){
|
||||
for(int y = 0; y < world.height(); y++){
|
||||
Tile tile = world.tile(x, y);
|
||||
|
|
@ -66,6 +85,8 @@ public class FogRenderer implements Disposable{
|
|||
|
||||
pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 4);
|
||||
dirty = true;
|
||||
|
||||
isOffseted = false;
|
||||
});
|
||||
|
||||
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(){
|
||||
if(buffer == null) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ public class OverlayRenderer{
|
|||
for(Player player : players){
|
||||
InputHandler input = control.input(player.playerIndex);
|
||||
|
||||
if(world.getSector() != null){
|
||||
world.getSector().currentMission().drawOverlay();
|
||||
}
|
||||
|
||||
if(!input.isDrawing() || player.isDead()) continue;
|
||||
|
||||
Shaders.outline.color.set(Palette.accent);
|
||||
|
|
|
|||
|
|
@ -206,6 +206,10 @@ public class DesktopInput extends InputHandler{
|
|||
return;
|
||||
}
|
||||
|
||||
if(Inputs.keyTap(section, "deselect")){
|
||||
player.setMineTile(null);
|
||||
}
|
||||
|
||||
if(!ui.hasMouse()){
|
||||
if(Inputs.keyTap(section, "select")){
|
||||
if(isPlacing()){
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import java.util.zip.InflaterInputStream;
|
|||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
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 Array<SaveFileVersion> versionArray = Array.with(
|
||||
new Save16()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import io.anuke.mindustry.game.Difficulty;
|
|||
import io.anuke.mindustry.game.Saves.SaveSlot;
|
||||
import io.anuke.mindustry.game.SpawnGroup;
|
||||
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.ucore.util.Bits;
|
||||
|
||||
|
|
@ -15,6 +15,8 @@ import static io.anuke.mindustry.Vars.control;
|
|||
|
||||
@Serialize
|
||||
public class Sector{
|
||||
private static final Mission victoryMission = new VictoryMission();
|
||||
|
||||
/**Position on the map, can be positive or negative.*/
|
||||
public short x, y;
|
||||
/**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.*/
|
||||
public int saveID = -1;
|
||||
/**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.*/
|
||||
public int completedMissions;
|
||||
/**Display texture. Needs to be disposed.*/
|
||||
|
|
@ -31,8 +33,6 @@ public class Sector{
|
|||
public transient Array<Mission> missions = new Array<>();
|
||||
/**Enemies spawned at this sector.*/
|
||||
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.*/
|
||||
public transient int difficulty;
|
||||
/**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.*/
|
||||
public Difficulty getDifficulty(){
|
||||
if(difficulty == 0){
|
||||
return Difficulty.easy;
|
||||
//yes, this means insane tutorial difficulty
|
||||
//(((have fun)))
|
||||
return Difficulty.hard;
|
||||
}else if(difficulty < 4){
|
||||
return Difficulty.normal;
|
||||
}else if(difficulty < 9){
|
||||
|
|
@ -52,7 +54,7 @@ public class Sector{
|
|||
}
|
||||
|
||||
public Mission currentMission(){
|
||||
return missions.get(Math.min(completedMissions, missions.size - 1));
|
||||
return completedMissions >= missions.size ? victoryMission : missions.get(completedMissions);
|
||||
}
|
||||
|
||||
public int getSeed(){
|
||||
|
|
|
|||
|
|
@ -3,19 +3,24 @@ package io.anuke.mindustry.maps;
|
|||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.content.Items;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.SaveIO;
|
||||
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
||||
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.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
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.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.GridMap;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
|
@ -25,6 +30,7 @@ import static io.anuke.mindustry.Vars.*;
|
|||
|
||||
public class Sectors{
|
||||
private static final int sectorImageSize = 32;
|
||||
private static final boolean checkExpansion = false;
|
||||
private static final float sectorLargeChance = 0.24f;
|
||||
|
||||
private GridMap<Sector> grid = new GridMap<>();
|
||||
|
|
@ -36,17 +42,22 @@ public class Sectors{
|
|||
}
|
||||
|
||||
if(!sector.hasSave()){
|
||||
for(Mission mission : sector.missions){
|
||||
mission.reset();
|
||||
}
|
||||
world.loadSector(sector);
|
||||
logic.play();
|
||||
sector.saveID = control.getSaves().addSave("sector-" + sector.packedPosition()).index;
|
||||
world.sectors().save();
|
||||
world.setSector(sector);
|
||||
sector.currentMission().onBegin();
|
||||
}else if(SaveIO.breakingVersions.contains(sector.getSave().getBuild())){
|
||||
ui.showInfo("$text.save.old");
|
||||
}else try{
|
||||
sector.getSave().load();
|
||||
world.setSector(sector);
|
||||
state.set(State.playing);
|
||||
sector.currentMission().onBegin();
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
sector.getSave().delete();
|
||||
|
|
@ -69,25 +80,145 @@ public class Sectors{
|
|||
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.*/
|
||||
public void completeSector(int x, int y){
|
||||
createSector(x, y);
|
||||
Sector sector = get(x, y);
|
||||
sector.complete = true;
|
||||
|
||||
for(GridPoint2 point : Edges.getEdges(sector.size)){
|
||||
createSector(sector.x + point.x, sector.y + point.y);
|
||||
for(int sx = 0; sx < sector.width + 2; sx++){
|
||||
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.*/
|
||||
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;
|
||||
|
||||
|
|
@ -95,11 +226,11 @@ public class Sectors{
|
|||
sector.x = (short)x;
|
||||
sector.y = (short)y;
|
||||
sector.complete = false;
|
||||
sector.size = isLarge ? 2 : 1;
|
||||
sector.width = sector.height = 1;
|
||||
initSector(sector);
|
||||
|
||||
for(int cx = 0; cx < sector.size; cx++){
|
||||
for(int cy = 0; cy < sector.size; cy++){
|
||||
for(int cx = 0; cx < sector.width; cx++){
|
||||
for(int cy = 0; cy < sector.height; cy++){
|
||||
grid.put(x + cx, y + cy, sector);
|
||||
}
|
||||
}
|
||||
|
|
@ -118,8 +249,8 @@ public class Sectors{
|
|||
for(Sector sector : out){
|
||||
createTexture(sector);
|
||||
initSector(sector);
|
||||
for(int cx = 0; cx < sector.size; cx++){
|
||||
for(int cy = 0; cy < sector.size; cy++){
|
||||
for(int cx = 0; cx < sector.width; cx++){
|
||||
for(int cy = 0; cy < sector.height; cy++){
|
||||
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));
|
||||
|
||||
if(sector.difficulty == 0){
|
||||
sector.missions.add(new WaveMission(10));
|
||||
//TODO make specfic expansion sector have specific ores
|
||||
sector.missions.addAll(TutorialSector.getMissions());
|
||||
}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))
|
||||
: 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
|
||||
sector.ores.addAll(Items.copper, Items.coal, Items.lead, Items.thorium, Items.titanium);
|
||||
for(Mission mission : sector.missions){
|
||||
sector.spawns.addAll(mission.getWaves(sector));
|
||||
}
|
||||
|
||||
//sector.ores.addAll(Items.copper);
|
||||
|
||||
//set starter items
|
||||
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));
|
||||
}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));
|
||||
}else{ //base starting items to prevent grinding much
|
||||
sector.startingItems = Array.with(new ItemStack(Items.copper, 130));
|
||||
}else{ //empty default
|
||||
sector.startingItems = Array.with();
|
||||
}
|
||||
}
|
||||
|
||||
private int round2(int i){
|
||||
if(i < 0) i --;
|
||||
return i/2*2;
|
||||
}
|
||||
|
||||
private void createTexture(Sector sector){
|
||||
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 y = 0; y < pixmap.getHeight(); y++){
|
||||
|
|
@ -190,8 +325,9 @@ public class Sectors{
|
|||
int toY = y * sectorSize / sectorImageSize;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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);
|
||||
|
||||
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> 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.blocks.Blocks;
|
||||
import io.anuke.mindustry.content.blocks.OreBlocks;
|
||||
import io.anuke.mindustry.content.blocks.StorageBlocks;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.maps.MapTileData;
|
||||
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.ucore.noise.RidgedPerlin;
|
||||
import io.anuke.ucore.noise.Simplex;
|
||||
import io.anuke.ucore.noise.VoronoiNoise;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
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{
|
||||
|
|
@ -37,15 +36,12 @@ public class WorldGenerator{
|
|||
private Simplex sim2 = new Simplex(baseSeed + 1);
|
||||
private Simplex sim3 = new Simplex(baseSeed + 2);
|
||||
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 GenResult result = new GenResult();
|
||||
private ObjectMap<Block, Block> decoration;
|
||||
|
||||
public WorldGenerator(){
|
||||
vn.setUseDistance(true);
|
||||
|
||||
decoration = Mathf.map(
|
||||
Blocks.grass, Blocks.shrub,
|
||||
Blocks.stone, Blocks.rock,
|
||||
|
|
@ -73,6 +69,11 @@ public class WorldGenerator{
|
|||
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){
|
||||
|
||||
//find multiblocks
|
||||
|
|
@ -82,14 +83,8 @@ public class WorldGenerator{
|
|||
for(int y = 0; y < tiles[0].length; y++){
|
||||
Tile tile = tiles[x][y];
|
||||
|
||||
Team team = tile.getTeam();
|
||||
|
||||
if(tile.block() == StorageBlocks.core){
|
||||
state.teams.get(team).cores.add(tile);
|
||||
}
|
||||
|
||||
if(tiles[x][y].block().isMultiblock()){
|
||||
multiblocks.add(tiles[x][y].packedPosition());
|
||||
if(tile.block().isMultiblock()){
|
||||
multiblocks.add(tile.packedPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -134,6 +129,7 @@ public class WorldGenerator{
|
|||
tile.setBlock(Blocks.air);
|
||||
}
|
||||
|
||||
//remove ore veins on cliffs
|
||||
if(tile.floor() instanceof OreBlock && tile.hasCliffs()){
|
||||
tile.setFloor(((OreBlock)tile.floor()).base);
|
||||
}
|
||||
|
|
@ -190,11 +186,12 @@ public class WorldGenerator{
|
|||
SeedRandom rnd = new SeedRandom(sector.getSeed());
|
||||
Generation gena = new Generation(sector, tiles, tiles.length, tiles[0].length, rnd);
|
||||
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 y = 0; y < height; y++){
|
||||
GenResult result = generateTile(this.result, sector.x, sector.y, x, y, true, spawnpoints);
|
||||
Tile tile = new Tile(x, y, (byte)result.floor.id, (byte)result.wall.id, (byte)0, (byte)0, result.elevation);
|
||||
GenResult result = generateTile(this.result, sector.x, sector.y, x, y, true, spawnpoints, ores);
|
||||
Tile tile = new Tile(x, y, result.floor.id, result.wall.id, (byte)0, (byte)0, result.elevation);
|
||||
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 y = 0; y < tiles[0].length; 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){
|
||||
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 y = sectorY * sectorSize + localY + Short.MAX_VALUE;
|
||||
|
||||
|
|
@ -255,8 +261,8 @@ public class WorldGenerator{
|
|||
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 elevation = elevationOf(x, y, detailed);
|
||||
double temp = vn.noise(x, y, 1f / 300f) * sim3.octaveNoise2D(detailed ? 2 : 1, 1, 1f / 13f, x, y)/13f
|
||||
+ sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x, y);
|
||||
double temp =
|
||||
+ sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x - 120, y);
|
||||
|
||||
int lerpDst = 20;
|
||||
lerpDst *= lerpDst;
|
||||
|
|
@ -313,6 +319,19 @@ public class WorldGenerator{
|
|||
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.floor = floor;
|
||||
result.elevation = (byte) Math.max(elevation, 0);
|
||||
|
|
@ -321,7 +340,7 @@ public class WorldGenerator{
|
|||
|
||||
double elevationOf(int x, int y, boolean detailed){
|
||||
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{
|
||||
|
|
|
|||
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.maps.generation.FortressGenerator;
|
||||
import io.anuke.mindustry.maps.generation.Generation;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
public class BattleMission implements Mission{
|
||||
public class BattleMission extends Mission{
|
||||
private final static int coreX = 60, coreY = 60;
|
||||
@Override
|
||||
public void display(Table table){
|
||||
table.add("$text.mission.battle");
|
||||
}
|
||||
|
||||
@Override
|
||||
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.maps.Sector;
|
||||
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.util.Bundles;
|
||||
|
||||
public interface Mission{
|
||||
boolean isComplete();
|
||||
String displayString();
|
||||
GameMode getMode();
|
||||
void display(Table table);
|
||||
import static io.anuke.mindustry.Vars.headless;
|
||||
import static io.anuke.mindustry.Vars.ui;
|
||||
|
||||
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<>();
|
||||
}
|
||||
|
||||
default Array<GridPoint2> getSpawnPoints(Generation gen){
|
||||
public Array<GridPoint2> getSpawnPoints(Generation gen){
|
||||
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].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.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.generation.Generation;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
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;
|
||||
|
||||
public WaveMission(int target){
|
||||
|
|
@ -29,8 +34,10 @@ public class WaveMission implements Mission{
|
|||
}
|
||||
|
||||
@Override
|
||||
public void display(Table table){
|
||||
table.add(Bundles.format("text.mission.wave", target));
|
||||
public void onBegin(){
|
||||
super.onBegin();
|
||||
|
||||
world.pathfinder().activateTeamPath(waveTeam);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -40,12 +47,29 @@ public class WaveMission implements Mission{
|
|||
|
||||
@Override
|
||||
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
|
||||
public boolean isComplete(){
|
||||
return state.wave >= target;
|
||||
return state.wave > target && Vars.unitGroups[Vars.waveTeam.ordinal()].size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public class Recipe extends UnlockableContent{
|
|||
public GameMode mode;
|
||||
public boolean isPad;
|
||||
public boolean hidden;
|
||||
public boolean alwaysUnlocked;
|
||||
|
||||
private UnlockableContent[] dependencies;
|
||||
private Block[] blockDependencies;
|
||||
|
|
@ -58,15 +59,16 @@ public class Recipe extends UnlockableContent{
|
|||
* Returns unlocked recipes in a category.
|
||||
* 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){
|
||||
throw new RuntimeException("Not implemented on the headless backend!");
|
||||
}
|
||||
|
||||
r.clear();
|
||||
for(Recipe recipe : content.recipes()){
|
||||
if(recipe.category == category && (control.database().isUnlocked(recipe))){
|
||||
r.add(recipe);
|
||||
arr.clear();
|
||||
for(Recipe r : content.recipes()){
|
||||
if(r.category == category && (control.database().isUnlocked(r)) &&
|
||||
!((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;
|
||||
}
|
||||
|
||||
public Recipe setAlwaysUnlocked(boolean unlocked){
|
||||
this.alwaysUnlocked = unlocked;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alwaysUnlocked(){
|
||||
return hidden;
|
||||
return alwaysUnlocked;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@ import com.badlogic.gdx.Gdx;
|
|||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
||||
import io.anuke.mindustry.content.Items;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.ColorMapper;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
|
|
@ -20,6 +23,7 @@ import static io.anuke.mindustry.Vars.sectorSize;
|
|||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class GenViewDialog extends FloatingDialog{
|
||||
Array<Item> ores = Array.with(Items.copper, Items.lead, Items.coal);
|
||||
|
||||
public GenViewDialog(){
|
||||
super("generate view");
|
||||
|
|
@ -81,7 +85,7 @@ public class GenViewDialog extends FloatingDialog{
|
|||
Pixmap pixmap = new Pixmap(sectorSize, sectorSize, Format.RGBA8888);
|
||||
for(int i = 0; i < sectorSize; i++){
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class SaveDialog extends LoadDialog{
|
|||
slots.row();
|
||||
slots.addImageTextButton("$text.save.new", "icon-add", "clear", 14 * 3, () ->
|
||||
ui.showTextInput("$text.save", "$text.save.newslot", "", text -> {
|
||||
ui.loadAnd("$text.saving", () -> {
|
||||
ui.loadGraphics("$text.saving", () -> {
|
||||
control.getSaves().addSave(text);
|
||||
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()) : ""))));
|
||||
content().row();
|
||||
content().label(() -> Bundles.format("text.mission", selected == null || selected.completedMissions >= selected.missions.size
|
||||
? Bundles.get("text.none") : selected.missions.get(selected.completedMissions).displayString())
|
||||
+ "[WHITE] " + (selected == null ? "" : Bundles.format("text.save.difficulty", "[LIGHT_GRAY]" + selected.getDifficulty().toString())));
|
||||
? Bundles.get("text.none") : selected.missions.get(selected.completedMissions).menuDisplayString())
|
||||
+ "[WHITE] " /*+ (selected == null ? "" : Bundles.format("text.save.difficulty", "[LIGHT_GRAY]" + selected.getDifficulty().toString()))*/);
|
||||
content().row();
|
||||
content().add(new SectorView()).grow();
|
||||
content().row();
|
||||
|
|
@ -113,9 +113,9 @@ public class SectorsDialog extends FloatingDialog{
|
|||
|
||||
float padSectorSize = sectorSize + sectorPadding;
|
||||
|
||||
float clipSize = Math.min(width, height);
|
||||
int shownSectors = (int)(clipSize/padSectorSize);
|
||||
clip.setSize(clipSize).setCenter(x + width/2f, y + height/2f);
|
||||
int shownSectorsX = (int)(width/padSectorSize);
|
||||
int shownSectorsY = (int)(height/padSectorSize);
|
||||
clip.setSize(width, height).setCenter(x + width/2f, y + height/2f);
|
||||
Graphics.flush();
|
||||
boolean clipped = ScissorStack.pushScissors(clip);
|
||||
|
||||
|
|
@ -124,8 +124,8 @@ public class SectorsDialog extends FloatingDialog{
|
|||
|
||||
Vector2 mouse = Graphics.mouse();
|
||||
|
||||
for(int x = -shownSectors; x <= shownSectors; x++){
|
||||
for(int y = -shownSectors; y <= shownSectors; y++){
|
||||
for(int x = -shownSectorsX; x <= shownSectorsX; x++){
|
||||
for(int y = -shownSectorsY; y <= shownSectorsY; y++){
|
||||
int sectorX = offsetX + x;
|
||||
int sectorY = offsetY + y;
|
||||
|
||||
|
|
@ -133,19 +133,21 @@ public class SectorsDialog extends FloatingDialog{
|
|||
float drawY = y + height/2f + sectorY * padSectorSize - offsetY * padSectorSize - panY % padSectorSize;
|
||||
|
||||
Sector sector = world.sectors().get(sectorX, sectorY);
|
||||
int size = (sector == null ? 1 : sector.size);
|
||||
float padding = (size-1) * sectorPadding;
|
||||
int width = (sector == null ? 1 : sector.width);
|
||||
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)){
|
||||
continue;
|
||||
}
|
||||
|
||||
drawX += (size-1)/2f*padSectorSize;
|
||||
drawY += (size-1)/2f*padSectorSize;
|
||||
drawX += (width-1)/2f*padSectorSize;
|
||||
drawY += (height-1)/2f*padSectorSize;
|
||||
|
||||
if(sector != null && sector.texture != null){
|
||||
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;
|
||||
|
|
@ -155,8 +157,8 @@ public class SectorsDialog extends FloatingDialog{
|
|||
}else if(sector == selected){
|
||||
Draw.color(Palette.place);
|
||||
stroke = 6f;
|
||||
}else if(Mathf.inRect(mouse.x, mouse.y, drawX - padSectorSize/2f * size, drawY - padSectorSize/2f * size,
|
||||
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 * width, drawY + padSectorSize/2f * height)){
|
||||
if(clicked){
|
||||
selectSector(sector);
|
||||
}
|
||||
|
|
@ -168,13 +170,13 @@ public class SectorsDialog extends FloatingDialog{
|
|||
}
|
||||
|
||||
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);
|
||||
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();
|
||||
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
|
||||
selectTable = main.table("pane", select -> {})
|
||||
.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();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx;
|
|||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Scaling;
|
||||
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.ui.IntFormat;
|
||||
import io.anuke.mindustry.ui.Minimap;
|
||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.actions.Actions;
|
||||
import io.anuke.ucore.scene.event.Touchable;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.ImageButton;
|
||||
import io.anuke.ucore.scene.ui.Label;
|
||||
import io.anuke.ucore.scene.ui.*;
|
||||
import io.anuke.ucore.scene.ui.layout.Stack;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
|
@ -103,7 +103,8 @@ public class HudFragment extends Fragment{
|
|||
|
||||
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();
|
||||
|
||||
|
|
@ -182,6 +183,27 @@ public class HudFragment extends Fragment{
|
|||
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.
|
||||
*/
|
||||
|
|
@ -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(){
|
||||
wavetable.clearActions();
|
||||
infolabel.clearActions();
|
||||
|
|
@ -312,27 +344,30 @@ public class HudFragment extends Fragment{
|
|||
}
|
||||
}
|
||||
|
||||
private void addWaveTable(Table table){
|
||||
private void addWaveTable(TextButton table){
|
||||
wavetable = table;
|
||||
float uheight = 66f;
|
||||
|
||||
IntFormat wavef = new IntFormat("text.wave");
|
||||
IntFormat timef = new IntFormat("text.wave.waiting");
|
||||
|
||||
table.clearChildren();
|
||||
table.setTouchable(Touchable.enabled);
|
||||
|
||||
table.background("button");
|
||||
table.left().table(text -> {
|
||||
text.left();
|
||||
text.label(() -> wavef.get(state.wave)).left().get().setFontScale(fontScale * 1.5f);
|
||||
text.row();
|
||||
text.label(() -> unitGroups[Team.red.ordinal()].size() > 0 && state.mode.disableWaveTimer ?
|
||||
getEnemiesRemaining() : (state.mode.disableWaveTimer) ? "$text.waiting" :
|
||||
timef.get((int) (state.wavetime / 60f))).minWidth(126).left();
|
||||
table.labelWrap(() -> world.getSector() == null ? wavef.get(state.wave) :
|
||||
Bundles.format("text.mission.display", world.getSector().currentMission().displayString())).growX();
|
||||
|
||||
table.clicked(() -> {
|
||||
if(world.getSector() != null && world.getSector().currentMission().hasMessage()){
|
||||
world.getSector().currentMission().showMessage();
|
||||
}
|
||||
});
|
||||
|
||||
table.add().growX();
|
||||
table.visible(() -> !state.mode.disableWaves);
|
||||
table.setDisabled(() -> !(world.getSector() != null && world.getSector().currentMission().hasMessage()));
|
||||
table.visible(() -> !((world.getSector() == null && state.mode.disableWaves) || !state.mode.showMission));
|
||||
|
||||
playButton(uheight);
|
||||
//playButton(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),
|
||||
load = new MobileButton("icon-load", isize, "$text.load", ui.load::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),
|
||||
unlocks = new MobileButton("icon-unlocks", isize, "$text.unlocks", ui.unlocks::show),
|
||||
donate = new MobileButton("icon-donate", isize, "$text.donate", Platform.instance::openDonations);
|
||||
|
|
@ -114,7 +114,7 @@ public class MenuFragment extends Fragment{
|
|||
|
||||
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));
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package io.anuke.mindustry.world;
|
|||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import io.anuke.mindustry.entities.Damage;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
|
|
@ -252,6 +253,19 @@ public class Block extends BaseBlock {
|
|||
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. */
|
||||
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.Team;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
|
||||
|
|
@ -34,8 +33,8 @@ public class ColorMapper implements ContentList{
|
|||
Color tmpColor = tmpColors.get();
|
||||
tmpColor.set(color);
|
||||
float maxMult = 1f/Math.max(Math.max(tmpColor.r, tmpColor.g), tmpColor.b) ;
|
||||
float mul = Math.min(1.1f + elevation / 4f, maxMult);
|
||||
if((cliffs & Mathf.pow2(6)) != 0){
|
||||
float mul = Math.min(0.7f + elevation / 5f, maxMult);
|
||||
if((cliffs & ((1 << 6))) != 0){
|
||||
mul -= 0.5f;
|
||||
}
|
||||
tmpColor.mul(mul, mul, mul, 1f);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public class OreBlock extends Floor{
|
|||
this.base = base;
|
||||
this.variants = 3;
|
||||
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.edge = base.name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ public class MendProjector extends Block{
|
|||
protected float reload = 250f;
|
||||
protected float range = 50f;
|
||||
protected float healPercent = 6f;
|
||||
protected float phaseBoost = 10f;
|
||||
protected float phaseBoost = 12f;
|
||||
protected float phaseRangeBoost = 40f;
|
||||
protected float useTime = 300f;
|
||||
|
||||
public MendProjector(String name){
|
||||
|
|
@ -65,7 +66,7 @@ public class MendProjector extends Block{
|
|||
}
|
||||
|
||||
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);
|
||||
entity.charge = 0f;
|
||||
|
|
|
|||
|
|
@ -286,6 +286,14 @@ public class ItemBridge extends Block{
|
|||
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
|
||||
public TileEntity newEntity(){
|
||||
return new ItemBridgeEntity();
|
||||
|
|
|
|||
|
|
@ -233,6 +233,14 @@ public class MassDriver extends Block{
|
|||
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
|
||||
public TileEntity newEntity(){
|
||||
return new MassDriverEntity();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import io.anuke.mindustry.entities.units.UnitType;
|
|||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.mindustry.maps.TutorialSector;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemType;
|
||||
|
|
@ -79,6 +80,14 @@ public class CoreBlock extends StorageBlock{
|
|||
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
|
||||
public boolean canBreak(Tile tile){
|
||||
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());
|
||||
unit.setSpawner(tile);
|
||||
unit.setDead(true);
|
||||
|
|
|
|||
|
|
@ -298,6 +298,14 @@ public class Reconstructor extends Block{
|
|||
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
|
||||
public TileEntity newEntity(){
|
||||
return new ReconstructorEntity();
|
||||
|
|
|
|||
|
|
@ -913,6 +913,7 @@ public class ServerControl extends Module{
|
|||
|
||||
playSectorMap();
|
||||
}else if(world.getSector().currentMission().isComplete()){
|
||||
world.getSector().currentMission().onComplete();
|
||||
//increment completed missions, check next index next frame
|
||||
world.getSector().completedMissions ++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue