mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-04-27 07:50:54 -07:00
Better fog / Research cost tweaks
This commit is contained in:
parent
c5ec8ff3ce
commit
895fa784cf
17 changed files with 158 additions and 117 deletions
|
|
@ -8,5 +8,5 @@ varying vec2 v_texCoords;
|
|||
|
||||
void main(){
|
||||
vec4 color = texture2D(u_texture, v_texCoords.xy);
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0 - floor(color.r / QUANT) * QUANT);
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, (1.0 - floor(color.r / QUANT) * QUANT) * (step(color.r, 0.99))) * v_color;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package mindustry.ai.types;
|
|||
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
|
|
@ -35,7 +35,7 @@ public class HugAI extends AIController{
|
|||
}
|
||||
|
||||
//raycast for target
|
||||
if(target != null && unit.within(target, unit.type.range) && !Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
||||
if(target != null && unit.within(target, unit.type.range) && !World.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
||||
for(Point2 p : Geometry.d4c){
|
||||
if(!unit.canPass(x + p.x, y + p.y)){
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mindustry.ai.types;
|
|||
import arc.math.geom.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
|
@ -48,7 +49,7 @@ public class SuicideAI extends GroundAI{
|
|||
blockedByBlock = false;
|
||||
|
||||
//raycast for target
|
||||
boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
||||
boolean blocked = World.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> {
|
||||
for(Point2 p : Geometry.d4c){
|
||||
Tile tile = Vars.world.tile(x + p.x, y + p.y);
|
||||
if(tile != null && tile.build == target) return false;
|
||||
|
|
|
|||
|
|
@ -925,6 +925,7 @@ public class Blocks{
|
|||
envDisabled = Env.none;
|
||||
itemCapacity = 30;
|
||||
drawer = new DrawArcSmelter();
|
||||
researchCostMultiplier = 0.3f;
|
||||
|
||||
consumeItems(with(Items.graphite, 1, Items.sand, 4));
|
||||
consumePower(6f);
|
||||
|
|
@ -2481,7 +2482,7 @@ public class Blocks{
|
|||
cliffCrusher = new WallCrafter("cliff-crusher"){{
|
||||
requirements(Category.production, with(Items.graphite, 25, Items.beryllium, 20));
|
||||
|
||||
consumePower(0.8f);
|
||||
consumePower(11 / 60f);
|
||||
|
||||
drillTime = 110f;
|
||||
size = 2;
|
||||
|
|
|
|||
|
|
@ -375,54 +375,6 @@ public class World{
|
|||
if(invalidMap) Core.app.post(() -> state.set(State.menu));
|
||||
}
|
||||
|
||||
public void raycastEachWorld(float x0, float y0, float x1, float y1, Raycaster cons){
|
||||
raycastEach(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons);
|
||||
}
|
||||
|
||||
public void raycastEach(int x1, int y1, int x2, int y2, Raycaster cons){
|
||||
int x = x1, dx = Math.abs(x2 - x), sx = x < x2 ? 1 : -1;
|
||||
int y = y1, dy = Math.abs(y2 - y), sy = y < y2 ? 1 : -1;
|
||||
int e2, err = dx - dy;
|
||||
|
||||
while(true){
|
||||
if(cons.accept(x, y)) break;
|
||||
if(x == x2 && y == y2) break;
|
||||
|
||||
e2 = 2 * err;
|
||||
if(e2 > -dy){
|
||||
err -= dy;
|
||||
x += sx;
|
||||
}
|
||||
|
||||
if(e2 < dx){
|
||||
err += dx;
|
||||
y += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean raycast(int x1, int y1, int x2, int y2, Raycaster cons){
|
||||
int x = x1, dx = Math.abs(x2 - x), sx = x < x2 ? 1 : -1;
|
||||
int y = y1, dy = Math.abs(y2 - y), sy = y < y2 ? 1 : -1;
|
||||
int e2, err = dx - dy;
|
||||
|
||||
while(true){
|
||||
if(cons.accept(x, y)) return true;
|
||||
if(x == x2 && y == y2) return false;
|
||||
|
||||
e2 = 2 * err;
|
||||
if(e2 > -dy){
|
||||
err = err - dy;
|
||||
x = x + sx;
|
||||
}
|
||||
|
||||
if(e2 < dx){
|
||||
err = err + dx;
|
||||
y = y + sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addDarkness(Tiles tiles){
|
||||
byte[] dark = new byte[tiles.width * tiles.height];
|
||||
byte[] writeBuffer = new byte[tiles.width * tiles.height];
|
||||
|
|
@ -547,6 +499,54 @@ public class World{
|
|||
return dark;
|
||||
}
|
||||
|
||||
public static void raycastEachWorld(float x0, float y0, float x1, float y1, Raycaster cons){
|
||||
raycastEach(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons);
|
||||
}
|
||||
|
||||
public static void raycastEach(int x1, int y1, int x2, int y2, Raycaster cons){
|
||||
int x = x1, dx = Math.abs(x2 - x), sx = x < x2 ? 1 : -1;
|
||||
int y = y1, dy = Math.abs(y2 - y), sy = y < y2 ? 1 : -1;
|
||||
int e2, err = dx - dy;
|
||||
|
||||
while(true){
|
||||
if(cons.accept(x, y)) break;
|
||||
if(x == x2 && y == y2) break;
|
||||
|
||||
e2 = 2 * err;
|
||||
if(e2 > -dy){
|
||||
err -= dy;
|
||||
x += sx;
|
||||
}
|
||||
|
||||
if(e2 < dx){
|
||||
err += dx;
|
||||
y += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean raycast(int x1, int y1, int x2, int y2, Raycaster cons){
|
||||
int x = x1, dx = Math.abs(x2 - x), sx = x < x2 ? 1 : -1;
|
||||
int y = y1, dy = Math.abs(y2 - y), sy = y < y2 ? 1 : -1;
|
||||
int e2, err = dx - dy;
|
||||
|
||||
while(true){
|
||||
if(cons.accept(x, y)) return true;
|
||||
if(x == x2 && y == y2) return false;
|
||||
|
||||
e2 = 2 * err;
|
||||
if(e2 > -dy){
|
||||
err = err - dy;
|
||||
x = x + sx;
|
||||
}
|
||||
|
||||
if(e2 < dx){
|
||||
err = err + dx;
|
||||
y = y + sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Context implements WorldContext{
|
||||
|
||||
Context(){}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public class Damage{
|
|||
public static @Nullable Building findAbsorber(Team team, float x1, float y1, float x2, float y2){
|
||||
tmpBuilding = null;
|
||||
|
||||
boolean found = world.raycast(World.toTile(x1), World.toTile(y1), World.toTile(x2), World.toTile(y2),
|
||||
boolean found = World.raycast(World.toTile(x1), World.toTile(y1), World.toTile(x2), World.toTile(y2),
|
||||
(x, y) -> (tmpBuilding = world.build(x, y)) != null && tmpBuilding.team != team && tmpBuilding.block.absorbLasers);
|
||||
|
||||
return found ? tmpBuilding : null;
|
||||
|
|
@ -136,7 +136,7 @@ public class Damage{
|
|||
|
||||
furthest = null;
|
||||
|
||||
boolean found = world.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
|
||||
boolean found = World.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
|
||||
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && (furthest.build != null && furthest.build.absorbLasers()));
|
||||
|
||||
return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
|
||||
|
|
@ -148,7 +148,7 @@ public class Damage{
|
|||
furthest = null;
|
||||
pierceCount = 0;
|
||||
|
||||
boolean found = world.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
|
||||
boolean found = World.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
|
||||
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.build != null && furthest.team() != b.team && ++pierceCount >= pierceCap);
|
||||
|
||||
return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
|
||||
|
|
@ -222,7 +222,7 @@ public class Damage{
|
|||
if(hitter.type.collidesGround){
|
||||
seg1.set(x, y);
|
||||
seg2.set(seg1).add(tr);
|
||||
world.raycastEachWorld(x, y, seg2.x, seg2.y, (cx, cy) -> {
|
||||
World.raycastEachWorld(x, y, seg2.x, seg2.y, (cx, cy) -> {
|
||||
collider.get(cx, cy);
|
||||
|
||||
for(Point2 p : Geometry.d4){
|
||||
|
|
@ -294,7 +294,7 @@ public class Damage{
|
|||
tmpBuilding = null;
|
||||
|
||||
if(hitter.type.collidesGround){
|
||||
world.raycastEachWorld(x, y, x + tr.x, y + tr.y, (cx, cy) -> {
|
||||
World.raycastEachWorld(x, y, x + tr.x, y + tr.y, (cx, cy) -> {
|
||||
Building tile = world.build(cx, cy);
|
||||
if(tile != null && tile.team != hitter.team){
|
||||
tmpBuilding = tile;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public class Lightning{
|
|||
bhit = false;
|
||||
Vec2 from = lines.get(lines.size - 2);
|
||||
Vec2 to = lines.get(lines.size - 1);
|
||||
world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
|
||||
World.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
|
||||
|
||||
Tile tile = world.tile(wx, wy);
|
||||
if(tile != null && (tile.build != null && tile.build.isInsulated()) && tile.team() != team){
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ abstract class TeamComp implements Posc{
|
|||
return team.rules().cheat;
|
||||
}
|
||||
|
||||
/** @return whether the center of this entity is visible to the viewing team. */
|
||||
boolean inFogTo(Team viewer){
|
||||
return this.team != viewer && !fogControl.isVisible(viewer, x, y);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CoreBuild core(){
|
||||
return team.core();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import arc.struct.*;
|
|||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.io.SaveFileReader.*;
|
||||
|
|
@ -63,7 +64,7 @@ public class FogControl implements CustomChunk{
|
|||
if(state.rules.fog && event.tile.build != null && event.tile.isCenter() && !event.tile.build.team.isAI() && event.tile.block().flags.contains(BlockFlag.hasFogRadius)){
|
||||
var data = data(event.tile.team());
|
||||
if(data != null){
|
||||
data.dynamicUpdated = data.dynamicUpdatedClient = true;
|
||||
data.dynamicUpdated = true;
|
||||
}
|
||||
|
||||
synchronized(staticEvents){
|
||||
|
|
@ -78,7 +79,7 @@ public class FogControl implements CustomChunk{
|
|||
if(state.rules.fog && e.tile.build != null && !e.tile.build.team.isAI() && e.tile.block().flags.contains(BlockFlag.hasFogRadius)){
|
||||
var data = data(e.tile.team());
|
||||
if(data != null){
|
||||
data.dynamicUpdated = data.dynamicUpdatedClient = true;
|
||||
data.dynamicUpdated = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -90,11 +91,16 @@ public class FogControl implements CustomChunk{
|
|||
return fog == null || fog[team.id] == null ? null : fog[team.id].staticData;
|
||||
}
|
||||
|
||||
public boolean isVisible(Team team, int x, int y){
|
||||
public boolean isVisible(Team team, float x, float y){
|
||||
return isVisibleTile(team, World.toTile(x), World.toTile(y));
|
||||
}
|
||||
|
||||
public boolean isVisibleTile(Team team, int x, int y){
|
||||
if(!state.rules.fog) return true;
|
||||
|
||||
var data = data(team);
|
||||
if(data == null || x < 0 || y < 0 || x >= ww || y >= wh) return false;
|
||||
if(data == null) return true;
|
||||
if(x < 0 || y < 0 || x >= ww || y >= wh) return false;
|
||||
return data.read.get(x + y * ww);
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +167,7 @@ public class FogControl implements CustomChunk{
|
|||
|
||||
if(data == null){
|
||||
data = fog[team.team.id] = new FogData();
|
||||
data.dynamicUpdated = data.dynamicUpdatedClient = true;
|
||||
data.dynamicUpdated = true;
|
||||
}
|
||||
|
||||
synchronized(staticEvents){
|
||||
|
|
@ -176,27 +182,21 @@ public class FogControl implements CustomChunk{
|
|||
if(unit.lastFogPos != pos){
|
||||
pushEvent(event);
|
||||
unit.lastFogPos = pos;
|
||||
data.dynamicUpdated = data.dynamicUpdatedClient = true;
|
||||
data.dynamicUpdated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add building updates (TODO this can run in the if-check, but the renderer needs it...)
|
||||
for(var build : indexer.getFlagged(team.team, BlockFlag.hasFogRadius)){
|
||||
unitEventQueue.add(FogEvent.get(build.tile.x, build.tile.y, build.block.fogRadius, 0));
|
||||
}
|
||||
|
||||
//on the client, let the renderer know of all the fog sources
|
||||
if(data.dynamicUpdatedClient && !headless && team.team == Vars.player.team()){
|
||||
renderer.fog.flushDynamic(unitEventQueue);
|
||||
data.dynamicUpdatedClient = false;
|
||||
}
|
||||
|
||||
//if it's time for an update, flush *everything* onto the update queue
|
||||
if(data.dynamicUpdated && Time.timeSinceMillis(data.lastDynamicMs) > staticUpdateInterval){
|
||||
data.dynamicUpdated = false;
|
||||
data.lastDynamicMs = Time.millis();
|
||||
|
||||
//add building updates
|
||||
for(var build : indexer.getFlagged(team.team, BlockFlag.hasFogRadius)){
|
||||
dynamicEventQueue.add(FogEvent.get(build.tile.x, build.tile.y, build.block.fogRadius, 0));
|
||||
}
|
||||
|
||||
//add unit updates
|
||||
dynamicEventQueue.addAll(unitEventQueue);
|
||||
}
|
||||
|
|
@ -405,8 +405,7 @@ public class FogControl implements CustomChunk{
|
|||
int consec = data & 0b0111_1111;
|
||||
|
||||
if(sign){
|
||||
//TODO disabled for testing?
|
||||
//bools.set(pos, pos + consec);
|
||||
bools.set(pos, pos + consec);
|
||||
pos += consec;
|
||||
}else{
|
||||
pos += consec;
|
||||
|
|
@ -480,8 +479,6 @@ public class FogControl implements CustomChunk{
|
|||
/** if true, a dynamic fog update must be scheduled. */
|
||||
boolean dynamicUpdated;
|
||||
|
||||
boolean dynamicUpdatedClient;
|
||||
|
||||
FogData(){
|
||||
int len = ww * wh;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,15 +12,17 @@ import mindustry.game.EventType.*;
|
|||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** Highly experimental fog-of-war renderer. */
|
||||
public class FogRenderer{
|
||||
public static final Color
|
||||
staticColor = new Color(0f, 0f, 0f, 1f),
|
||||
dynamicColor = new Color(0f, 0f, 0f, 0.5f);
|
||||
private FrameBuffer staticFog = new FrameBuffer(), dynamicFog = new FrameBuffer();
|
||||
private LongSeq events = new LongSeq();
|
||||
private LongSeq dynamics = new LongSeq();
|
||||
private boolean dynamicUpdate = false;
|
||||
private Rect rect = new Rect();
|
||||
private @Nullable Team lastTeam;
|
||||
|
||||
|
|
@ -35,12 +37,6 @@ public class FogRenderer{
|
|||
events.add(event);
|
||||
}
|
||||
|
||||
public void flushDynamic(LongSeq seq){
|
||||
dynamics.clear();
|
||||
dynamics.addAll(seq);
|
||||
dynamicUpdate = true;
|
||||
}
|
||||
|
||||
public Texture getStaticTexture(){
|
||||
return staticFog.getTexture();
|
||||
}
|
||||
|
|
@ -54,25 +50,33 @@ public class FogRenderer{
|
|||
if(fogControl.getDiscovered(player.team()) == null) return;
|
||||
|
||||
//resize if world size changes
|
||||
boolean
|
||||
clearStatic = staticFog.resizeCheck(world.width(), world.height()),
|
||||
clearDynamic = dynamicFog.resizeCheck(world.width(), world.height());
|
||||
boolean clearStatic = staticFog.resizeCheck(world.width(), world.height());
|
||||
|
||||
dynamicFog.resize(world.width(), world.height());
|
||||
|
||||
if(player.team() != lastTeam){
|
||||
copyFromCpu();
|
||||
lastTeam = player.team();
|
||||
clearStatic = false;
|
||||
dynamicUpdate = true;
|
||||
}
|
||||
|
||||
if(clearDynamic || dynamicUpdate){
|
||||
dynamicUpdate = false;
|
||||
//draw dynamic fog every frame
|
||||
{
|
||||
|
||||
Draw.proj(0, 0, staticFog.getWidth(), staticFog.getHeight());
|
||||
Core.camera.bounds(Tmp.r1);
|
||||
Draw.proj(0, 0, staticFog.getWidth() * tilesize, staticFog.getHeight() * tilesize);
|
||||
dynamicFog.begin(Color.black);
|
||||
ScissorStack.push(rect.set(1, 1, staticFog.getWidth() - 2, staticFog.getHeight() - 2));
|
||||
|
||||
//TODO render all (clipped) view circles
|
||||
Team team = player.team();
|
||||
|
||||
for(var build : indexer.getFlagged(team, BlockFlag.hasFogRadius)){
|
||||
poly(Tmp.r1, build.x, build.y, build.block.fogRadius * tilesize);
|
||||
}
|
||||
|
||||
for(var unit : team.data().units){
|
||||
poly(Tmp.r1, unit.x, unit.y, unit.type.fogRadius * tilesize);
|
||||
}
|
||||
|
||||
dynamicFog.end();
|
||||
ScissorStack.pop();
|
||||
|
|
@ -95,18 +99,10 @@ public class FogRenderer{
|
|||
|
||||
Draw.color(Color.white);
|
||||
|
||||
//process new fog events
|
||||
//process new static fog events
|
||||
for(int i = 0; i < events.size; i++){
|
||||
long e = events.items[i];
|
||||
Tile tile = world.tile(FogEvent.x(e), FogEvent.y(e));
|
||||
float o = 0f;
|
||||
//visual offset for uneven blocks; this is not reflected on the CPU, but it doesn't really matter
|
||||
if(tile != null && tile.block().size % 2 == 0 && tile.isCenter()){
|
||||
o = 0.5f;
|
||||
}
|
||||
Fill.poly(FogEvent.x(e) + 0.5f + o, FogEvent.y(e) + 0.5f + o, 20, FogEvent.radius(e) + 0.3f);
|
||||
renderEvent(events.items[i]);
|
||||
}
|
||||
|
||||
events.clear();
|
||||
|
||||
staticFog.end();
|
||||
|
|
@ -115,12 +111,32 @@ public class FogRenderer{
|
|||
}
|
||||
|
||||
staticFog.getTexture().setFilter(TextureFilter.linear);
|
||||
dynamicFog.getTexture().setFilter(TextureFilter.linear);
|
||||
|
||||
Draw.shader(Shaders.fog);
|
||||
Draw.color(dynamicColor);
|
||||
Draw.fbo(dynamicFog.getTexture(), world.width(), world.height(), tilesize);
|
||||
Draw.color(staticColor);
|
||||
Draw.fbo(staticFog.getTexture(), world.width(), world.height(), tilesize);
|
||||
Draw.shader();
|
||||
}
|
||||
|
||||
void poly(Rect check, float x, float y, float rad){
|
||||
if(check.overlaps(x - rad / 2f, y - rad / 2f, rad * 2f, rad * 2f)){
|
||||
Fill.poly(x, y, 20, rad);
|
||||
}
|
||||
}
|
||||
|
||||
void renderEvent(long e){
|
||||
Tile tile = world.tile(FogEvent.x(e), FogEvent.y(e));
|
||||
float o = 0f;
|
||||
//visual offset for uneven blocks; this is not reflected on the CPU, but it doesn't really matter
|
||||
if(tile != null && tile.block().size % 2 == 0 && tile.isCenter()){
|
||||
o = 0.5f;
|
||||
}
|
||||
Fill.poly(FogEvent.x(e) + 0.5f + o, FogEvent.y(e) + 0.5f + o, 20, FogEvent.radius(e) + 0.3f);
|
||||
}
|
||||
|
||||
public void copyFromCpu(){
|
||||
staticFog.resize(world.width(), world.height());
|
||||
staticFog.begin(Color.black);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public class MinimapRenderer{
|
|||
updateUnitArray();
|
||||
}else{
|
||||
units.clear();
|
||||
Groups.unit.each(units::add);
|
||||
Groups.unit.copy(units);
|
||||
}
|
||||
|
||||
float sz = baseSize * zoom;
|
||||
|
|
@ -112,10 +112,12 @@ public class MinimapRenderer{
|
|||
rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize);
|
||||
|
||||
for(Unit unit : units){
|
||||
if(unit.inFogTo(player.team())) continue;
|
||||
|
||||
float rx = !withLabels ? (unit.x - rect.x) / rect.width * w : unit.x / (world.width() * tilesize) * w;
|
||||
float ry = !withLabels ? (unit.y - rect.y) / rect.width * h : unit.y / (world.height() * tilesize) * h;
|
||||
|
||||
Draw.mixcol(unit.team().color, 1f);
|
||||
Draw.mixcol(unit.team.color, 1f);
|
||||
float scale = Scl.scl(1f) / 2f * scaling * 32f;
|
||||
var region = unit.icon();
|
||||
Draw.rect(region, x + rx, y + ry, scale, scale * (float)region.height / region.width, unit.rotation() - 90);
|
||||
|
|
@ -144,11 +146,23 @@ public class MinimapRenderer{
|
|||
zoom = z;
|
||||
}
|
||||
Draw.shader(Shaders.fog);
|
||||
renderer.fog.getStaticTexture().setFilter(TextureFilter.nearest);
|
||||
Texture staticTex = renderer.fog.getStaticTexture(), dynamicTex = renderer.fog.getDynamicTexture();
|
||||
|
||||
//crisp pixels
|
||||
Tmp.tr1.set(renderer.fog.getStaticTexture());
|
||||
staticTex.setFilter(TextureFilter.nearest);
|
||||
dynamicTex.setFilter(TextureFilter.nearest);
|
||||
|
||||
Tmp.tr1.set(dynamicTex);
|
||||
Tmp.tr1.set(region.u, 1f - region.v, region.u2, 1f - region.v2);
|
||||
|
||||
Draw.color(FogRenderer.dynamicColor);
|
||||
Draw.rect(Tmp.tr1, x + w/2f, y + h/2f, w, h);
|
||||
|
||||
Tmp.tr1.texture = staticTex;
|
||||
Draw.color(FogRenderer.staticColor);
|
||||
Draw.rect(Tmp.tr1, x + w/2f, y + h/2f, w, h);
|
||||
|
||||
Draw.color();
|
||||
Draw.shader();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import arc.struct.*;
|
|||
import arc.util.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.abilities.*;
|
||||
import mindustry.game.*;
|
||||
|
|
@ -191,7 +192,7 @@ public class SectorDamage{
|
|||
|
||||
//TODO would be nice if this worked in a more generic way, with two different calculations and paths
|
||||
if(airOnly){
|
||||
world.raycastEach(start.x, start.y, core.tileX(), core.tileY(), (x, y) -> {
|
||||
World.raycastEach(start.x, start.y, core.tileX(), core.tileY(), (x, y) -> {
|
||||
path.add(world.rawTile(x, y));
|
||||
return false;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -438,10 +438,6 @@ public class UnitType extends UnlockableContent{
|
|||
lightRadius = Math.max(60f, hitSize * 2.3f);
|
||||
}
|
||||
|
||||
if(fogRadius < 0){
|
||||
fogRadius = lightRadius * 2f / 8f;
|
||||
}
|
||||
|
||||
clipSize = Math.max(clipSize, lightRadius * 1.1f);
|
||||
singleTarget = weapons.size <= 1 && !forceMultiTarget;
|
||||
|
||||
|
|
@ -469,6 +465,10 @@ public class UnitType extends UnlockableContent{
|
|||
}
|
||||
}
|
||||
|
||||
if(fogRadius < 0){
|
||||
fogRadius = Math.max(lightRadius * 2.5f, 1f) / 8f;
|
||||
}
|
||||
|
||||
if(weapons.isEmpty()){
|
||||
range = maxRange = miningRange;
|
||||
}
|
||||
|
|
@ -787,6 +787,8 @@ public class UnitType extends UnlockableContent{
|
|||
//region drawing
|
||||
|
||||
public void draw(Unit unit){
|
||||
if(unit.inFogTo(Vars.player.team())) return;
|
||||
|
||||
Mechc mech = unit instanceof Mechc ? (Mechc)unit : null;
|
||||
float z = unit.elevation > 0.5f ? (lowAltitude ? Layer.flyingUnitLow : Layer.flyingUnit) : groundLayer + Mathf.clamp(hitSize / 4000f, 0, 0.01f);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import arc.scene.ui.layout.*;
|
|||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
|
|
@ -125,7 +126,7 @@ public class RepairBeamWeapon extends Weapon{
|
|||
|
||||
if(targetBuildings){
|
||||
//snap to closest building
|
||||
Vars.world.raycastEachWorld(wx, wy, heal.lastEnd.x, heal.lastEnd.y, (x, y) -> {
|
||||
World.raycastEachWorld(wx, wy, heal.lastEnd.x, heal.lastEnd.y, (x, y) -> {
|
||||
var build = Vars.world.build(x, y);
|
||||
if(build != null && build.team == unit.team && build.damaged()){
|
||||
heal.target = build;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
|
|
@ -48,6 +49,7 @@ public class BaseTurret extends Block{
|
|||
}
|
||||
|
||||
placeOverlapRange = Math.max(placeOverlapRange, range + placeOverlapMargin);
|
||||
fogRadius = Math.max(Mathf.round(range / tilesize), fogRadius);
|
||||
super.init();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ public class PowerNode extends PowerBlock{
|
|||
}
|
||||
|
||||
public static boolean insulated(int x, int y, int x2, int y2){
|
||||
return world.raycast(x, y, x2, y2, (wx, wy) -> {
|
||||
return World.raycast(x, y, x2, y2, (wx, wy) -> {
|
||||
Building tile = world.build(wx, wy);
|
||||
return tile != null && tile.isInsulated();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ public class CoreBlock extends StorageBlock{
|
|||
public void init(){
|
||||
//assign to update clipSize internally
|
||||
lightRadius = 30f + 20f * size;
|
||||
fogRadius = Math.max(fogRadius, (int)(lightRadius / 8f * 2f));
|
||||
emitLight = true;
|
||||
|
||||
super.init();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue