Turn logic / Cross-sector production / Pad tweaks

This commit is contained in:
Anuken 2020-05-15 11:03:21 -04:00
parent 603cb4295a
commit b68e0a8562
16 changed files with 188 additions and 39 deletions

View file

@ -0,0 +1 @@
{version:2,fields:[{name:lifetime,type:float,size:4},{name:stacks,type:arc.struct.Array<mindustry.type.ItemStack>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View file

@ -80,7 +80,7 @@ public class Vars implements Loadable{
public static final float miningRange = 70f;
/** range for building */
public static final float buildingRange = 220f;
/** duration of one turn. */
/** duration of one turn in ticks */
public static final float turnDuration = 5 * Time.toMinutes;
/** for map generator dialog */
public static boolean updateEditorOnChange = false;

View file

@ -1320,7 +1320,7 @@ public class Blocks implements ContentList{
requirements(Category.effect, BuildVisibility.campaignOnly, ItemStack.with(Items.copper, 250, Items.silicon, 75, Items.lead, 100));
size = 3;
itemCapacity = 100;
launchTime = 60f * 2;
launchTime = 60*3;//60f * 15;
hasPower = true;
consumes.power(4f);
}};

View file

@ -159,6 +159,12 @@ public class Fx{
Fill.circle(e.x, e.y, (7f - e.fin() * 7f)/2f);
}),
rocketSmoke = new Effect(120, e -> {
color(Color.gray);
alpha(Mathf.clamp(e.fout()*1.6f - e.rotation*0.8f));
Fill.circle(e.x, e.y, (1f + 6f * e.rotation) - e.fin()*2f);
}),
magmasmoke = new Effect(110, e -> {
color(Color.gray);
Fill.circle(e.x, e.y, e.fslope() * 6f);

View file

@ -225,8 +225,8 @@ public class Renderer implements ApplicationListener{
}
if(bloom != null){
Draw.draw(Layer.bullet - 0.001f, bloom::capture);
Draw.draw(Layer.effect + 0.001f, bloom::render);
Draw.draw(Layer.bullet - 0.01f, bloom::capture);
Draw.draw(Layer.effect + 0.01f, bloom::render);
}
Draw.z(Layer.plans);

View file

@ -30,10 +30,12 @@ abstract class BuilderComp implements Unitc{
Queue<BuildRequest> requests = new Queue<>();
transient float buildSpeed = 1f;
//boolean building;
transient boolean building = true;
@Override
public void update(){
if(!building) return;
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
Iterator<BuildRequest> it = requests.iterator();

View file

@ -167,7 +167,7 @@ public class Saves{
public class SaveSlot{
public final Fi file;
boolean requestedPreview;
SaveMeta meta;
public SaveMeta meta;
public SaveSlot(Fi file){
this.file = file;
@ -242,6 +242,10 @@ public class Saves{
return isSector();
}
public ObjectFloatMap<Item> getProductionRates(){
return meta.productionRates;
}
public String getPlayTime(){
return Strings.formatMillis(current == this ? totalPlaytime : meta.timePlayed);
}

View file

@ -5,8 +5,6 @@ import arc.struct.*;
import arc.util.*;
import mindustry.type.*;
import java.util.*;
import static mindustry.Vars.content;
public class Stats{
@ -30,36 +28,44 @@ public class Stats{
/** Friendly buildings destroyed. */
public int buildingsDestroyed;
/** Item production means. Holds means per period. */
private transient WindowedMean[] itemExport = new WindowedMean[content.items().size];
/** Counters of items recieved this period. */
private transient float[] itemCounters = new float[content.items().size];
/** Counter refresh state. */
private transient Interval time = new Interval();
public Stats(){
for(int i = 0; i < itemExport.length; i++){
itemExport[i] = new WindowedMean(exportWindow);
}
}
/** Export statistics. */
public ObjectMap<Item, ProductionStat> production = new ObjectMap<>();
/** Updates export statistics. */
public void handleItemExport(ItemStack stack){
itemCounters[stack.item.id] += stack.amount;
production.getOr(stack.item, ProductionStat::new).counter += stack.amount;
}
public float getExport(Item item){
return production.getOr(item, ProductionStat::new).mean;
}
public void update(){
//refresh throughput
if(time.get(refreshPeriod)){
for(int i = 0; i < itemCounters.length; i++){
itemExport[i].add(itemCounters[i]);
}
for(ProductionStat stat : production.values()){
//initialize stat after loading
if(!stat.loaded){
stat.means.fill(stat.mean);
stat.loaded = true;
}
Arrays.fill(itemCounters, 0);
stat.means.add(stat.counter);
stat.counter = 0;
stat.mean = stat.means.rawMean();
}
}
}
public ObjectFloatMap<Item> productionRates(){
ObjectFloatMap<Item> map = new ObjectFloatMap<>();
production.each((item, value) -> map.put(item, value.mean));
return map;
}
public RankResult calculateRank(Sector zone, boolean launched){
float score = 0;
@ -106,7 +112,15 @@ public class Stats{
}
}
public enum Rank{
F, D, C, B, A, S, SS
}
public static class ProductionStat{
public transient float counter;
public transient WindowedMean means = new WindowedMean(content.items().size);
public transient boolean loaded;
public float mean;
}
}

View file

@ -2,8 +2,10 @@ package mindustry.game;
import arc.*;
import arc.math.*;
import arc.struct.ObjectFloatMap.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.io.*;
import mindustry.type.*;
import static mindustry.Vars.*;
@ -69,7 +71,24 @@ public class Universe{
}
private void onTurn(){
//create a random event here, e.g. invasion
//TODO run waves on hostile sectors, damage them
//calculate passive items
for(Planet planet : content.planets()){
for(Sector sector : planet.sectors){
if(sector.hasSave()){
SaveMeta meta = sector.save.meta;
for(Entry<Item> entry : meta.productionRates){
//total is calculated by items/sec (value) * turn duration in seconds
int total = (int)(entry.value * turnDuration / 60f);
//add the items to global data
data.addItem(entry.key, total);
}
}
}
}
}
public float secondsMod(float mod, float scale){

View file

@ -199,6 +199,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public void update(){
player.typing(ui.chatfrag.shown());
if(player.isBuilder()){
player.builder().building(isBuilding);
}
if(!player.dead()){
controlledType = player.unit().type();
}

View file

@ -3,6 +3,7 @@ package mindustry.io;
import arc.struct.*;
import mindustry.game.*;
import mindustry.maps.*;
import mindustry.type.*;
import static mindustry.Vars.maps;
@ -16,8 +17,11 @@ public class SaveMeta{
public Rules rules;
public StringMap tags;
public String[] mods;
/** These are in items/second. */
public ObjectFloatMap<Item> productionRates;
public boolean hasProduction;
public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, StringMap tags){
public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, ObjectFloatMap<Item> productionRates, StringMap tags){
this.version = version;
this.build = build;
this.timestamp = timestamp;
@ -27,5 +31,8 @@ public class SaveMeta{
this.rules = rules;
this.tags = tags;
this.mods = JsonIO.read(String[].class, tags.get("mods", "[]"));
this.productionRates = productionRates;
productionRates.each(e -> hasProduction |= e.value > 0.001f);
}
}

View file

@ -31,7 +31,17 @@ public abstract class SaveVersion extends SaveFileReader{
public SaveMeta getMeta(DataInput stream) throws IOException{
stream.readInt(); //length of data, doesn't matter here
StringMap map = readStringMap(stream);
return new SaveMeta(map.getInt("version"), map.getLong("saved"), map.getLong("playtime"), map.getInt("build"), map.get("mapname"), map.getInt("wave"), JsonIO.read(Rules.class, map.get("rules", "{}")), map);
return new SaveMeta(
map.getInt("version"),
map.getLong("saved"),
map.getLong("playtime"),
map.getInt("build"),
map.get("mapname"),
map.getInt("wave"),
JsonIO.read(Rules.class, map.get("rules", "{}")),
JsonIO.read(Stats.class, map.get("stats", "{}")).productionRates(),
map
);
}
@Override

View file

@ -39,6 +39,10 @@ public class Sector{
this.data = data;
}
public boolean hasSave(){
return save != null;
}
public void generate(){
//TODO use simplex and a seed
hostility = Math.max(Noise.snoise3(tile.v.x, tile.v.y, tile.v.z, 1f, 0.5f), 0);

View file

@ -273,11 +273,11 @@ public class PlanetDialog extends FloatingDialog{
}
if(sec.hostility >= 0.02f){
drawSelection(sec, Color.scarlet, 0.11f * sec.hostility, 0.0001f);
drawSelection(sec, Color.scarlet, 0.11f * sec.hostility, -0.02f);
}
if(sec.save != null){
drawSelection(sec, Color.lime, 0.03f, 0.0009f);
drawSelection(sec, Color.lime, 0.03f, -0.01f);
}
}
@ -355,6 +355,25 @@ public class PlanetDialog extends FloatingDialog{
}
}).fillX().row();
//production
if(selected.hasSave() && selected.save.meta.hasProduction){
stable.add("Production:").row();
stable.table(t -> {
t.left();
selected.save.meta.productionRates.each(entry -> {
int total = (int)(entry.value * turnDuration / 60f);
if(total > 1){
t.image(entry.key.icon(Cicon.small)).padRight(3);
t.add(ui.formatAmount(total) + " /turn").color(Color.lightGray);
t.row();
}
});
});
}
stable.row();
stable.button("Launch", Styles.transt, () -> {

View file

@ -21,6 +21,7 @@ import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.input.*;
import mindustry.net.Packets.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*;
@ -296,6 +297,41 @@ public class HudFragment extends Fragment{
p.touchable(Touchable.disabled);
});
//DEBUG: rate table
parent.fill(t -> {
t.bottom().left();
t.table(Styles.black6, c -> {
Bits used = new Bits(content.items().size);
Runnable rebuild = () -> {
c.clearChildren();
for(Item item : content.items()){
if(state.stats.getExport(item) >= 1){
c.image(item.icon(Cicon.small));
c.label(() -> (int)state.stats.getExport(item) + " /s").color(Color.lightGray);
c.row();
}
}
};
c.update(() -> {
boolean wrong = false;
for(Item item : content.items()){
boolean has = state.stats.getExport(item) >= 1;
if(used.get(item.id) != has){
used.set(item.id, has);
wrong = true;
}
}
if(wrong){
rebuild.run();
}
});
});
});
blockfrag.build(parent);
}

View file

@ -72,7 +72,7 @@ public class LaunchPad extends Block{
Draw.reset();
}
float cooldown = Mathf.clamp(timer.getTime(timerLaunch) / 60f);
float cooldown = Mathf.clamp(timer.getTime(timerLaunch) / 90f);
Draw.mixcol(lightColor, 1f - cooldown);
@ -109,48 +109,71 @@ public class LaunchPad extends Block{
@Import float x,y;
Array<ItemStack> stacks = new Array<>();
transient Interval in = new Interval();
@Override
public void draw(){
float alpha = fout(Interp.pow5Out);
float cx = x + fin(Interp.pow2In) * 15f, cy = y + fin(Interp.pow5In) * 130f;
float rotation = fin() * 120f;
float scale = (1f - alpha) * 1.3f + 1f;
float cx = cx(), cy = cy();
float rotation = fin() * (130f + Mathf.randomSeedRange(id(), 50f));
Draw.z(Layer.effect);
Draw.z(Layer.effect + 0.001f);
Draw.color(Pal.engine);
float rad = 0.2f + fslope();
Fill.light(cx, cy, 10, 25f * rad, Tmp.c2.set(Pal.engine), Tmp.c1.set(Pal.engine).a(0f));
Fill.light(cx, cy, 10, 25f * (rad + scale-1f), Tmp.c2.set(Pal.engine).a(alpha), Tmp.c1.set(Pal.engine).a(0f));
Draw.alpha(alpha);
for(int i = 0; i < 4; i++){
Drawf.tri(cx, cy, 6f, 40f * rad, i * 90f + rotation);
Drawf.tri(cx, cy, 6f, 40f * (rad + scale-1f), i * 90f + rotation);
}
Draw.color();
Draw.z(Layer.weather - 1);
Draw.alpha(alpha);
Draw.rect("launchpod", cx, cy, rotation);
TextureRegion region = Core.atlas.find("launchpod");
float rw = region.getWidth() * Draw.scl * scale, rh = region.getHeight() * Draw.scl * scale;
Tmp.v1.trns(225f, fin(Interp.linear) * 250f);
Draw.alpha(alpha);
Draw.rect(region, cx, cy, rw, rh, rotation);
Tmp.v1.trns(225f, fin(Interp.pow3In) * 250f);
Draw.z(Layer.flyingUnit + 1);
Draw.color(0, 0, 0, 0.22f * alpha);
Draw.rect("launchpod", cx + Tmp.v1.x, cy + Tmp.v1.y, rotation);
Draw.rect(region, cx + Tmp.v1.x, cy + Tmp.v1.y, rw, rh, rotation);
Draw.reset();
}
float cx(){
return x + fin(Interp.pow2In) * (12f + Mathf.randomSeedRange(id() + 3, 4f));
}
float cy(){
return y + fin(Interp.pow5In) * (100f + Mathf.randomSeedRange(id() + 2, 30f));
}
@Override
public void update(){
float r = 3f;
if(in.get(4f - fin()*2f)){
Fx.rocketSmoke.at(cx() + Mathf.range(r), cy() + Mathf.range(r), fin());
}
}
@Override
public void remove(){
//actually launch the items upon removal
if(team() == Vars.state.rules.defaultTeam){
for(ItemStack stack : stacks){
Vars.data.addItem(stack.item, stack.amount);
Events.fire(new LaunchItemEvent(stack));
Vars.state.stats.handleItemExport(stack);
}
}
}