Various tweaks and speculative changes

This commit is contained in:
Anuken
2020-09-19 21:54:08 -04:00
parent cdd1e90d1a
commit b9fd38a76e
12 changed files with 66 additions and 54 deletions

View File

@@ -5,20 +5,14 @@ import arc.math.geom.*;
import mindustry.ai.formations.*; import mindustry.ai.formations.*;
public class CircleFormation extends FormationPattern{ public class CircleFormation extends FormationPattern{
/** The radius of one member. This is needed to determine how close we can pack a given number of members around circle. */
public float memberRadius;
/** Angle offset. */ /** Angle offset. */
public float angleOffset = 0; public float angleOffset = 0;
public CircleFormation(float memberRadius){
this.memberRadius = memberRadius;
}
@Override @Override
public Vec3 calculateSlotLocation(Vec3 outLocation, int slotNumber){ public Vec3 calculateSlotLocation(Vec3 outLocation, int slotNumber){
if(slots > 1){ if(slots > 1){
float angle = (360f * slotNumber) / slots; float angle = (360f * slotNumber) / slots;
float radius = memberRadius / (float)Math.sin(180f / slots * Mathf.degRad); float radius = spacing / (float)Math.sin(180f / slots * Mathf.degRad);
outLocation.set(Angles.trnsx(angle, radius), Angles.trnsy(angle, radius), angle); outLocation.set(Angles.trnsx(angle, radius), Angles.trnsy(angle, radius), angle);
}else{ }else{
outLocation.set(0, 0, 360f * slotNumber); outLocation.set(0, 0, 360f * slotNumber);

View File

@@ -2,10 +2,10 @@ package mindustry.ai.types;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import mindustry.*;
import mindustry.ai.formations.*; import mindustry.ai.formations.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.type.*;
public class FormationAI extends AIController implements FormationMember{ public class FormationAI extends AIController implements FormationMember{
public Unit leader; public Unit leader;
@@ -25,33 +25,33 @@ public class FormationAI extends AIController implements FormationMember{
@Override @Override
public void updateUnit(){ public void updateUnit(){
UnitType type = unit.type();
if(leader.dead){ if(leader.dead){
unit.resetController(); unit.resetController();
return; return;
} }
unit.controlWeapons(leader.isRotate(), leader.isShooting); unit.controlWeapons(true, leader.isShooting);
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed)); // unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));
if(leader.isShooting){
unit.aimLook(leader.aimX(), leader.aimY()); unit.aim(leader.aimX(), leader.aimY());
}else{
if(!leader.moving() || !unit.type().rotateShooting){ if(unit.type().rotateShooting){
if(unit.moving()){ unit.lookAt(leader.aimX(), leader.aimY());
unit.lookAt(unit.vel.angle()); }else if(unit.moving()){
} unit.lookAt(unit.vel.angle());
}else{
unit.lookAt(leader.rotation);
}
} }
Vec2 realtarget = vec.set(target); Vec2 realtarget = vec.set(target);
if(unit.isGrounded() && Vars.world.raycast(unit.tileX(), unit.tileY(), leader.tileX(), leader.tileY(), Vars.world::solid)){ float margin = 3f;
//TODO pathfind
//realtarget.set(Vars.pathfinder.getTargetTile(unit.tileOn(), unit.team, leader));
}
unit.moveAt(realtarget.sub(unit).limit(unit.type().speed)); if(unit.dst(realtarget) <= margin){
unit.vel.approachDelta(Vec2.ZERO, type.speed * type.accel / 2f);
}else{
unit.moveAt(realtarget.sub(unit).limit(type.speed));
}
} }
@Override @Override
@@ -68,7 +68,7 @@ public class FormationAI extends AIController implements FormationMember{
//TODO return formation size //TODO return formation size
//eturn ((Commanderc)unit).formation(). //eturn ((Commanderc)unit).formation().
} }
return unit.hitSize * 1.7f; return unit.hitSize * 1f;
} }
@Override @Override

View File

@@ -747,6 +747,7 @@ public class UnitTypes implements ContentList{
accel = 0.08f; accel = 0.08f;
drag = 0.016f; drag = 0.016f;
flying = true; flying = true;
hitsize = 9f;
targetAir = false; targetAir = false;
engineOffset = 7.8f; engineOffset = 7.8f;
range = 140f; range = 140f;

View File

@@ -338,8 +338,6 @@ public class NetClient implements ApplicationListener{
@Remote(variants = Variant.both) @Remote(variants = Variant.both)
public static void setRules(Rules rules){ public static void setRules(Rules rules){
state.rules = rules; state.rules = rules;
//campaign is not valid in multiplayer
state.rules.sector = null;
} }
@Remote(variants = Variant.both) @Remote(variants = Variant.both)
@@ -442,7 +440,7 @@ public class NetClient implements ApplicationListener{
} }
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true) @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, boolean gameOver, short coreDataLen, byte[] coreData){ public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, boolean gameOver, int timeData, short coreDataLen, byte[] coreData){
try{ try{
if(wave > state.wave){ if(wave > state.wave){
state.wave = wave; state.wave = wave;
@@ -455,6 +453,8 @@ public class NetClient implements ApplicationListener{
state.enemies = enemies; state.enemies = enemies;
state.serverPaused = paused; state.serverPaused = paused;
universe.updateNetSeconds(timeData);
netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen)); netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen));
DataInputStream input = netClient.dataStream; DataInputStream input = netClient.dataStream;

View File

@@ -846,7 +846,7 @@ public class NetServer implements ApplicationListener{
byte[] stateBytes = syncStream.toByteArray(); byte[] stateBytes = syncStream.toByteArray();
//write basic state data. //write basic state data.
Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, state.gameOver, (short)stateBytes.length, net.compressSnapshot(stateBytes)); Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, state.gameOver, universe.seconds(), (short)stateBytes.length, net.compressSnapshot(stateBytes));
viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY); viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);

View File

@@ -519,7 +519,7 @@ public class World{
dark = Math.max((edgeBlend - edgeDst) * (4f / edgeBlend), dark); dark = Math.max((edgeBlend - edgeDst) * (4f / edgeBlend), dark);
} }
if(state.hasSector()){ if(state.hasSector() && state.getSector().preset == null){
int circleBlend = 14; int circleBlend = 14;
//quantized angle //quantized angle
float offset = state.getSector().rect.rotation + 90; float offset = state.getSector().rect.rotation + 90;

View File

@@ -27,7 +27,7 @@ abstract class CommanderComp implements Unitc{
@Override @Override
public void update(){ public void update(){
if(formation != null){ if(formation != null){
formation.anchor.set(x, y, rotation); formation.anchor.set(x, y, /*rotation*/ 0); //TODO rotation set to 0 because rotating is pointless
formation.updateSlots(); formation.updateSlots();
} }
} }
@@ -73,7 +73,7 @@ abstract class CommanderComp implements Unitc{
void command(Formation formation, Seq<Unit> units){ void command(Formation formation, Seq<Unit> units){
clearCommand(); clearCommand();
float spacing = hitSize() * 1.7f; float spacing = hitSize() * 1f;
minFormationSpeed = type().speed; minFormationSpeed = type().speed;
controlling.addAll(units); controlling.addAll(units);

View File

@@ -87,6 +87,9 @@ public class SectorInfo{
/** Update averages of various stats, updates some special sector logic. /** Update averages of various stats, updates some special sector logic.
* Called every frame. */ * Called every frame. */
public void update(){ public void update(){
//updating in multiplayer as a client doesn't make sense
if(net.client()) return;
internalTimeSpent += Time.delta; internalTimeSpent += Time.delta;
//create last stored core items //create last stored core items

View File

@@ -14,7 +14,8 @@ import static mindustry.Vars.*;
/** Updates and handles state of the campaign universe. Has no relevance to other gamemodes. */ /** Updates and handles state of the campaign universe. Has no relevance to other gamemodes. */
public class Universe{ public class Universe{
private long seconds; private int seconds;
private int netSeconds;
private float secondCounter; private float secondCounter;
private int turn; private int turn;
@@ -76,15 +77,19 @@ public class Universe{
/** Update planet rotations, global time and relevant state. */ /** Update planet rotations, global time and relevant state. */
public void update(){ public void update(){
secondCounter += Time.delta / 60f;
if(secondCounter >= 1){ //only update time when not in multiplayer
seconds += (int)secondCounter; if(!net.client()){
secondCounter %= 1f; secondCounter += Time.delta / 60f;
//save every few seconds if(secondCounter >= 1){
if(seconds % 10 == 1){ seconds += (int)secondCounter;
save(); secondCounter %= 1f;
//save every few seconds
if(seconds % 10 == 1){
save();
}
} }
} }
@@ -191,25 +196,30 @@ public class Universe{
return count; return count;
} }
public float secondsMod(float mod, float scale){ public void updateNetSeconds(int value){
return (seconds / scale) % mod; netSeconds = value;
} }
public long seconds(){ public float secondsMod(float mod, float scale){
return seconds; return (seconds() / scale) % mod;
}
public int seconds(){
//use networked seconds when playing as client
return net.client() ? netSeconds : seconds;
} }
public float secondsf(){ public float secondsf(){
return seconds + secondCounter; return seconds() + secondCounter;
} }
private void save(){ private void save(){
Core.settings.put("utime", seconds); Core.settings.put("utimei", seconds);
Core.settings.put("turn", turn); Core.settings.put("turn", turn);
} }
private void load(){ private void load(){
seconds = Core.settings.getLong("utime"); seconds = Core.settings.getInt("utimei");
turn = Core.settings.getInt("turn"); turn = Core.settings.getInt("turn");
} }

View File

@@ -324,7 +324,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
commander.clearCommand(); commander.clearCommand();
}else{ }else{
commander.commandNearby(new SquareFormation()); //TODO try out some other formations
commander.commandNearby(new CircleFormation());
Fx.commandSend.at(player); Fx.commandSend.at(player);
} }

View File

@@ -42,8 +42,6 @@ public class NetworkIO{
try(DataInputStream stream = new DataInputStream(is)){ try(DataInputStream stream = new DataInputStream(is)){
Time.clear(); Time.clear();
state.rules = JsonIO.read(Rules.class, stream.readUTF()); state.rules = JsonIO.read(Rules.class, stream.readUTF());
//campaign is not valid in multiplayer
state.rules.sector = null;
state.map = new Map(SaveIO.getSaveWriter().readStringMap(stream)); state.map = new Map(SaveIO.getSaveWriter().readStringMap(stream));
state.wave = stream.readInt(); state.wave = stream.readInt();

View File

@@ -97,7 +97,7 @@ public class LaunchPad extends Block{
//launch when full and base conditions are met //launch when full and base conditions are met
if(items.total() >= itemCapacity && efficiency() >= 1f && timer(timerLaunch, launchTime / timeScale)){ if(items.total() >= itemCapacity && efficiency() >= 1f && timer(timerLaunch, launchTime / timeScale)){
LaunchPayload entity = LaunchPayload.create(); LaunchPayload entity = LaunchPayload.create();
items.each((item, amount) -> entity.stacks().add(new ItemStack(item, amount))); items.each((item, amount) -> entity.stacks.add(new ItemStack(item, amount)));
entity.set(this); entity.set(this);
entity.lifetime(120f); entity.lifetime(120f);
entity.team(team); entity.team(team);
@@ -174,9 +174,14 @@ public class LaunchPad extends Block{
@Override @Override
public void remove(){ public void remove(){
if(!state.isCampaign()) return;
//on multiplayer the destination is a the first captured sector (basically random)
Sector destsec = !net.client() ? state.secinfo.origin : state.rules.sector.planet.sectors.find(Sector::hasBase);
//actually launch the items upon removal //actually launch the items upon removal
if(team() == state.rules.defaultTeam && state.secinfo.origin != null){ if(team() == state.rules.defaultTeam && destsec != null){
ItemSeq dest = state.secinfo.origin.getExtraItems(); ItemSeq dest = destsec.getExtraItems();
for(ItemStack stack : stacks){ for(ItemStack stack : stacks){
dest.add(stack); dest.add(stack);
@@ -186,7 +191,7 @@ public class LaunchPad extends Block{
Events.fire(new LaunchItemEvent(stack)); Events.fire(new LaunchItemEvent(stack));
} }
state.secinfo.origin.setExtraItems(dest); destsec.setExtraItems(dest);
} }
} }
} }