This commit is contained in:
Anuken 2023-01-13 09:42:28 -05:00
parent b1e1fe4922
commit b2b4602c91

View File

@ -6,7 +6,6 @@ import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import arc.util.pooling.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.game.EventType.*;
@ -27,8 +26,6 @@ public class Damage{
private static final Seq<Unit> units = new Seq<>();
private static final IntSet collidedBlocks = new IntSet();
private static final IntFloatMap damages = new IntFloatMap();
private static final Seq<Collided> collided = new Seq<>();
private static final Pool<Collided> collidePool = Pools.get(Collided.class, Collided::new);
private static final Seq<Building> builds = new Seq<>();
private static final FloatSeq distances = new FloatSeq();
@ -187,7 +184,7 @@ public class Damage{
return Math.min(distances.size < pierceCap || pierceCap < 0 ? length : Math.max(6f, distances.get(pierceCap - 1)), maxDst);
}
/** Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */
/** TODO Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */
public static float collideLaser(Bullet b, float length, boolean large, boolean laser, int pierceCap){
float resultLength = findPierceLength(b, pierceCap, length);
@ -229,27 +226,40 @@ public class Damage{
length = findPierceLength(hitter, pierceCap, length);
}
//TODO pierceCount ++ should happen in blocks AND units!
collidedBlocks.clear();
vec.trnsExact(angle, length);
Intc2 collider = (cx, cy) -> {
Building tile = world.build(cx, cy);
boolean collide = tile != null && hitter.checkUnderBuild(tile, cx * tilesize, cy * tilesize) && collidedBlocks.add(tile.pos());
if(hitter.damage > 0){
float health = !collide ? 0 : tile.health;
if(collide && tile.team != team && tile.collide(hitter)){
tile.collision(hitter);
hitter.type.hit(hitter, cx * tilesize, cy * tilesize);
}
//try to heal the tile
if(collide && hitter.type.testCollision(hitter, tile)){
hitter.type.hitTile(hitter, tile, cx * tilesize, cy * tilesize, health, false);
}
}
};
if(hitter.type.collidesGround){
seg1.set(x, y);
seg2.set(seg1).add(vec);
World.raycastEachWorld(x, y, seg2.x, seg2.y, (cx, cy) -> {
Building tile = world.build(cx, cy);
boolean collide = tile != null && hitter.checkUnderBuild(tile, cx * tilesize, cy * tilesize)
&& ((tile.team != team && tile.collide(hitter)) || hitter.type.testCollision(hitter, tile)) && collidedBlocks.add(tile.pos());
if(collide){
collided.add(collidePool.obtain().set(cx * tilesize, cy * tilesize, tile));
collider.get(cx, cy);
for(Point2 p : Geometry.d4){
Tile other = world.tile(p.x + cx, p.y + cy);
if(other != null && (large || Intersector.intersectSegmentRectangle(seg1, seg2, other.getBounds(Tmp.r1)))){
Building build = other.build;
if(build != null && hitter.checkUnderBuild(build, cx * tilesize, cy * tilesize) && collidedBlocks.add(build.pos())){
collided.add(collidePool.obtain().set((p.x + cx * tilesize), (p.y + cy) * tilesize, build));
}
}
for(Point2 p : Geometry.d4){
Tile other = world.tile(p.x + cx, p.y + cy);
if(other != null && (large || Intersector.intersectSegmentRectangle(seg1, seg2, other.getBounds(Tmp.r1)))){
collider.get(cx + p.x, cy + p.y);
}
}
return false;
@ -261,44 +271,32 @@ public class Damage{
rect.setPosition(x, y).setSize(vec.x, vec.y).normalize().grow(expand * 2f);
float x2 = vec.x + x, y2 = vec.y + y;
Cons<Unit> cons = e -> {
if(!e.hittable()) return;
//the peirce cap works for units, but really terribly, I'm just disabling it for now.
//if(pierceCap > 0 && pierceCount > pierceCap) return;
e.hitbox(hitrect);
Vec2 vec = Geometry.raycastRect(x, y, x2, y2, hitrect.grow(expand * 2));
if(vec != null && hitter.damage > 0){
effect.at(vec.x, vec.y);
e.collision(hitter, vec.x, vec.y);
hitter.collision(e, vec.x, vec.y);
}
};
units.clear();
Units.nearbyEnemies(team, rect, u -> {
if(u.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround) && u.hittable()){
u.hitbox(hitrect);
Vec2 vec = Geometry.raycastRect(x, y, x2, y2, hitrect.grow(expand * 2));
if(vec != null){
collided.add(collidePool.obtain().set(vec.x, vec.y, u));
}
if(u.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround)){
units.add(u);
}
});
int[] collideCount = {0};
collided.sort(c -> hitter.dst2(c.x, c.y));
collided.each(c -> {
if(hitter.damage > 0 && (pierceCap <= 0 || collideCount[0]++ < pierceCap)){
if(c.target instanceof Unit u){
effect.at(c.x, c.y);
u.collision(hitter, c.x, c.y);
hitter.collision(u, c.x, c.y);
}else if(c.target instanceof Building tile){
float health = tile.health;
if(tile.team != team && tile.collide(hitter)){
tile.collision(hitter);
hitter.type.hit(hitter, c.x, c.y);
}
//try to heal the tile
if(hitter.type.testCollision(hitter, tile)){
hitter.type.hitTile(hitter, tile, c.x, c.y, health, false);
}
}
}
});
collidePool.freeAll(collided);
collided.clear();
units.sort(u -> u.dst2(hitter));
units.each(cons);
}
/**
@ -340,7 +338,7 @@ public class Damage{
*/
public static Healthc linecast(Bullet hitter, float x, float y, float angle, float length){
vec.trns(angle, length);
tmpBuilding = null;
if(hitter.type.collidesGround){
@ -615,16 +613,4 @@ public class Damage{
public static float applyArmor(float damage, float armor){
return Math.max(damage - armor, minArmorDamage * damage);
}
public static class Collided{
public float x, y;
public Teamc target;
public Collided set(float x, float y, Teamc target){
this.x = x;
this.y = y;
this.target = target;
return this;
}
}
}
}