mirror of
https://github.com/Anuken/Mindustry.git
synced 2024-12-22 15:54:00 +07:00
WIP campaign difficulty dialog
This commit is contained in:
parent
efb86724a1
commit
d8eabece7c
2
.github/workflows/pr.yml
vendored
2
.github/workflows/pr.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
|||||||
- name: Run unit tests and build JAR
|
- name: Run unit tests and build JAR
|
||||||
run: ./gradlew desktop:dist
|
run: ./gradlew desktop:dist
|
||||||
- name: Upload desktop JAR for testing
|
- name: Upload desktop JAR for testing
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Desktop JAR (zipped)
|
name: Desktop JAR (zipped)
|
||||||
path: desktop/build/libs/Mindustry.jar
|
path: desktop/build/libs/Mindustry.jar
|
||||||
|
@ -197,6 +197,7 @@ campaign.select = Select Starting Campaign
|
|||||||
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
|
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
|
||||||
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nMore difficult. Higher quality maps and overall experience.
|
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nMore difficult. Higher quality maps and overall experience.
|
||||||
campaign.serpulo = Older content; the classic experience. More open-ended, more content.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
|
campaign.serpulo = Older content; the classic experience. More open-ended, more content.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
|
||||||
|
campaign.difficulty = Difficulty
|
||||||
completed = [accent]Researched
|
completed = [accent]Researched
|
||||||
techtree = Tech Tree
|
techtree = Tech Tree
|
||||||
techtree.select = Tech Tree Selection
|
techtree.select = Tech Tree Selection
|
||||||
@ -800,6 +801,11 @@ threat.high = High
|
|||||||
threat.extreme = Extreme
|
threat.extreme = Extreme
|
||||||
threat.eradication = Eradication
|
threat.eradication = Eradication
|
||||||
|
|
||||||
|
difficulty.easy = Easy
|
||||||
|
difficulty.normal = Normal
|
||||||
|
difficulty.hard = Hard
|
||||||
|
difficulty.eradication = Eradication
|
||||||
|
|
||||||
planets = Planets
|
planets = Planets
|
||||||
|
|
||||||
planet.serpulo.name = Serpulo
|
planet.serpulo.name = Serpulo
|
||||||
@ -1172,12 +1178,6 @@ setting.fpscap.text = {0} FPS
|
|||||||
setting.uiscale.name = UI Scaling
|
setting.uiscale.name = UI Scaling
|
||||||
setting.uiscale.description = Restart required to apply changes.
|
setting.uiscale.description = Restart required to apply changes.
|
||||||
setting.swapdiagonal.name = Always Diagonal Placement
|
setting.swapdiagonal.name = Always Diagonal Placement
|
||||||
setting.difficulty.training = Training
|
|
||||||
setting.difficulty.easy = Easy
|
|
||||||
setting.difficulty.normal = Normal
|
|
||||||
setting.difficulty.hard = Hard
|
|
||||||
setting.difficulty.insane = Insane
|
|
||||||
setting.difficulty.name = Difficulty:
|
|
||||||
setting.screenshake.name = Screen Shake
|
setting.screenshake.name = Screen Shake
|
||||||
setting.bloomintensity.name = Bloom Intensity
|
setting.bloomintensity.name = Bloom Intensity
|
||||||
setting.bloomblur.name = Bloom Blur
|
setting.bloomblur.name = Bloom Blur
|
||||||
@ -1397,6 +1397,8 @@ rules.title.teams = Teams
|
|||||||
rules.title.planet = Planet
|
rules.title.planet = Planet
|
||||||
rules.lighting = Lighting
|
rules.lighting = Lighting
|
||||||
rules.fog = Fog of War
|
rules.fog = Fog of War
|
||||||
|
rules.invasions = Enemy Sector Invasions
|
||||||
|
rules.showspawns = Show Enemy Spawns
|
||||||
rules.fire = Fire
|
rules.fire = Fire
|
||||||
rules.anyenv = <Any>
|
rules.anyenv = <Any>
|
||||||
rules.explosions = Block/Unit Explosion Damage
|
rules.explosions = Block/Unit Explosion Damage
|
||||||
|
@ -66,12 +66,19 @@ public class WaveSpawner{
|
|||||||
if(group.type == null) continue;
|
if(group.type == null) continue;
|
||||||
|
|
||||||
int spawned = group.getSpawned(state.wave - 1);
|
int spawned = group.getSpawned(state.wave - 1);
|
||||||
|
if(spawned == 0) continue;
|
||||||
|
|
||||||
|
if(state.isCampaign()){
|
||||||
|
spawned = Math.max(1, Mathf.round(spawned * state.getPlanet().campaignRules.difficulty.enemySpawnMultiplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
int spawnedf = spawned;
|
||||||
|
|
||||||
if(group.type.flying){
|
if(group.type.flying){
|
||||||
float spread = margin / 1.5f;
|
float spread = margin / 1.5f;
|
||||||
|
|
||||||
eachFlyerSpawn(group.spawn, (spawnX, spawnY) -> {
|
eachFlyerSpawn(group.spawn, (spawnX, spawnY) -> {
|
||||||
for(int i = 0; i < spawned; i++){
|
for(int i = 0; i < spawnedf; i++){
|
||||||
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
|
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
|
||||||
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
||||||
spawnEffect(unit);
|
spawnEffect(unit);
|
||||||
@ -82,7 +89,7 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
eachGroundSpawn(group.spawn, (spawnX, spawnY, doShockwave) -> {
|
eachGroundSpawn(group.spawn, (spawnX, spawnY, doShockwave) -> {
|
||||||
|
|
||||||
for(int i = 0; i < spawned; i++){
|
for(int i = 0; i < spawnedf; i++){
|
||||||
Tmp.v1.rnd(spread);
|
Tmp.v1.rnd(spread);
|
||||||
|
|
||||||
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
|
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
|
||||||
@ -153,7 +160,7 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
private void eachFlyerSpawn(int filterPos, Floatc2 cons){
|
private void eachFlyerSpawn(int filterPos, Floatc2 cons){
|
||||||
boolean airUseSpawns = state.rules.airUseSpawns;
|
boolean airUseSpawns = state.rules.airUseSpawns;
|
||||||
|
|
||||||
for(Tile tile : spawns){
|
for(Tile tile : spawns){
|
||||||
if(filterPos != -1 && filterPos != tile.pos()) continue;
|
if(filterPos != -1 && filterPos != tile.pos()) continue;
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ public class Blocks{
|
|||||||
|
|
||||||
//payloads
|
//payloads
|
||||||
payloadConveyor, payloadRouter, reinforcedPayloadConveyor, reinforcedPayloadRouter, payloadMassDriver, largePayloadMassDriver, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader,
|
payloadConveyor, payloadRouter, reinforcedPayloadConveyor, reinforcedPayloadRouter, payloadMassDriver, largePayloadMassDriver, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader,
|
||||||
|
|
||||||
//logic
|
//logic
|
||||||
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank,
|
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank,
|
||||||
canvas, reinforcedMessage,
|
canvas, reinforcedMessage,
|
||||||
@ -1282,7 +1282,7 @@ public class Blocks{
|
|||||||
itemCapacity = 0;
|
itemCapacity = 0;
|
||||||
consumePower(100f / 60f);
|
consumePower(100f / 60f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
slagHeater = new HeatProducer("slag-heater"){{
|
slagHeater = new HeatProducer("slag-heater"){{
|
||||||
requirements(Category.crafting, with(Items.tungsten, 50, Items.oxide, 20, Items.beryllium, 20));
|
requirements(Category.crafting, with(Items.tungsten, 50, Items.oxide, 20, Items.beryllium, 20));
|
||||||
|
|
||||||
@ -3405,7 +3405,7 @@ public class Blocks{
|
|||||||
lightningLength = 10;
|
lightningLength = 10;
|
||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
|
|
||||||
shoot = new ShootBarrel(){{
|
shoot = new ShootBarrel(){{
|
||||||
barrels = new float[]{
|
barrels = new float[]{
|
||||||
-4, -1.25f, 0,
|
-4, -1.25f, 0,
|
||||||
@ -5326,7 +5326,7 @@ public class Blocks{
|
|||||||
requirements(Category.units, with(Items.copper, 150, Items.lead, 130, Items.metaglass, 120));
|
requirements(Category.units, with(Items.copper, 150, Items.lead, 130, Items.metaglass, 120));
|
||||||
plans = Seq.with(
|
plans = Seq.with(
|
||||||
new UnitPlan(UnitTypes.risso, 60f * 45f, with(Items.silicon, 20, Items.metaglass, 35)),
|
new UnitPlan(UnitTypes.risso, 60f * 45f, with(Items.silicon, 20, Items.metaglass, 35)),
|
||||||
new UnitPlan(UnitTypes.retusa, 60f * 50f, with(Items.silicon, 15, Items.metaglass, 25, Items.titanium, 20))
|
new UnitPlan(UnitTypes.retusa, 60f * 35f, with(Items.silicon, 15, Items.titanium, 20))
|
||||||
);
|
);
|
||||||
size = 3;
|
size = 3;
|
||||||
consumePower(1.2f);
|
consumePower(1.2f);
|
||||||
@ -5930,7 +5930,7 @@ public class Blocks{
|
|||||||
|
|
||||||
worldCell = new MemoryBlock("world-cell"){{
|
worldCell = new MemoryBlock("world-cell"){{
|
||||||
requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
|
requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
|
||||||
|
|
||||||
targetable = false;
|
targetable = false;
|
||||||
privileged = true;
|
privileged = true;
|
||||||
memoryCapacity = 128;
|
memoryCapacity = 128;
|
||||||
@ -5939,7 +5939,7 @@ public class Blocks{
|
|||||||
|
|
||||||
worldMessage = new MessageBlock("world-message"){{
|
worldMessage = new MessageBlock("world-message"){{
|
||||||
requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
|
requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
|
||||||
|
|
||||||
targetable = false;
|
targetable = false;
|
||||||
privileged = true;
|
privileged = true;
|
||||||
}};
|
}};
|
||||||
|
@ -85,6 +85,8 @@ public class Planets{
|
|||||||
r.coreDestroyClear = true;
|
r.coreDestroyClear = true;
|
||||||
r.onlyDepositCore = true;
|
r.onlyDepositCore = true;
|
||||||
};
|
};
|
||||||
|
campaignRuleDefaults.fog = true;
|
||||||
|
campaignRuleDefaults.showSpawns = true;
|
||||||
|
|
||||||
unlockedOnLand.add(Blocks.coreBastion);
|
unlockedOnLand.add(Blocks.coreBastion);
|
||||||
}};
|
}};
|
||||||
|
@ -16,9 +16,9 @@ import mindustry.content.*;
|
|||||||
import mindustry.content.TechTree.*;
|
import mindustry.content.TechTree.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
|
import mindustry.game.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.Objectives.*;
|
import mindustry.game.Objectives.*;
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.game.Saves.*;
|
import mindustry.game.Saves.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
@ -30,7 +30,6 @@ import mindustry.net.*;
|
|||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.storage.*;
|
|
||||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -441,6 +440,7 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
state.wave = 1;
|
state.wave = 1;
|
||||||
//set up default wave time
|
//set up default wave time
|
||||||
state.wavetime = state.rules.initialWaveSpacing <= 0f ? (state.rules.waveSpacing * (sector.preset == null ? 2f : sector.preset.startWaveTimeMultiplier)) : state.rules.initialWaveSpacing;
|
state.wavetime = state.rules.initialWaveSpacing <= 0f ? (state.rules.waveSpacing * (sector.preset == null ? 2f : sector.preset.startWaveTimeMultiplier)) : state.rules.initialWaveSpacing;
|
||||||
|
state.wavetime *= sector.planet.campaignRules.difficulty.waveTimeMultiplier;
|
||||||
//reset captured state
|
//reset captured state
|
||||||
sector.info.wasCaptured = false;
|
sector.info.wasCaptured = false;
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ public class Logic implements ApplicationListener{
|
|||||||
if(wavesPassed > 0){
|
if(wavesPassed > 0){
|
||||||
//simulate wave counter moving forward
|
//simulate wave counter moving forward
|
||||||
state.wave += wavesPassed;
|
state.wave += wavesPassed;
|
||||||
state.wavetime = state.rules.waveSpacing;
|
state.wavetime = state.rules.waveSpacing * state.getPlanet().campaignRules.difficulty.waveTimeMultiplier;
|
||||||
|
|
||||||
SectorDamage.applyCalculatedDamage();
|
SectorDamage.applyCalculatedDamage();
|
||||||
}
|
}
|
||||||
@ -221,7 +221,7 @@ public class Logic implements ApplicationListener{
|
|||||||
public void play(){
|
public void play(){
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
//grace period of 2x wave time before game starts
|
//grace period of 2x wave time before game starts
|
||||||
state.wavetime = state.rules.initialWaveSpacing <= 0 ? state.rules.waveSpacing * 2 : state.rules.initialWaveSpacing;
|
state.wavetime = (state.rules.initialWaveSpacing <= 0 ? state.rules.waveSpacing * 2 : state.rules.initialWaveSpacing) * (state.isCampaign() ? state.getPlanet().campaignRules.difficulty.waveTimeMultiplier : 1f);;
|
||||||
Events.fire(new PlayEvent());
|
Events.fire(new PlayEvent());
|
||||||
|
|
||||||
//add starting items
|
//add starting items
|
||||||
@ -270,7 +270,7 @@ public class Logic implements ApplicationListener{
|
|||||||
public void runWave(){
|
public void runWave(){
|
||||||
spawner.spawnEnemies();
|
spawner.spawnEnemies();
|
||||||
state.wave++;
|
state.wave++;
|
||||||
state.wavetime = state.rules.waveSpacing;
|
state.wavetime = state.rules.waveSpacing * (state.isCampaign() ? state.getPlanet().campaignRules.difficulty.waveTimeMultiplier : 1f);
|
||||||
|
|
||||||
Events.fire(new WaveEvent());
|
Events.fire(new WaveEvent());
|
||||||
}
|
}
|
||||||
|
15
core/src/mindustry/game/CampaignRules.java
Normal file
15
core/src/mindustry/game/CampaignRules.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package mindustry.game;
|
||||||
|
|
||||||
|
public class CampaignRules{
|
||||||
|
public Difficulty difficulty = Difficulty.normal;
|
||||||
|
public boolean fog;
|
||||||
|
public boolean showSpawns;
|
||||||
|
public boolean sectorInvasion;
|
||||||
|
|
||||||
|
public void apply(Rules rules){
|
||||||
|
rules.staticFog = rules.fog = fog;
|
||||||
|
rules.showSpawns = showSpawns;
|
||||||
|
rules.teams.get(rules.waveTeam).blockHealthMultiplier = difficulty.enemyHealthMultiplier;
|
||||||
|
rules.teams.get(rules.waveTeam).unitHealthMultiplier = difficulty.enemyHealthMultiplier;
|
||||||
|
}
|
||||||
|
}
|
26
core/src/mindustry/game/Difficulty.java
Normal file
26
core/src/mindustry/game/Difficulty.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package mindustry.game;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
|
||||||
|
public enum Difficulty{
|
||||||
|
//TODO these need tweaks
|
||||||
|
easy(1f, 0.75f, 1.5f),
|
||||||
|
normal(1f, 1f, 1f),
|
||||||
|
hard(1.25f, 1.5f, 0.6f),
|
||||||
|
eradication(1.5f, 2f, 0.4f);
|
||||||
|
|
||||||
|
public static final Difficulty[] all = values();
|
||||||
|
|
||||||
|
//TODO add more fields
|
||||||
|
public float enemyHealthMultiplier, enemySpawnMultiplier, waveTimeMultiplier;
|
||||||
|
|
||||||
|
Difficulty(float enemyHealthMultiplier, float enemySpawnMultiplier, float waveTimeMultiplier){
|
||||||
|
this.enemySpawnMultiplier = enemySpawnMultiplier;
|
||||||
|
this.waveTimeMultiplier = waveTimeMultiplier;
|
||||||
|
this.enemyHealthMultiplier = enemyHealthMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String localized(){
|
||||||
|
return Core.bundle.get("difficulty." + name());
|
||||||
|
}
|
||||||
|
}
|
@ -252,7 +252,7 @@ public class Universe{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//queue random invasions
|
//queue random invasions
|
||||||
if(!sector.isAttacked() && sector.planet.allowSectorInvasion && sector.info.minutesCaptured > invasionGracePeriod && sector.info.hasSpawns){
|
if(!sector.isAttacked() && sector.planet.campaignRules.sectorInvasion && sector.info.minutesCaptured > invasionGracePeriod && sector.info.hasSpawns){
|
||||||
int count = sector.near().count(s -> s.hasEnemyBase() && !s.hasBase());
|
int count = sector.near().count(s -> s.hasEnemyBase() && !s.hasBase());
|
||||||
|
|
||||||
//invasion chance depends on # of nearby bases
|
//invasion chance depends on # of nearby bases
|
||||||
|
@ -19,6 +19,7 @@ import mindustry.gen.*;
|
|||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.graphics.g3d.*;
|
import mindustry.graphics.g3d.*;
|
||||||
import mindustry.graphics.g3d.PlanetGrid.*;
|
import mindustry.graphics.g3d.PlanetGrid.*;
|
||||||
|
import mindustry.io.*;
|
||||||
import mindustry.maps.generators.*;
|
import mindustry.maps.generators.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
@ -127,15 +128,21 @@ public class Planet extends UnlockableContent{
|
|||||||
public boolean allowWaves = false;
|
public boolean allowWaves = false;
|
||||||
/** If false, players are unable to land on this planet's numbered sectors. */
|
/** If false, players are unable to land on this planet's numbered sectors. */
|
||||||
public boolean allowLaunchToNumbered = true;
|
public boolean allowLaunchToNumbered = true;
|
||||||
|
/** If true, the player is allowed to change the difficulty/rules in the planet UI. */
|
||||||
|
public boolean allowCampaignRules = false;
|
||||||
/** Icon as displayed in the planet selection dialog. This is a string, as drawables are null at load time. */
|
/** Icon as displayed in the planet selection dialog. This is a string, as drawables are null at load time. */
|
||||||
public String icon = "planet";
|
public String icon = "planet";
|
||||||
/** Plays in the planet dialog when this planet is selected. */
|
/** Plays in the planet dialog when this planet is selected. */
|
||||||
public Music launchMusic = Musics.launch;
|
public Music launchMusic = Musics.launch;
|
||||||
/** Default core block for launching. */
|
/** Default core block for launching. */
|
||||||
public Block defaultCore = Blocks.coreShard;
|
public Block defaultCore = Blocks.coreShard;
|
||||||
|
/** Global difficulty/modifier settings for this planet's campaign. */
|
||||||
|
public CampaignRules campaignRules = new CampaignRules();
|
||||||
|
/** Defaults applied to the rules. */
|
||||||
|
public CampaignRules campaignRuleDefaults = new CampaignRules();
|
||||||
/** Sets up rules on game load for any sector on this planet. */
|
/** Sets up rules on game load for any sector on this planet. */
|
||||||
public Cons<Rules> ruleSetter = r -> {};
|
public Cons<Rules> ruleSetter = r -> {};
|
||||||
/** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system.*/
|
/** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system. */
|
||||||
public @Nullable Planet parent;
|
public @Nullable Planet parent;
|
||||||
/** The root parent of the whole solar system this planet is in. */
|
/** The root parent of the whole solar system this planet is in. */
|
||||||
public Planet solarSystem;
|
public Planet solarSystem;
|
||||||
@ -183,6 +190,7 @@ public class Planet extends UnlockableContent{
|
|||||||
|
|
||||||
//calculate solar system
|
//calculate solar system
|
||||||
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
|
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
|
||||||
|
allowCampaignRules = isVanilla();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Planet(String name, Planet parent, float radius, int sectorSize){
|
public Planet(String name, Planet parent, float radius, int sectorSize){
|
||||||
@ -200,17 +208,38 @@ public class Planet extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveRules(){
|
||||||
|
Core.settings.putJson(name + "-campaign-rules", campaignRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadRules(){
|
||||||
|
campaignRules = Core.settings.getJson(name + "-campaign-rules", CampaignRules.class, () -> campaignRules);
|
||||||
|
}
|
||||||
|
|
||||||
public @Nullable Sector getStartSector(){
|
public @Nullable Sector getStartSector(){
|
||||||
return sectors.size == 0 ? null : sectors.get(startSector);
|
return sectors.size == 0 ? null : sectors.get(startSector);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyRules(Rules rules){
|
public void applyRules(Rules rules){
|
||||||
|
applyRules(rules, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyRules(Rules rules, boolean customGame){
|
||||||
ruleSetter.get(rules);
|
ruleSetter.get(rules);
|
||||||
|
|
||||||
rules.attributes.clear();
|
rules.attributes.clear();
|
||||||
rules.attributes.add(defaultAttributes);
|
rules.attributes.add(defaultAttributes);
|
||||||
rules.env = defaultEnv;
|
rules.env = defaultEnv;
|
||||||
rules.planet = this;
|
rules.planet = this;
|
||||||
|
|
||||||
|
if(!customGame){
|
||||||
|
campaignRules.apply(rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyDefaultRules(CampaignRules rules){
|
||||||
|
JsonIO.copy(campaignRuleDefaults, rules);
|
||||||
|
rules.sectorInvasion = allowSectorInvasion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable Sector getLastSector(){
|
public @Nullable Sector getLastSector(){
|
||||||
@ -327,6 +356,9 @@ public class Planet extends UnlockableContent{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
|
applyDefaultRules(campaignRules);
|
||||||
|
loadRules();
|
||||||
|
|
||||||
if(techTree == null){
|
if(techTree == null){
|
||||||
techTree = TechTree.roots.find(n -> n.planet == this);
|
techTree = TechTree.roots.find(n -> n.planet == this);
|
||||||
}
|
}
|
||||||
|
86
core/src/mindustry/ui/dialogs/CampaignRulesDialog.java
Normal file
86
core/src/mindustry/ui/dialogs/CampaignRulesDialog.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package mindustry.ui.dialogs;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.scene.ui.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.game.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
|
||||||
|
public class CampaignRulesDialog extends BaseDialog{
|
||||||
|
Planet planet;
|
||||||
|
Table current;
|
||||||
|
|
||||||
|
public CampaignRulesDialog(){
|
||||||
|
super("@campaign.difficulty");
|
||||||
|
|
||||||
|
addCloseButton();
|
||||||
|
|
||||||
|
hidden(() -> {
|
||||||
|
if(planet != null){
|
||||||
|
planet.saveRules();
|
||||||
|
|
||||||
|
if(Vars.state.isGame() && Vars.state.isCampaign() && Vars.state.getPlanet() == planet){
|
||||||
|
planet.campaignRules.apply(Vars.state.rules);
|
||||||
|
Call.setRules(Vars.state.rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebuild(){
|
||||||
|
CampaignRules rules = planet.campaignRules;
|
||||||
|
cont.clear();
|
||||||
|
|
||||||
|
cont.top().pane(inner -> {
|
||||||
|
inner.top().left().defaults().fillX().left().pad(5);
|
||||||
|
current = inner;
|
||||||
|
|
||||||
|
current.table(Tex.button, t -> {
|
||||||
|
t.margin(10f);
|
||||||
|
var group = new ButtonGroup<>();
|
||||||
|
var style = Styles.flatTogglet;
|
||||||
|
|
||||||
|
t.defaults().size(140f, 50f);
|
||||||
|
|
||||||
|
for(Difficulty diff : Difficulty.all){
|
||||||
|
t.button(diff.localized(), style, () -> {
|
||||||
|
rules.difficulty = diff;
|
||||||
|
}).group(group).checked(b -> rules.difficulty == diff);
|
||||||
|
}
|
||||||
|
}).left().fill(false).expand(false, false).row();
|
||||||
|
|
||||||
|
if(planet.allowSectorInvasion){
|
||||||
|
check("@rules.invasions", b -> rules.sectorInvasion = b, () -> rules.sectorInvasion);
|
||||||
|
}
|
||||||
|
|
||||||
|
check("@rules.fog", b -> rules.fog = b, () -> rules.fog);
|
||||||
|
check("@rules.showspawns", b -> rules.showSpawns = b, () -> rules.showSpawns);
|
||||||
|
}).growY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(Planet planet){
|
||||||
|
this.planet = planet;
|
||||||
|
|
||||||
|
rebuild();
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void check(String text, Boolc cons, Boolp prov){
|
||||||
|
check(text, cons, prov, () -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check(String text, Boolc cons, Boolp prov, Boolp condition){
|
||||||
|
String infoText = text.substring(1) + ".info";
|
||||||
|
var cell = current.check(text, cons).checked(prov.get()).update(a -> a.setDisabled(!condition.get()));
|
||||||
|
if(Core.bundle.has(infoText)){
|
||||||
|
cell.tooltip(text + ".info");
|
||||||
|
}
|
||||||
|
cell.get().left();
|
||||||
|
current.row();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -329,7 +329,7 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
|
|
||||||
for(Planet planet : content.planets().select(p -> p.accessible && p.visible && p.isLandable())){
|
for(Planet planet : content.planets().select(p -> p.accessible && p.visible && p.isLandable())){
|
||||||
t.button(planet.localizedName, style, () -> {
|
t.button(planet.localizedName, style, () -> {
|
||||||
planet.applyRules(rules);
|
planet.applyRules(rules, true);
|
||||||
}).group(group).checked(b -> rules.planet == planet);
|
}).group(group).checked(b -> rules.planet == planet);
|
||||||
|
|
||||||
if(t.getChildren().size % 3 == 0){
|
if(t.getChildren().size % 3 == 0){
|
||||||
|
@ -67,10 +67,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
public Label hoverLabel = new Label("");
|
public Label hoverLabel = new Label("");
|
||||||
|
|
||||||
private Texture[] planetTextures;
|
private Texture[] planetTextures;
|
||||||
|
private CampaignRulesDialog campaignRules = new CampaignRulesDialog();
|
||||||
|
|
||||||
public PlanetDialog(){
|
public PlanetDialog(){
|
||||||
super("", Styles.fullDialog);
|
super("", Styles.fullDialog);
|
||||||
|
|
||||||
state.renderer = this;
|
state.renderer = this;
|
||||||
state.drawUi = true;
|
state.drawUi = true;
|
||||||
|
|
||||||
@ -387,7 +388,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
//preset sectors can only be selected once unlocked
|
//preset sectors can only be selected once unlocked
|
||||||
if(sector.preset != null){
|
if(sector.preset != null){
|
||||||
TechNode node = sector.preset.techNode;
|
TechNode node = sector.preset.techNode;
|
||||||
return node == null || node.parent == null || (node.parent.content.unlocked() && (!(node.parent.content instanceof SectorPreset preset) || preset.sector.hasBase()));
|
return sector.preset.unlocked() || node == null || node.parent == null || (node.parent.content.unlocked() && (!(node.parent.content instanceof SectorPreset preset) || preset.sector.hasBase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sector.planet.generator != null ?
|
return sector.planet.generator != null ?
|
||||||
@ -474,7 +475,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
if(state.uiAlpha > 0.001f){
|
if(state.uiAlpha > 0.001f){
|
||||||
for(Sector sec : planet.sectors){
|
for(Sector sec : planet.sectors){
|
||||||
if(sec.hasBase()){
|
if(sec.hasBase()){
|
||||||
if(planet.allowSectorInvasion){
|
if(planet.campaignRules.sectorInvasion){
|
||||||
for(Sector enemy : sec.near()){
|
for(Sector enemy : sec.near()){
|
||||||
if(enemy.hasEnemyBase()){
|
if(enemy.hasEnemyBase()){
|
||||||
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25);
|
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25);
|
||||||
@ -612,6 +613,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
t.top().left();
|
t.top().left();
|
||||||
ScrollPane pane = new ScrollPane(null, Styles.smallPane);
|
ScrollPane pane = new ScrollPane(null, Styles.smallPane);
|
||||||
t.add(pane).colspan(2).row();
|
t.add(pane).colspan(2).row();
|
||||||
|
t.button("@campaign.difficulty", Icon.bookSmall, () -> {
|
||||||
|
campaignRules.show(state.planet);
|
||||||
|
}).margin(12f).size(208f, 40f).padTop(12f).visible(() -> state.planet.allowCampaignRules).row();
|
||||||
|
t.add().height(64f); //padding for close button
|
||||||
Table starsTable = new Table(Styles.black);
|
Table starsTable = new Table(Styles.black);
|
||||||
pane.setWidget(starsTable);
|
pane.setWidget(starsTable);
|
||||||
pane.setScrollingDisabled(true, false);
|
pane.setScrollingDisabled(true, false);
|
||||||
@ -1133,7 +1138,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
|||||||
|
|
||||||
if(sector.isAttacked()){
|
if(sector.isAttacked()){
|
||||||
addSurvivedInfo(sector, stable, false);
|
addSurvivedInfo(sector, stable, false);
|
||||||
}else if(sector.hasBase() && sector.planet.allowSectorInvasion && sector.near().contains(Sector::hasEnemyBase)){
|
}else if(sector.hasBase() && sector.planet.campaignRules.sectorInvasion && sector.near().contains(Sector::hasEnemyBase)){
|
||||||
stable.add("@sectors.vulnerable");
|
stable.add("@sectors.vulnerable");
|
||||||
stable.row();
|
stable.row();
|
||||||
}else if(!sector.hasBase() && sector.hasEnemyBase()){
|
}else if(!sector.hasBase() && sector.hasEnemyBase()){
|
||||||
|
@ -32,5 +32,5 @@ public enum BlockFlag{
|
|||||||
public final static BlockFlag[] all = values();
|
public final static BlockFlag[] all = values();
|
||||||
|
|
||||||
/** Values for logic only. Filters out some internal flags. */
|
/** Values for logic only. Filters out some internal flags. */
|
||||||
public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, battery, reactor};
|
public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, battery, reactor, drill};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user