mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-01-25 05:51:47 -08:00
Turn logic / Cross-sector production / Pad tweaks
This commit is contained in:
parent
603cb4295a
commit
b68e0a8562
16 changed files with 188 additions and 39 deletions
|
|
@ -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}]}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, () -> {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue