Various database entry stats (#11583)
* Add Firerate Stat to Lustre and sublimate * 8 votes * forgot comment * Show shock mine damage stats * make spawnBullets appear in core database * spawned instead * typo h * fuck impact stats * segment and point defense stuff * Change repair & shieldregen field's shown stats * Grant "Airborne" achievement when commanding units * more database entries * navanax entries (holy hell there are so many) * boosting speed entry * add arrow icon and stuff * dont break tests * junction storage per side * Apply suggestion from @Anuken --------- Co-authored-by: Anuken <arnukren@gmail.com>
This commit is contained in:
@@ -1069,6 +1069,20 @@
|
||||
"search": [
|
||||
"planet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "ec43f846ca53702f30310718d627f2b5",
|
||||
"css": "arrow-note",
|
||||
"code": 59444,
|
||||
"src": "custom_icons",
|
||||
"selected": true,
|
||||
"svg": {
|
||||
"path": "M50 0L0 50V150 250 350 450 550 650L50 700H150 250 350 450 550 650 750L800 750 750 800 700 850V950L750 1000H850L900 950 950 900 1000 850 1050 800 1100 750 1150 700 1200 650V550L1150 500 1100 450 1050 400 1000 350 950 300 900 250 850 200H750L700 250V350L750 400 800 450 750 500H650 550 450 350 250L200 450V350 250 150 50L150 0Z",
|
||||
"width": 1200
|
||||
},
|
||||
"search": [
|
||||
"arrow-note"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
core/assets-raw/icons/arrow-note.png
Normal file
BIN
core/assets-raw/icons/arrow-note.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 B |
@@ -1019,7 +1019,6 @@ stat.targetsair = Targets Air
|
||||
stat.targetsground = Targets Ground
|
||||
stat.crushdamage = Crush Damage
|
||||
stat.legsplashdamage = Leg Splash Damage
|
||||
stat.legsplashrange = Leg Splash Range
|
||||
stat.itemsmoved = Move Speed
|
||||
stat.launchtime = Time Between Launches
|
||||
stat.shootrange = Range
|
||||
@@ -1036,6 +1035,7 @@ stat.itemcapacity = Item Capacity
|
||||
stat.memorycapacity = Memory Capacity
|
||||
stat.basepowergeneration = Base Power Generation
|
||||
stat.productiontime = Production Time
|
||||
stat.warmuptime = Warmup Time
|
||||
stat.repairtime = Block Full Repair Time
|
||||
stat.repairspeed = Repair Speed
|
||||
stat.weapons = Weapons
|
||||
@@ -1078,6 +1078,7 @@ stat.minetier = Mine Tier
|
||||
stat.payloadcapacity = Payload Capacity
|
||||
stat.abilities = Abilities
|
||||
stat.canboost = Can Boost
|
||||
stat.boostingspeed = Boosting Speed
|
||||
stat.flying = Flying
|
||||
stat.ammouse = Ammo Use
|
||||
stat.ammocapacity = Ammo Capacity
|
||||
@@ -1176,6 +1177,8 @@ bar.activated = Activated
|
||||
|
||||
units.processorcontrol = [lightgray]Processor Controlled
|
||||
|
||||
weapon.pointdefense = [stat]Point Defense
|
||||
|
||||
bullet.damage = [stat]{0}[lightgray] damage
|
||||
bullet.splashdamage = [stat]{0}[lightgray] area dmg ~ [stat]{1}[lightgray] tiles
|
||||
bullet.incendiary = [stat]incendiary
|
||||
@@ -1186,10 +1189,17 @@ bullet.armorpiercing = [stat]{0}%[lightgray] armor piercing
|
||||
bullet.antiarmor = [stat]{0}x[lightgray] anti-armor
|
||||
bullet.maxdamagefraction = [stat]{0}%[lightgray] damage limit
|
||||
bullet.suppression = [stat]{0}[lightgray] seconds of repair suppression ~ [stat]{1}[lightgray] tiles
|
||||
bullet.empradius = [stat]{0}[lightgray] tiles EMP radius
|
||||
bullet.empboost = [stat]{0}%[lightgray] overdrive ~ [stat]{1}[lightgray]
|
||||
bullet.empdamage = [stat]{0}%[lightgray] power damage
|
||||
bullet.empslowdown = [stat]{0}%[lightgray] enemy power overdrive ~ [stat]{1}[lightgray]
|
||||
bullet.empunitdamage = [stat]{0}%[lightgray] unit damage
|
||||
bullet.interval = [stat]{0}/sec[lightgray] interval bullets:
|
||||
bullet.frags = [stat]{0}x[lightgray] frag bullets:
|
||||
bullet.lightning = [stat]{0}x[lightgray] lightning ~ [stat]{1}[lightgray] damage
|
||||
bullet.lightninginterval = [stat]{0}[lightgray] tiles interval ~ [stat]{1}[lightgray] tiles length
|
||||
bullet.buildingdamage = [stat]{0}%[lightgray] building damage
|
||||
bullet.spawnBullets = [stat]{0}x[lightgray] spawned bullets:
|
||||
bullet.shielddamage = [stat]{0}%[lightgray] shield damage
|
||||
bullet.knockback = [stat]{0}[lightgray] knockback
|
||||
bullet.pierce = [stat]{0}x[lightgray] pierce
|
||||
@@ -1210,6 +1220,7 @@ unit.liquidsecond = liquid units/second
|
||||
unit.itemssecond = items/second
|
||||
unit.liquidunits = liquid units
|
||||
unit.powerunits = power units
|
||||
unit.powerequilibrium = power equilibrium
|
||||
unit.heatunits = heat units
|
||||
unit.degrees = degrees
|
||||
unit.seconds = seconds
|
||||
@@ -1227,6 +1238,7 @@ unit.billions = b
|
||||
unit.shots = shots
|
||||
unit.pershot = /shot
|
||||
unit.perleg = per leg
|
||||
unit.perside = per side
|
||||
category.purpose = Purpose
|
||||
category.general = General
|
||||
category.power = Power
|
||||
@@ -2847,4 +2859,4 @@ lenum.ambientlight = Ambient light color. Used when lighting is enabled.
|
||||
lenum.solarmultiplier = Multiplies power output of solar panels.
|
||||
lenum.dragmultiplier = Environment drag multiplier.
|
||||
lenum.ban = Blocks or units that cannot be placed or built.
|
||||
lenum.unban = Unban a unit or block.
|
||||
lenum.unban = Unban a unit or block.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -10,7 +10,7 @@ public class BoostAI extends AIController{
|
||||
public void updateUnit(){
|
||||
if(unit.controller() instanceof CommandAI ai){
|
||||
ai.defaultBehavior();
|
||||
unit.updateBoosting(true);
|
||||
unit.updateBoosting(true, true);
|
||||
|
||||
//auto land when near target
|
||||
if(ai.attackTarget != null && unit.within(ai.attackTarget, unit.range())){
|
||||
|
||||
@@ -2368,64 +2368,6 @@ public class UnitTypes{
|
||||
buildSpeed = 3.5f;
|
||||
rotateToBuilding = false;
|
||||
|
||||
for(float mountY : new float[]{-117/4f, 50/4f}){
|
||||
for(float sign : Mathf.signs){
|
||||
weapons.add(new Weapon("plasma-laser-mount"){{
|
||||
shadow = 20f;
|
||||
controllable = false;
|
||||
autoTarget = true;
|
||||
mirror = false;
|
||||
shake = 3f;
|
||||
shootY = 7f;
|
||||
rotate = true;
|
||||
x = 84f/4f * sign;
|
||||
y = mountY;
|
||||
|
||||
targetInterval = 20f;
|
||||
targetSwitchInterval = 35f;
|
||||
|
||||
rotateSpeed = 3.5f;
|
||||
reload = 170f;
|
||||
recoil = 1f;
|
||||
shootSound = Sounds.beamPlasmaSmall;
|
||||
initialShootSound = Sounds.shootBeamPlasmaSmall;
|
||||
continuous = true;
|
||||
cooldownTime = reload;
|
||||
immunities.add(StatusEffects.burning);
|
||||
|
||||
bullet = new ContinuousLaserBulletType(){{
|
||||
maxRange = 90f;
|
||||
damage = 27f;
|
||||
length = 95f;
|
||||
hitEffect = Fx.hitMeltHeal;
|
||||
drawSize = 200f;
|
||||
lifetime = 155f;
|
||||
shake = 1f;
|
||||
|
||||
shootEffect = Fx.shootHeal;
|
||||
smokeEffect = Fx.none;
|
||||
width = 4f;
|
||||
largeHit = false;
|
||||
|
||||
incendChance = 0.03f;
|
||||
incendSpread = 5f;
|
||||
incendAmount = 1;
|
||||
|
||||
healPercent = 0.4f;
|
||||
collidesTeam = true;
|
||||
|
||||
colors = new Color[]{Pal.heal.cpy().a(.2f), Pal.heal.cpy().a(.5f), Pal.heal.cpy().mul(1.2f), Color.white};
|
||||
}};
|
||||
}});
|
||||
}
|
||||
}
|
||||
abilities.add(new SuppressionFieldAbility(){{
|
||||
orbRadius = 5;
|
||||
particleSize = 3;
|
||||
y = -10f;
|
||||
particles = 10;
|
||||
color = particleColor = effectColor = Pal.heal;
|
||||
}});
|
||||
weapons.add(new Weapon("emp-cannon-mount"){{
|
||||
rotate = true;
|
||||
|
||||
@@ -2508,6 +2450,66 @@ public class UnitTypes{
|
||||
});
|
||||
}};
|
||||
}});
|
||||
|
||||
for(float mountY : new float[]{-117/4f, 50/4f}){
|
||||
for(float sign : Mathf.signs){
|
||||
weapons.add(new Weapon("plasma-laser-mount"){{
|
||||
shadow = 20f;
|
||||
controllable = false;
|
||||
autoTarget = true;
|
||||
mirror = false;
|
||||
shake = 3f;
|
||||
shootY = 7f;
|
||||
rotate = true;
|
||||
x = 84f/4f * sign;
|
||||
y = mountY;
|
||||
|
||||
targetInterval = 20f;
|
||||
targetSwitchInterval = 35f;
|
||||
|
||||
rotateSpeed = 3.5f;
|
||||
reload = 170f;
|
||||
recoil = 1f;
|
||||
shootSound = Sounds.beamPlasmaSmall;
|
||||
initialShootSound = Sounds.shootBeamPlasmaSmall;
|
||||
continuous = true;
|
||||
cooldownTime = reload;
|
||||
immunities.add(StatusEffects.burning);
|
||||
|
||||
bullet = new ContinuousLaserBulletType(){{
|
||||
maxRange = 90f;
|
||||
damage = 27f;
|
||||
length = 95f;
|
||||
hitEffect = Fx.hitMeltHeal;
|
||||
drawSize = 200f;
|
||||
lifetime = 155f;
|
||||
shake = 1f;
|
||||
|
||||
shootEffect = Fx.shootHeal;
|
||||
smokeEffect = Fx.none;
|
||||
width = 4f;
|
||||
largeHit = false;
|
||||
|
||||
incendChance = 0.03f;
|
||||
incendSpread = 5f;
|
||||
incendAmount = 1;
|
||||
|
||||
healPercent = 0.4f;
|
||||
collidesTeam = true;
|
||||
|
||||
colors = new Color[]{Pal.heal.cpy().a(.2f), Pal.heal.cpy().a(.5f), Pal.heal.cpy().mul(1.2f), Color.white};
|
||||
}};
|
||||
}});
|
||||
}
|
||||
}
|
||||
abilities.add(new SuppressionFieldAbility(){{
|
||||
orbRadius = 5;
|
||||
particleSize = 3;
|
||||
y = -10f;
|
||||
particles = 10;
|
||||
color = particleColor = effectColor = Pal.heal;
|
||||
}});
|
||||
|
||||
}};
|
||||
|
||||
//endregion
|
||||
@@ -3115,6 +3117,7 @@ public class UnitTypes{
|
||||
float fin = 0.05f + (j + 1) / (float)count;
|
||||
float spd = speed;
|
||||
float life = lifetime / Mathf.lerp(fin, 1f, 0.5f);
|
||||
boolean show = j == 0 && i > 0;
|
||||
spawnBullets.add(new BasicBulletType(spd * fin, 60){{
|
||||
drag = 0.002f;
|
||||
width = 12f;
|
||||
@@ -3124,6 +3127,7 @@ public class UnitTypes{
|
||||
hitSize = 5f;
|
||||
pierceCap = 2;
|
||||
pierce = true;
|
||||
showStats = show;
|
||||
pierceBuilding = true;
|
||||
hitColor = backColor = trailColor = Color.valueOf("feb380");
|
||||
frontColor = Color.white;
|
||||
|
||||
@@ -43,11 +43,15 @@ public class RepairFieldAbility extends Ability{
|
||||
super.addStats(t);
|
||||
t.add(Core.bundle.format("bullet.range", Strings.autoFixed(range / tilesize, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("repairspeed", Strings.autoFixed(amount * 60f / reload, 2)));
|
||||
t.add(abilityStat("firingrate", Strings.autoFixed(60f / reload, 2)));
|
||||
t.row();
|
||||
if(amount > 0){
|
||||
t.add(Core.bundle.format("bullet.healamount", Strings.autoFixed(amount, 2)) + "[lightgray] ~ []" + abilityStat("repairspeed", Strings.autoFixed(amount * 60f / reload, 2)));
|
||||
t.row();
|
||||
}
|
||||
if(healPercent > 0f){
|
||||
t.row();
|
||||
t.add(Core.bundle.format("bullet.healpercent", Strings.autoFixed(healPercent, 2)));
|
||||
t.add(Core.bundle.format("bullet.healpercent", Strings.autoFixed(healPercent, 2)) + "[lightgray] ~ []" + abilityStat("repairspeed", Strings.autoFixed(healPercent * 60f / reload, 2) + "%"));
|
||||
}
|
||||
if(sameTypeHealMult != 1f){
|
||||
t.row();
|
||||
|
||||
@@ -38,7 +38,7 @@ public class ShieldRegenFieldAbility extends Ability{
|
||||
t.row();
|
||||
t.add(abilityStat("firingrate", Strings.autoFixed(60f / reload, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("pulseregen", Strings.autoFixed(amount, 2)));
|
||||
t.add(abilityStat("pulseregen", Strings.autoFixed(amount, 2)) + "[lightgray] ~ []" + abilityStat("regen", Strings.autoFixed(amount * 60f / reload, 2)));
|
||||
t.row();
|
||||
t.add(abilityStat("shield", Strings.autoFixed(max, 2)));
|
||||
}
|
||||
|
||||
@@ -241,6 +241,8 @@ public class BulletType extends Content implements Cloneable{
|
||||
public Effect healEffect = Fx.healBlockFull;
|
||||
/** Bullets spawned when this bullet is created. Rarely necessary, used for visuals. */
|
||||
public Seq<BulletType> spawnBullets = new Seq<>();
|
||||
/** Whether to display the stats of the spawned bullet. */
|
||||
public boolean showStats = false;
|
||||
/** Random angle spread of spawn bullets. */
|
||||
public float spawnBulletRandomSpread = 0f;
|
||||
/** Unit spawned _instead of_ this bullet. Useful for missiles. */
|
||||
|
||||
@@ -113,10 +113,17 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
}
|
||||
|
||||
public void updateBoosting(boolean boost){
|
||||
updateBoosting(boost, false);
|
||||
}
|
||||
|
||||
public void updateBoosting(boolean boost, boolean event){
|
||||
if(!type.canBoost || dead) return;
|
||||
|
||||
boolean shouldBoost = boost || onSolid() || (isFlying() && !canLand());
|
||||
elevation = Mathf.approachDelta(elevation, type.canBoost ? Mathf.num(shouldBoost) : 0f, shouldBoost ? type.riseSpeed : type.descentSpeed);
|
||||
if(event){
|
||||
Events.fire(Trigger.unitCommandBoost);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move based on preferred unit movement type. */
|
||||
|
||||
@@ -46,6 +46,7 @@ public class EventType{
|
||||
unitCommandChange,
|
||||
unitCommandPosition,
|
||||
unitCommandAttack,
|
||||
unitCommandBoost,
|
||||
importMod,
|
||||
draw,
|
||||
drawOver,
|
||||
|
||||
@@ -177,6 +177,12 @@ public class GameService{
|
||||
}
|
||||
});
|
||||
|
||||
Events.run(Trigger.unitCommandBoost, () -> {
|
||||
if(campaign()){
|
||||
boostUnit.complete();
|
||||
}
|
||||
});
|
||||
|
||||
Events.run(Trigger.newGame, () -> Core.app.post(() -> {
|
||||
if(campaign() && player.core() != null && player.core().items.total() >= 10 * 1000){
|
||||
drop10kitems.complete();
|
||||
|
||||
@@ -794,8 +794,10 @@ public class UnitType extends UnlockableContent implements Senseable{
|
||||
}
|
||||
|
||||
if(legSplashDamage > 0 && legSplashRange > 0){
|
||||
stats.add(Stat.legSplashDamage, legSplashDamage, StatUnit.perLeg);
|
||||
stats.add(Stat.legSplashRange, Strings.autoFixed(legSplashRange / tilesize, 1), StatUnit.blocks);
|
||||
stats.add(Stat.legSplashDamage, table -> {
|
||||
table.add((String)(Core.bundle.format("bullet.splashdamage", Strings.autoFixed(legSplashDamage, 2),
|
||||
Strings.autoFixed(legSplashRange / tilesize, 2))).replace("[stat]", "[white]") + " " + StatUnit.perLeg.localized());
|
||||
});
|
||||
}
|
||||
|
||||
stats.add(Stat.targetsAir, targetAir);
|
||||
@@ -809,6 +811,9 @@ public class UnitType extends UnlockableContent implements Senseable{
|
||||
|
||||
if(!flying){
|
||||
stats.add(Stat.canBoost, canBoost);
|
||||
if(canBoost){
|
||||
stats.add(Stat.boostingSpeed, boostMultiplier * speed * 60f / tilesize, StatUnit.tilesSecond);
|
||||
}
|
||||
}
|
||||
|
||||
if(mineTier >= 1){
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package mindustry.type.weapons;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -38,6 +43,12 @@ public class PointDefenseWeapon extends Weapon{
|
||||
targetInterval = 10f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStats(UnitType u, Table t){
|
||||
t.add(Core.bundle.format("weapon.pointdefense"));
|
||||
super.addStats(u, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Teamc findTarget(Unit unit, float x, float y, float range, boolean air, boolean ground){
|
||||
return Groups.bullet.intersect(x - range, y - range, range*2, range*2).min(b -> b.team != unit.team && b.type().hittable, b -> b.dst2(x, y));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.defense;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
@@ -11,6 +12,7 @@ import mindustry.entities.bullet.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class ShockMine extends Block{
|
||||
public final int timerDamage = timers++;
|
||||
@@ -35,6 +37,14 @@ public class ShockMine extends Block{
|
||||
targetable = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
stats.add(Stat.damage, table -> {
|
||||
table.add((String)(Core.bundle.format("bullet.lightning", tendrils, Strings.autoFixed(damage, 2)).replace("[stat]", "[white]")));
|
||||
});
|
||||
}
|
||||
|
||||
public class ShockMineBuild extends Building{
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,6 +52,7 @@ public class PointDefenseTurret extends ReloadTurret{
|
||||
super.setStats();
|
||||
|
||||
stats.add(Stat.reload, 60f / reload, StatUnit.perSecond);
|
||||
stats.add(Stat.damage, bulletDamage, StatUnit.none);
|
||||
}
|
||||
|
||||
public class PointDefenseBuild extends ReloadTurretBuild{
|
||||
|
||||
@@ -30,7 +30,9 @@ public class Junction extends Block{
|
||||
|
||||
//(60f / speed * capacity) returns 13.84 which is not the actual value (non linear, depends on fps)
|
||||
stats.add(Stat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
|
||||
stats.add(Stat.itemCapacity, capacity, StatUnit.items);
|
||||
stats.add(Stat.itemCapacity, table -> {
|
||||
table.add(Strings.autoFixed(capacity, 2) + " " + StatUnit.items.localized() + " " + StatUnit.perSide.localized());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -59,6 +59,13 @@ public class ImpactReactor extends PowerGenerator{
|
||||
if(hasItems){
|
||||
stats.add(Stat.productionTime, itemDuration / 60f, StatUnit.seconds);
|
||||
}
|
||||
//exponential decay formula
|
||||
float max = -(float)Math.log(0.001f) / warmupSpeed / 60f;
|
||||
float equal = -(float)Math.log(1f - Mathf.pow(consPower.usage / powerProduction, 1f / 5f)) / warmupSpeed / 60f;
|
||||
stats.add(Stat.warmupTime, t -> {
|
||||
t.add(Strings.autoFixed(max, 2) + " " + StatUnit.seconds.localized() + (consPower != null ?
|
||||
" ~ " + Strings.autoFixed(equal, 2) + " " + StatUnit.seconds.localized() + " " + StatUnit.powerEquilibrium.localized() : ""));
|
||||
});
|
||||
}
|
||||
|
||||
public class ImpactReactorBuild extends GeneratorBuild{
|
||||
|
||||
@@ -36,6 +36,7 @@ public class Stat implements Comparable<Stat>{
|
||||
lightningDamage = new Stat("lightningDamage"),
|
||||
abilities = new Stat("abilities"),
|
||||
canBoost = new Stat("canBoost"),
|
||||
boostingSpeed = new Stat("boostingspeed"),
|
||||
maxUnits = new Stat("maxUnits"),
|
||||
|
||||
damageMultiplier = new Stat("damageMultiplier"),
|
||||
@@ -60,6 +61,7 @@ public class Stat implements Comparable<Stat>{
|
||||
powerRange = new Stat("powerRange", StatCat.power),
|
||||
powerConnections = new Stat("powerConnections", StatCat.power),
|
||||
basePowerGeneration = new Stat("basePowerGeneration", StatCat.power),
|
||||
warmupTime = new Stat("warmupTime", StatCat.power),
|
||||
|
||||
tiles = new Stat("tiles", StatCat.crafting),
|
||||
input = new Stat("input", StatCat.crafting),
|
||||
|
||||
@@ -20,6 +20,7 @@ public class StatUnit{
|
||||
itemsSecond = new StatUnit("itemsSecond"),
|
||||
liquidUnits = new StatUnit("liquidUnits", "[sky]" + Iconc.liquid + "[]"),
|
||||
powerUnits = new StatUnit("powerUnits", "[accent]" + Iconc.power + "[]"),
|
||||
powerEquilibrium = new StatUnit("powerEquilibrium"),
|
||||
heatUnits = new StatUnit("heatUnits", "[red]" + Iconc.waves + "[]"),
|
||||
degrees = new StatUnit("degrees"),
|
||||
seconds = new StatUnit("seconds"),
|
||||
@@ -29,6 +30,7 @@ public class StatUnit{
|
||||
perMinute = new StatUnit("perMinute", false),
|
||||
perShot = new StatUnit("perShot", false),
|
||||
perLeg = new StatUnit("perLeg"),
|
||||
perSide = new StatUnit("perSide"),
|
||||
timesSpeed = new StatUnit("timesSpeed", false),
|
||||
multiplier = new StatUnit("multiplier", false),
|
||||
percent = new StatUnit("percent", false),
|
||||
|
||||
@@ -7,6 +7,7 @@ import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.Tooltip.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
@@ -19,6 +20,7 @@ import mindustry.ctype.*;
|
||||
import mindustry.entities.abilities.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
@@ -31,6 +33,9 @@ import static mindustry.Vars.*;
|
||||
/** Utilities for displaying certain stats in a table. */
|
||||
public class StatValues{
|
||||
|
||||
//only allocate once, dont break unit tests
|
||||
static @Nullable TextureRegionDrawable noteIcon = Icon.arrowNoteSmall != null ? new TextureRegionDrawable(Icon.arrowNoteSmall) : null;
|
||||
|
||||
public static StatValue string(String value, Object... args){
|
||||
String result = Strings.format(value, args);
|
||||
return table -> table.add(result);
|
||||
@@ -640,11 +645,8 @@ public class StatValues{
|
||||
}
|
||||
|
||||
if(type.damage > 0 && (type.collides || type.splashDamage <= 0)){
|
||||
if(type.continuousDamage() > 0){
|
||||
bt.add(Core.bundle.format("bullet.damage", type.continuousDamage()) + StatUnit.perSecond.localized());
|
||||
}else{
|
||||
bt.add(Core.bundle.format("bullet.damage", type.damage));
|
||||
}
|
||||
bt.add(Core.bundle.format("bullet.damage", type.damage) + (type.continuousDamage() > 0 ?
|
||||
"[lightgray] ~ [stat]" + Core.bundle.format("bullet.damage", type.continuousDamage()) + StatUnit.perSecond.localized() : ""));
|
||||
}
|
||||
|
||||
if(type.buildingDamageMultiplier != 1){
|
||||
@@ -700,17 +702,44 @@ public class StatValues{
|
||||
sep(bt, Core.bundle.format("bullet.lightning", type.lightning, type.lightningDamage < 0 ? type.damage : type.lightningDamage));
|
||||
}
|
||||
|
||||
if(type instanceof LaserBulletType b && b.lightningSpacing > 0){
|
||||
int count = (int)(b.length / b.lightningSpacing) * 2 + 2;
|
||||
float damage = b.lightningDamage < 0 ? b.damage : b.lightningDamage;
|
||||
sep(bt, Core.bundle.format("bullet.lightning", count, damage));
|
||||
note(bt, Core.bundle.format("bullet.lightninginterval", Strings.autoFixed(b.lightningSpacing / tilesize, 2), Strings.autoFixed(b.lightningLength, 2))).left();
|
||||
}
|
||||
|
||||
if(type instanceof EmpBulletType b && b.radius > 0f){
|
||||
sep(bt, Core.bundle.format("bullet.empradius", Strings.fixed(b.radius / tilesize, 1)));
|
||||
if(b.timeDuration > 0f && b.timeIncrease > 1f){
|
||||
sep(bt, Core.bundle.format("bullet.empboost", Strings.autoFixed(b.timeIncrease * 100f, 2),
|
||||
Strings.autoFixed(b.timeDuration / 60f, 1)) + " " + StatUnit.seconds.localized());
|
||||
}
|
||||
if(b.timeDuration > 0f && b.powerSclDecrease < 1f){
|
||||
sep(bt, Core.bundle.format("bullet.empslowdown",
|
||||
(b.powerSclDecrease < 1f ? "[negstat]" : "") + Strings.autoFixed((b.powerSclDecrease - 1f) * 100f, 2),
|
||||
Strings.autoFixed(b.timeDuration / 60f, 1)) + " " + StatUnit.seconds.localized());
|
||||
}
|
||||
if(!Mathf.equal(b.powerDamageScl, 1f)){
|
||||
sep(bt, Core.bundle.format("bullet.empdamage", Strings.autoFixed(b.powerDamageScl * 100f, 2)));
|
||||
}
|
||||
if(b.hitUnits){
|
||||
sep(bt, Core.bundle.format("bullet.empunitdamage",
|
||||
(b.unitDamageScl < 1f ? "[negstat]" : "") + Strings.autoFixed(b.unitDamageScl * 100f, 2)));
|
||||
}
|
||||
}
|
||||
|
||||
if(type.pierceArmor){
|
||||
sep(bt, "@bullet.armorpierce");
|
||||
}
|
||||
|
||||
if(type.armorMultiplier != 1f){
|
||||
if(type.armorMultiplier > 1f){
|
||||
sep(bt, Core.bundle.format("bullet.armorweakness", (int)(type.armorMultiplier * 100)));
|
||||
sep(bt, Core.bundle.format("bullet.armorweakness", (int)(type.armorMultiplier * 100)));
|
||||
}else if(Mathf.sign(type.armorMultiplier) == 1){
|
||||
sep(bt, Core.bundle.format("bullet.armorpiercing", (int)((1 - type.armorMultiplier) * 100)));
|
||||
sep(bt, Core.bundle.format("bullet.armorpiercing", (int)((1 - type.armorMultiplier) * 100)));
|
||||
}else{
|
||||
sep(bt, Core.bundle.format("bullet.antiarmor", (-type.armorMultiplier)));
|
||||
sep(bt, Core.bundle.format("bullet.antiarmor", (-type.armorMultiplier)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -770,6 +799,27 @@ public class StatValues{
|
||||
bt.row();
|
||||
bt.add(coll);
|
||||
}
|
||||
|
||||
if(type.spawnBullets != null && type.spawnBullets.size > 0){
|
||||
bt.row();
|
||||
|
||||
Table sc = new Table();
|
||||
for(BulletType spawn : type.spawnBullets){
|
||||
if(spawn.showStats) ammo(ObjectMap.of(t, spawn), true, false).display(sc);
|
||||
}
|
||||
Collapser coll = new Collapser(sc, true);
|
||||
coll.setDuration(0.1f);
|
||||
|
||||
bt.table(st -> {
|
||||
st.left().defaults().left();
|
||||
|
||||
st.add(Core.bundle.format("bullet.spawnBullets", type.spawnBullets.size));
|
||||
if(sc.getChildren().size > 0) st.button(Icon.downOpen, Styles.emptyi, () -> coll.toggle(false)).update(i -> i.getStyle().imageUp = (!coll.isCollapsed() ? Icon.upOpen : Icon.downOpen)).size(8).padLeft(16f).expandX();
|
||||
});
|
||||
bt.row();
|
||||
bt.add(coll);
|
||||
}
|
||||
|
||||
}).padLeft(5).padTop(5).padBottom(compact ? 0 : 5).growX().margin(compact ? 0 : 10);
|
||||
table.row();
|
||||
}
|
||||
@@ -782,6 +832,19 @@ public class StatValues{
|
||||
return table.add(text);
|
||||
}
|
||||
|
||||
//add a note under a value
|
||||
private static Cell<?> note(Table table, String text){
|
||||
table.row();
|
||||
return table.table(t -> {
|
||||
if(noteIcon != null){
|
||||
noteIcon.setMinWidth(15f);
|
||||
noteIcon.setMinHeight(15f);
|
||||
t.image(noteIcon).color(Pal.stat).scaling(Scaling.fit).padRight(6).padLeft(12);
|
||||
}
|
||||
t.add(text);
|
||||
});
|
||||
}
|
||||
|
||||
//for AmmoListValue
|
||||
private static String ammoStat(float val){
|
||||
return (val > 0 ? "[stat]+" : "[negstat]") + Strings.autoFixed(val, 1);
|
||||
|
||||
Reference in New Issue
Block a user