Added sample tutorial text / Refactoring

This commit is contained in:
Anuken 2018-09-22 12:20:04 -04:00
parent 999dd5eb6f
commit b77caed0ba
16 changed files with 199 additions and 93 deletions

View File

@ -58,15 +58,16 @@ text.sector.resume=Resume
text.sector.locked=[scarlet][[Incomplete]
text.sector.unexplored=[accent][[Unexplored]
text.mission=Mission:[LIGHT_GRAY] {0}
text.mission.complete=Mission complete!
text.mission.info=Mission Info
text.mission.complete=[accent]Mission complete!
text.mission.complete.body=Sector {0},{1} has been conquered.
text.mission.wave=Survive [accent]{0}/{1} []waves
text.mission.wave.menu=Survive [accent]{0} []waves
text.mission.wave=Survive[accent] {0}/{1} []waves\nWave in {2}
text.mission.wave.menu=Survive[accent] {0} []waves
text.mission.battle=Destroy the enemy core
text.mission.resource=Obtain {0} x{1}
text.mission.block=Create {0}
text.mission.unit=Create {0} Unit
text.mission.display=[accent]Mission:[LIGHT_GRAY] {0}
text.mission.display=[accent]Mission:\n[LIGHT_GRAY]{0}
text.none=<none>
text.close=Close
text.quit=Quit
@ -654,4 +655,6 @@ unit.wraith.description=A fast, hit-and-run interceptor unit.
unit.fortress.name=Fortress
unit.fortress.description=A heavy artillery ground unit.
unit.revenant.name=Revenant
unit.revenant.description=A heavy laser platform.
unit.revenant.description=A heavy laser platform.
tutorial.begin=Starting tutorial text

View File

@ -338,7 +338,6 @@ public class Control extends Module{
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();
});
}
}
@ -350,6 +349,29 @@ public class Control extends Module{
}
}
private void updateSectors(){
if(world.getSector() == null) return;
//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();
}
//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(){
@ -375,23 +397,7 @@ public class Control extends Module{
Platform.instance.updateRPC();
}
//TODO move sector code into logic class
//check unlocked sectors
if(world.getSector() != null && !world.getSector().complete){
//all assigned missions are complete
if(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());
}else if(world.getSector().currentMission().isComplete()){
world.getSector().currentMission().onComplete();
//increment completed missions, check next index next frame
world.getSector().completedMissions ++;
state.mode = world.getSector().currentMission().getMode();
}
}
updateSectors();
//check unlocks every 2 seconds
if(world.getSector() != null && Timers.get("timerCheckUnlock", 120)){

View File

@ -5,13 +5,12 @@ import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
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.core.GameState.State;
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.*;
import io.anuke.mindustry.maps.missions.BattleMission;
import io.anuke.mindustry.maps.missions.WaveMission;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.Tile;
@ -251,27 +250,7 @@ public class Sectors{
if(sector.difficulty == 0){
//TODO make specfic expansion sector have specific ores
sector.missions.addAll(Array.with(
new ItemMission(Items.copper, 30),
new BlockMission(ProductionBlocks.mechanicalDrill),
new BlockMission(DistributionBlocks.conveyor),
new ItemMission(Items.copper, 40),
new BlockMission(TurretBlocks.duo),
new WaveMission(5),
new ExpandMission(1, 0),
new ItemMission(Items.lead, 30),
new ItemMission(Items.copper, 150),
new BlockMission(CraftingBlocks.smelter),
new ItemMission(Items.densealloy, 30),
new BlockMission(PowerBlocks.combustionGenerator),
new BlockMission(PowerBlocks.powerNode),
new BlockMission(CraftingBlocks.siliconsmelter),
new ItemMission(Items.silicon, 30),
new BlockMission(UnitBlocks.daggerFactory),
new UnitMission(UnitTypes.dagger),
new ExpandMission(-1, 0),
new BattleMission()
));
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());

View File

@ -0,0 +1,35 @@
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.maps.missions.*;
/**Just a class for returning the list of tutorial missions.*/
public class TutorialSector{
public static Array<Mission> getMissions(){
return Array.with(
new ItemMission(Items.copper, 30).setMessage("$tutorial.begin"),
new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.begin"),
new BlockMission(DistributionBlocks.conveyor),
new ItemMission(Items.copper, 40),
new BlockMission(TurretBlocks.duo),
new WaveMission(5),
new ExpandMission(1, 0),
new ItemMission(Items.lead, 30),
new ItemMission(Items.copper, 150),
new BlockMission(CraftingBlocks.smelter),
new ItemMission(Items.densealloy, 30),
new BlockMission(PowerBlocks.combustionGenerator),
new BlockMission(PowerBlocks.powerNode),
new BlockMission(CraftingBlocks.siliconsmelter),
new ItemMission(Items.silicon, 30),
new BlockMission(UnitBlocks.daggerFactory),
new UnitMission(UnitTypes.dagger),
new ExpandMission(-1, 0),
new BattleMission()
);
}
}

View File

@ -190,7 +190,7 @@ public class WorldGenerator{
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);
Tile tile = new Tile(x, y, result.floor.id, result.wall.id, (byte)0, (byte)0, result.elevation);
tiles[x][y] = tile;
}
}
@ -241,7 +241,7 @@ public class WorldGenerator{
return generateTile(result, sectorX, sectorY, localX, localY, detailed, null);
}
//TODO include tile in result
//TODO include ore in result
/**
* Gets the generation result from a specific sector at specific coordinates.
* @param result where to put the generation results

View File

@ -6,7 +6,7 @@ import io.anuke.mindustry.game.GameMode;
import static io.anuke.mindustry.Vars.threads;
/**A mission which simply runs a single action and is completed instantly.*/
public abstract class ActionMission implements Mission{
public abstract class ActionMission extends Mission{
private Runnable runner;
public ActionMission(Runnable runner){

View File

@ -9,7 +9,7 @@ import io.anuke.mindustry.maps.generation.FortressGenerator;
import io.anuke.mindustry.maps.generation.Generation;
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

View File

@ -10,7 +10,7 @@ import static io.anuke.mindustry.Vars.defaultTeam;
import static io.anuke.mindustry.Vars.world;
/**A mission in which the player must place a block.*/
public class BlockMission implements Mission{
public class BlockMission extends Mission{
private final Block block;
private boolean complete;

View File

@ -9,7 +9,7 @@ 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 implements Mission{
public class ItemMission extends Mission{
private final Item item;
private final int amount;

View File

@ -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);
}
});
}
}

View File

@ -2,7 +2,6 @@ package io.anuke.mindustry.maps.missions;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.SpawnGroup;
@ -10,43 +9,70 @@ import io.anuke.mindustry.game.Team;
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;
public interface Mission{
boolean isComplete();
import static io.anuke.mindustry.Vars.headless;
import static io.anuke.mindustry.Vars.ui;
public abstract class Mission{
private String extraMessage;
public abstract boolean isComplete();
/**Returns the string that is displayed in-game near the menu.*/
String displayString();
public abstract String displayString();
/**Returns the info string displayed in the sector dialog (menu)*/
default String menuDisplayString(){
public String menuDisplayString(){
return displayString();
}
default GameMode getMode(){
public GameMode getMode(){
return GameMode.noWaves;
}
default void onComplete(){
if(!Vars.headless){
//TODO show 'mission complete' message somewhere
/**Sets the message displayed on mission begin. Returns this mission for chaining.*/
public Mission setMessage(String message){
this.extraMessage = message;
return this;
}
/**Shows the unique sector message.*/
public void showMessage(){
if(!headless && extraMessage != null){
ui.hudfrag.showTextDialog(extraMessage);
}
}
default void display(Table table){
public boolean hasMessage(){
return extraMessage != null;
}
public void onBegin(){
showMessage();
}
public void onComplete(){
if(!headless){
ui.hudfrag.showText("[LIGHT_GRAY]"+menuDisplayString() + ":\n" + Bundles.get("text.mission.complete"));
}
}
public void display(Table table){
table.add(displayString());
}
default Array<SpawnGroup> getWaves(Sector sector){
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);
}

View File

@ -6,7 +6,7 @@ import io.anuke.mindustry.entities.units.UnitType;
import io.anuke.mindustry.game.GameMode;
import io.anuke.ucore.util.Bundles;
public class UnitMission implements Mission{
public class UnitMission extends Mission{
private final UnitType type;
public UnitMission(UnitType type){

View File

@ -3,7 +3,7 @@ package io.anuke.mindustry.maps.missions;
import io.anuke.mindustry.game.GameMode;
import io.anuke.ucore.scene.ui.layout.Table;
public class VictoryMission implements Mission{
public class VictoryMission extends Mission{
@Override
public boolean isComplete(){
return false;

View File

@ -12,7 +12,7 @@ import io.anuke.ucore.util.Bundles;
import static io.anuke.mindustry.Vars.state;
public class WaveMission implements Mission{
public class WaveMission extends Mission{
private final int target;
public WaveMission(int target){
@ -37,7 +37,7 @@ public class WaveMission implements Mission{
@Override
public String displayString(){
return Bundles.format("text.mission.wave", state.wave, target);
return Bundles.format("text.mission.wave", state.wave, target, (int)(state.wavetime/60));
}
@Override

View File

@ -110,9 +110,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);
@ -121,8 +121,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;
@ -130,19 +130,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.width);
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;
@ -152,8 +154,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);
}
@ -165,13 +167,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();

View File

@ -16,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;
@ -104,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();
@ -183,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.
*/
@ -282,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(600f).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();
@ -313,21 +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.labelWrap(() -> world.getSector() == null ? wavef.get(state.wave) :
Bundles.format("text.mission.display", world.getSector().currentMission().displayString())).growX()
.get().setAlignment(Align.center, Align.center);
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.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){