1
0
mirror of https://github.com/Anuken/Mindustry.git synced 2024-10-06 04:47:14 +03:00

Bullet pierceCap fix + Malis + Other fixes

This commit is contained in:
Anuken 2022-04-10 17:12:49 -04:00
parent 84686a260d
commit 89af2c8033
25 changed files with 112 additions and 79 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

View File

@ -1416,12 +1416,12 @@ block.large-logic-display.name = Large Logic Display
block.memory-cell.name = Memory Cell
block.memory-bank.name = Memory Bank
team.blue.name = blue
team.crux.name = crux
team.sharded.name = sharded
team.derelict.name = derelict
team.green.name = green
team.purple.name = purple
team.malis.name = Malis
team.crux.name = Crux
team.sharded.name = Sharded
team.derelict.name = Derelict
team.green.name = Green
team.purple.name = Purple
hint.skip = Skip
hint.desktopMove = Use [accent][[WASD][] to move.

View File

@ -544,3 +544,4 @@
63148=turret-unit-build-tower|unit-turret-unit-build-tower-ui
63147=blast-door|block-blast-door-ui
63146=alphaaaa|alphaaaa
63145=malis|team-malis

View File

@ -2987,7 +2987,7 @@ public class Blocks{
//TODO these may work in space, but what's the point?
lancer = new PowerTurret("lancer"){{
requirements(Category.turret, with(Items.copper, 60, Items.lead, 70, Items.silicon, 50));
requirements(Category.turret, with(Items.copper, 70, Items.lead, 70, Items.silicon, 70));
range = 165f;
shoot.firstShotDelay = 40f;
@ -3020,6 +3020,8 @@ public class Blocks{
collidesAir = false;
length = 173f;
ammoMultiplier = 1f;
pierceCap = 4;
}};
}};
@ -3751,6 +3753,7 @@ public class Blocks{
damage = 90f;
length = r;
knockback = 1f;
pierceCap = 3;
colors = new Color[]{Color.valueOf("eb7abe").a(0.55f), Color.valueOf("e189f5").a(0.7f), Color.valueOf("907ef7").a(0.8f), Color.valueOf("91a4ff"), Color.white};
}},
@ -3759,6 +3762,7 @@ public class Blocks{
rangeChange = 70f;
length = r + rangeChange;
knockback = 2f;
pierceCap = 4;
colors = new Color[]{Color.valueOf("465ab8").a(0.55f), Color.valueOf("66a6d2").a(0.7f), Color.valueOf("89e8b6").a(0.8f), Color.valueOf("cafcbe"), Color.white};
flareColor = Color.valueOf("89e8b6");

View File

@ -225,7 +225,7 @@ public class ErekirTechTree{
});
});
node(radar, Seq.with(new Research(beamNode), new Research(turbineCondenser)), () -> {
node(radar, Seq.with(new Research(beamNode), new Research(turbineCondenser), new Research(fabricator)), () -> {
node(breach, Seq.with(new Research(siliconArcFurnace), new OnSector(two)), () -> {
node(berylliumWall, () -> {
node(berylliumWallLarge, () -> {

View File

@ -122,6 +122,8 @@ public class Planets{
allowSectorInvasion = true;
allowLaunchSchematics = true;
ruleSetter = r -> {
//TODO this planet is crux, need to update all maps.
//r.waveTeam = Team.crux;
r.placeRangeCheck = false;
r.attributes.clear();
r.showSpawns = false;

View File

@ -161,7 +161,7 @@ public class StatusEffects{
}};
boss = new StatusEffect("boss"){{
color = Team.crux.color;
color = Team.malis.color;
permanent = true;
damageMultiplier = 1.3f;
healthMultiplier = 1.5f;

View File

@ -8,6 +8,7 @@ public class TeamEntries{
//TODO
//new TeamEntry(Team.derelict);
//new TeamEntry(Team.sharded);
//new TeamEntry(Team.malis);
//new TeamEntry(Team.crux);
}
}

View File

@ -110,9 +110,9 @@ public class UnitTypes{
}};
mace = new UnitType("mace"){{
speed = 0.45f;
speed = 0.5f;
hitSize = 10f;
health = 540;
health = 550;
armor = 4f;
ammoType = new ItemAmmoType(Items.coal);
@ -125,11 +125,13 @@ public class UnitTypes{
reload = 11f;
recoil = 1f;
ejectEffect = Fx.none;
bullet = new BulletType(4.1f, 35f){{
bullet = new BulletType(4.2f, 37f){{
ammoMultiplier = 3f;
hitSize = 7f;
lifetime = 13f;
pierce = true;
pierceBuilding = true;
pierceCap = 2;
statusDuration = 60f * 4;
shootEffect = Fx.shootSmallFlame;
hitEffect = Fx.hitFlameSmall;

View File

@ -19,17 +19,20 @@ import static mindustry.Vars.*;
/** Utility class for damaging in an area. */
public class Damage{
private static final Rect rect = new Rect();
private static final Rect hitrect = new Rect();
private static final Vec2 vec = new Vec2(), seg1 = new Vec2(), seg2 = new Vec2();
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<Building> builds = new Seq<>();
private static final FloatSeq distances = new FloatSeq();
private static Tile furthest;
private static Rect rect = new Rect();
private static Rect hitrect = new Rect();
private static Vec2 tr = new Vec2(), seg1 = new Vec2(), seg2 = new Vec2();
private static Seq<Unit> units = new Seq<>();
private static float maxDst = 0f;
private static int pierceCount = 0;
private static IntSet collidedBlocks = new IntSet();
private static Building tmpBuilding;
private static Unit tmpUnit;
private static IntFloatMap damages = new IntFloatMap();
private static Seq<Building> builds = new Seq<>();
public static void applySuppression(Team team, float x, float y, float range, float reload, float maxDelay, float applyParticleChance, @Nullable Position source){
builds.clear();
@ -132,33 +135,59 @@ public class Damage{
}
public static float findLaserLength(Bullet b, float length){
Tmp.v1.trnsExact(b.rotation(), length);
vec.trnsExact(b.rotation(), length);
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 + vec.x), World.toTile(b.y + vec.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;
}
public static float findPierceLength(Bullet b, int pierceCap, float length){
Tmp.v1.trnsExact(b.rotation(), length);
vec.trnsExact(b.rotation(), length);
rect.setPosition(b.x, b.y).setSize(vec.x, vec.y).normalize().grow(3f);
furthest = null;
pierceCount = 0;
maxDst = Float.POSITIVE_INFINITY;
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);
distances.clear();
return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
World.raycast(b.tileX(), b.tileY(), World.toTile(b.x + vec.x), World.toTile(b.y + vec.y), (x, y) -> {
//add distance to list so it can be processed
var build = world.build(x, y);
if(build != null && build.team != b.team){
distances.add(b.dst(build));
if(b.type.laserAbsorb && build.absorbLasers()){
maxDst = Math.min(maxDst, b.dst(build));
return true;
}
}
/** 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){
float resultLength = findLaserLength(b, length);
return false;
});
collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength, large);
Units.nearbyEnemies(b.team, rect, u -> {
if(u.checkTarget(b.type.collidesAir, b.type.collidesGround)){
distances.add(u.dst(b));
}
});
distances.sort();
//return either the length when not enough things were pierced,
//or the last pierced object if there were enough blockages
return Math.min(distances.size < pierceCap || pierceCap < 0 ? length : Math.max(6f, distances.get(pierceCap - 1)), maxDst);
}
/** 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);
collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength, large, laser, pierceCap);
b.fdata = resultLength;
@ -197,8 +226,10 @@ public class Damage{
length = findPierceLength(hitter, pierceCap, length);
}
//TODO pierceCount ++ should happen in blocks AND units!
collidedBlocks.clear();
tr.trnsExact(angle, length);
vec.trnsExact(angle, length);
Intc2 collider = (cx, cy) -> {
Building tile = world.build(cx, cy);
@ -221,7 +252,7 @@ public class Damage{
if(hitter.type.collidesGround){
seg1.set(x, y);
seg2.set(seg1).add(tr);
seg2.set(seg1).add(vec);
World.raycastEachWorld(x, y, seg2.x, seg2.y, (cx, cy) -> {
collider.get(cx, cy);
@ -235,25 +266,10 @@ public class Damage{
});
}
rect.setPosition(x, y).setSize(tr.x, tr.y);
float x2 = tr.x + x, y2 = tr.y + y;
if(rect.width < 0){
rect.x += rect.width;
rect.width *= -1;
}
if(rect.height < 0){
rect.y += rect.height;
rect.height *= -1;
}
float expand = 3f;
rect.y -= expand;
rect.x -= expand;
rect.width += expand * 2;
rect.height += expand * 2;
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 -> {
//the peirce cap works for units, but really terribly, I'm just disabling it for now.
@ -289,12 +305,12 @@ public class Damage{
* @return the first encountered object.
*/
public static Healthc linecast(Bullet hitter, float x, float y, float angle, float length){
tr.trns(angle, length);
vec.trns(angle, length);
tmpBuilding = null;
if(hitter.type.collidesGround){
World.raycastEachWorld(x, y, x + tr.x, y + tr.y, (cx, cy) -> {
World.raycastEachWorld(x, y, x + vec.x, y + vec.y, (cx, cy) -> {
Building tile = world.build(cx, cy);
if(tile != null && tile.team != hitter.team){
tmpBuilding = tile;
@ -304,8 +320,8 @@ public class Damage{
});
}
rect.setPosition(x, y).setSize(tr.x, tr.y);
float x2 = tr.x + x, y2 = tr.y + y;
rect.setPosition(x, y).setSize(vec.x, vec.y);
float x2 = vec.x + x, y2 = vec.y + y;
if(rect.width < 0){
rect.x += rect.width;
@ -428,8 +444,8 @@ public class Damage{
float amount = calculateDamage(scaled ? Math.max(0, entity.dst(x, y) - entity.type.hitSize/2) : entity.dst(x, y), radius, damage);
entity.damage(amount);
//TODO better velocity displacement
float dst = tr.set(entity.x - x, entity.y - y).len();
entity.vel.add(tr.setLength((1f - dst / radius) * 2f / entity.mass()));
float dst = vec.set(entity.x - x, entity.y - y).len();
entity.vel.add(vec.setLength((1f - dst / radius) * 2f / entity.mass()));
if(complete && damage >= 9999999f && entity.isPlayer()){
Events.fire(Trigger.exclusionDeath);

View File

@ -44,6 +44,10 @@ public class BulletType extends Content implements Cloneable{
public boolean pierceBuilding;
/** Maximum # of pierced objects. */
public int pierceCap = -1;
/** If false, this bullet isn't removed after pierceCap is exceeded. Expert usage only. */
public boolean removeAfterPierce = true;
/** For piercing lasers, setting this to true makes it get absorbed by plastanium walls. */
public boolean laserAbsorb = true;
/** Life fraction at which this bullet has the best range/damage/etc. Used for lasers and continuous turrets. */
public float optimalLifeFract = 0f;
/** Z layer to drawn on. */

View File

@ -11,11 +11,10 @@ public class ContinuousBulletType extends BulletType{
public float damageInterval = 5f;
public boolean largeHit = false;
public boolean continuous = true;
public boolean laserAbsorb = true;
/** can't use pierceCap here for... many reasons. DO NOT USE, BUGGY */
public int pierceMax = -1;
{
removeAfterPierce = false;
pierceCap = -1;
speed = 0f;
despawnEffect = Fx.none;
shootEffect = Fx.none;
@ -78,7 +77,7 @@ public class ContinuousBulletType extends BulletType{
}
public void applyDamage(Bullet b){
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), currentLength(b), largeHit, laserAbsorb, pierceMax);
Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), currentLength(b), largeHit, laserAbsorb, pierceCap);
}
public float currentLength(Bullet b){

View File

@ -57,7 +57,7 @@ public class ContinuousFlameBulletType extends ContinuousBulletType{
@Override
public void draw(Bullet b){
float mult = b.fin(lengthInterp);
float realLength = (pierceMax <= 0 ? length : Damage.findPierceLength(b, pierceMax, length)) * mult;
float realLength = (pierceCap <= 0 ? length : Damage.findPierceLength(b, pierceCap, length)) * mult;
float sin = Mathf.sin(Time.time, oscScl, oscMag);

View File

@ -63,7 +63,7 @@ public class LaserBulletType extends BulletType{
@Override
public void init(Bullet b){
float resultLength = Damage.collideLaser(b, length, largeHit), rot = b.rotation();
float resultLength = Damage.collideLaser(b, length, largeHit, laserAbsorb, pierceCap), rot = b.rotation();
laserEffect.at(b.x, b.y, rot, resultLength * 0.75f);

View File

@ -36,7 +36,7 @@ public class ShrapnelBulletType extends BulletType{
public void init(Bullet b){
super.init(b);
Damage.collideLaser(b, length, hitLarge);
Damage.collideLaser(b, length, hitLarge, laserAbsorb, pierceCap);
}
@Override

View File

@ -132,7 +132,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
tileRaycast(World.toTile(lastX()), World.toTile(lastY()), tileX(), tileY());
}
if(type.pierceCap != -1 && collided.size >= type.pierceCap){
if(type.removeAfterPierce && type.pierceCap != -1 && collided.size >= type.pierceCap){
hit = true;
remove();
}

View File

@ -128,7 +128,7 @@ public class Rules{
/** team of the player by default. */
public Team defaultTeam = Team.sharded;
/** team of the enemy in waves/sectors. */
public Team waveTeam = Team.crux;
public Team waveTeam = Team.malis;
/** color of clouds that is displayed when the player is landing */
public Color cloudColor = new Color(0f, 0f, 0f, 0f);
/** name of the custom mode that this ruleset describes, or null. */

View File

@ -31,11 +31,11 @@ public class Team implements Comparable<Team>{
derelict = new Team(0, "derelict", Color.valueOf("4d4e58")),
sharded = new Team(1, "sharded", Pal.accent.cpy(),
Color.valueOf("ffd37f"), Color.valueOf("eab678"), Color.valueOf("d4816b")),
crux = new Team(2, "crux", Color.valueOf("f25555"),
malis = new Team(2, "malis", Color.valueOf("f25555"),
Color.valueOf("fc8e6c"), Color.valueOf("f25555"), Color.valueOf("a04553")),
green = new Team(3, "green", Color.valueOf("54d67d"), Color.valueOf("96f58c"), Color.valueOf("54d67d"), Color.valueOf("28785c")),
purple = new Team(4, "purple", Color.valueOf("995bb0"), Color.valueOf("f08dd5"), Color.valueOf("995bb0"), Color.valueOf("312c63")),
blue = new Team(5, "blue", Color.valueOf("554deb"), Color.valueOf("80aaff"), Color.valueOf("554deb"), Color.valueOf("3f207d"));
crux = new Team(3, "crux", Color.valueOf("6c87fd"), Color.valueOf("85caf9"), Color.valueOf("6c87fd"), Color.valueOf("3b3392")),
green = new Team(4, "green", Color.valueOf("54d67d"), Color.valueOf("96f58c"), Color.valueOf("54d67d"), Color.valueOf("28785c")),
purple = new Team(5, "purple", Color.valueOf("995bb0"), Color.valueOf("f08dd5"), Color.valueOf("995bb0"), Color.valueOf("312c63"));
static{
Mathf.rand.setSeed(8);

View File

@ -29,7 +29,7 @@ public class Teams{
public Seq<Unit> bosses = new Seq<>();
public Teams(){
active.add(get(Team.crux));
active.add(get(Team.malis));
}
@Nullable

View File

@ -370,11 +370,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(canSelect(sec) || sec.unlocked() || debugSelect){
Color color =
sec.hasBase() ? Tmp.c2.set(Team.sharded.color).lerp(Team.crux.color, sec.hasEnemyBase() ? 0.5f : 0f) :
sec.hasBase() ? Tmp.c2.set(Team.sharded.color).lerp(Team.malis.color, sec.hasEnemyBase() ? 0.5f : 0f) :
sec.preset != null ?
sec.preset.unlocked() ? Tmp.c2.set(Team.derelict.color).lerp(Color.white, Mathf.absin(Time.time, 10f, 1f)) :
Color.gray :
sec.hasEnemyBase() ? Team.crux.color :
sec.hasEnemyBase() ? Team.malis.color :
null;
if(color != null){
@ -419,7 +419,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(planet.allowSectorInvasion){
for(Sector enemy : sec.near()){
if(enemy.hasEnemyBase()){
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25);
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.malis.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25);
}
}
}

View File

@ -107,7 +107,7 @@ public class BuildTurret extends BaseTurret{
checkSuppression();
unit.buildSpeedMultiplier(efficiency * timeScale);
unit.buildSpeedMultiplier(Math.max(efficiency * timeScale, 0.0001f));
unit.speedMultiplier(efficiency * timeScale);
warmup = Mathf.lerpDelta(warmup, unit.activelyBuilding() ? 1f : 0f, 0.1f);
@ -204,7 +204,7 @@ public class BuildTurret extends BaseTurret{
@Override
public boolean shouldConsume(){
return super.shouldConsume() && unit.activelyBuilding() && !isHealSuppressed();
return unit.plans().size > 0 && !isHealSuppressed();
}
@Override

View File

@ -96,6 +96,7 @@ public class RegenProjector extends Block{
public Seq<Building> targets = new Seq<>();
public int lastChange = -2;
public float warmup, totalTime, optionalTimer;
public boolean anyTargets = false;
public boolean didRegen = false;
public void updateTargets(){
@ -115,12 +116,15 @@ public class RegenProjector extends Block{
warmup = Mathf.approachDelta(warmup, didRegen ? 1f : 0f, 1f / 70f);
totalTime += warmup * Time.delta;
didRegen = false;
anyTargets = false;
//no healing when suppressed
if(checkSuppression()){
return;
}
anyTargets = targets.contains(b -> b.damaged());
if(efficiency > 0){
if((optionalTimer += Time.delta * optionalEfficiency) >= optionalUseTime){
consume();
@ -161,8 +165,8 @@ public class RegenProjector extends Block{
}
@Override
public boolean productionValid(){
return didRegen;
public boolean shouldConsume(){
return anyTargets;
}
@Override

View File

@ -74,7 +74,7 @@ public class Turret extends ReloadTurret{
/** Minimum warmup needed to fire. */
public float minWarmup = 0f;
/** If true, this turret will accurately target moving targets with respect to charge time. */
public boolean accurateDelay = false;
public boolean accurateDelay = true;
/** If false, this turret can't move while charging. */
public boolean moveWhileCharging = true;
/** pattern used for bullets */

View File

@ -25,4 +25,4 @@ org.gradle.caching=true
#used for slow jitpack builds; TODO see if this actually works
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
archash=59577c8222
archash=91f392f766

View File

@ -915,7 +915,7 @@ public class ServerControl implements ApplicationListener{
info("Core destroyed.");
inExtraRound = false;
Events.fire(new GameOverEvent(Team.crux));
Events.fire(new GameOverEvent(state.rules.waveTeam));
});
handler.register("info", "<IP/UUID/name...>", "Find player info(s). Can optionally check for all names or IPs a player has had.", arg -> {