Ammo stats

This commit is contained in:
Anuken
2019-03-24 17:55:41 -04:00
parent f7aa58e385
commit 87481e0a4d
12 changed files with 187 additions and 90 deletions

View File

@ -397,6 +397,19 @@ blocks.fuelburntime = Fuel Burn Time
blocks.inputcapacity = Input capacity
blocks.outputcapacity = Output capacity
blocks.ammo = Ammo
bullet.damage = [stat]{0}[lightgray] dmg
bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles
bullet.incendiary = [stat]incendiary
bullet.homing = [stat]homing
bullet.shock = [stat]shock
bullet.frag = [stat]frag
bullet.knockback = [stat]{0}[lightgray] knockback
bullet.freezing = [stat]freezing
bullet.tarred = [stat]tarred
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x reload
unit.blocks = blocks
unit.powersecond = power units/second
unit.liquidsecond = liquid units/second

View File

@ -294,7 +294,6 @@ public class Bullets implements ContentList{
standardDense = new BasicBulletType(3.5f, 18, "bullet"){{
bulletWidth = 9f;
bulletHeight = 12f;
armorPierce = 0.2f;
reloadMultiplier = 0.6f;
ammoMultiplier = 2;
}};
@ -302,7 +301,6 @@ public class Bullets implements ContentList{
standardThorium = new BasicBulletType(4f, 29, "bullet"){{
bulletWidth = 10f;
bulletHeight = 13f;
armorPierce = 0.5f;
shootEffect = Fx.shootBig;
smokeEffect = Fx.shootBigSmoke;
ammoMultiplier = 2;
@ -348,14 +346,12 @@ public class Bullets implements ContentList{
standardDenseBig = new BasicBulletType(7f, 42, "bullet"){{
bulletWidth = 15f;
bulletHeight = 21f;
armorPierce = 0.2f;
shootEffect = Fx.shootBig;
}};
standardThoriumBig = new BasicBulletType(8f, 65, "bullet"){{
bulletWidth = 16f;
bulletHeight = 23f;
armorPierce = 0.5f;
shootEffect = Fx.shootBig;
}};

View File

@ -108,6 +108,7 @@ public class UI implements ApplicationListener{
});
Colors.put("accent", Pal.accent);
Colors.put("stat", Pal.stat);
loadCursors();
}

View File

@ -4,13 +4,6 @@ import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.effect.Lightning;
import io.anuke.mindustry.entities.traits.TargetTrait;
import io.anuke.mindustry.graphics.Pal;
/**An extended BulletType for most ammo-based bullets shot from turrets and units.*/
@ -20,28 +13,9 @@ public class BasicBulletType extends BulletType{
public float bulletShrink = 0.5f;
public String bulletSprite;
public int fragBullets = 9;
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f;
public BulletType fragBullet = null;
/**Use a negative value to disable splash damage.*/
public float splashDamageRadius = -1f;
public int incendAmount = 0;
public float incendSpread = 8f;
public float incendChance = 1f;
public float homingPower = 0f;
public float homingRange = 50f;
public int lightining;
public int lightningLength = 5;
public TextureRegion backRegion;
public TextureRegion frontRegion;
public float hitShake = 0f;
public BasicBulletType(float speed, float damage, String bulletSprite){
super(speed, damage);
this.bulletSprite = bulletSprite;
@ -63,51 +37,4 @@ public class BasicBulletType extends BulletType{
Draw.rect(frontRegion, b.x, b.y, bulletWidth, height, b.rot() - 90);
Draw.color();
}
@Override
public void update(Bullet b){
super.update(b);
if(homingPower > 0.0001f){
TargetTrait target = Units.getClosestTarget(b.getTeam(), b.x, b.y, homingRange);
if(target != null){
b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f));
}
}
}
@Override
public void hit(Bullet b, float x, float y){
super.hit(b, x, y);
Effects.shake(hitShake, hitShake, b);
if(fragBullet != null){
for(int i = 0; i < fragBullets; i++){
float len = Mathf.random(1f, 7f);
float a = Mathf.random(360f);
Bullet.create(fragBullet, b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax));
}
}
if(Mathf.chance(incendChance)){
Damage.createIncend(x, y, incendSpread, incendAmount);
}
if(splashDamageRadius > 0){
Damage.damage(b.getTeam(), x, y, splashDamageRadius, splashDamage);
}
}
@Override
public void despawned(Bullet b){
super.despawned(b);
if(fragBullet != null || splashDamageRadius > 0){
hit(b);
}
for (int i = 0; i < lightining; i++) {
Lightning.create(b.getTeam(), Pal.surge, damage, b.x, b.y, Mathf.random(360f), lightningLength);
}
}
}

View File

@ -1,10 +1,17 @@
package io.anuke.mindustry.entities.bullet;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.effect.Lightning;
import io.anuke.mindustry.entities.traits.TargetTrait;
import io.anuke.mindustry.game.Content;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.StatusEffect;
import io.anuke.mindustry.world.Tile;
@ -41,8 +48,6 @@ public abstract class BulletType extends Content{
public StatusEffect status = StatusEffects.none;
/**Intensity of applied status effect in terms of duration.*/
public float statusDuration = 60 * 1f;
/**What fraction of armor is pierced, 0-1*/
public float armorPierce = 0f;
/**Whether to sync this bullet to clients.*/
public boolean syncable;
/**Whether this bullet type collides with tiles.*/
@ -56,6 +61,27 @@ public abstract class BulletType extends Content{
/**Whether velocity is inherited from the shooter.*/
public boolean keepVelocity = true;
//additional effects
public int fragBullets = 9;
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f;
public BulletType fragBullet = null;
/**Use a negative value to disable splash damage.*/
public float splashDamageRadius = -1f;
public int incendAmount = 0;
public float incendSpread = 8f;
public float incendChance = 1f;
public float homingPower = 0f;
public float homingRange = 50f;
public int lightining;
public int lightningLength = 5;
public float hitShake = 0f;
public BulletType(float speed, float damage){
this.speed = speed;
this.damage = damage;
@ -81,12 +107,38 @@ public abstract class BulletType extends Content{
hit(b, b.x, b.y);
}
public void hit(Bullet b, float hitx, float hity){
Effects.effect(hitEffect, hitx, hity, b.rot());
public void hit(Bullet b, float x, float y){
Effects.effect(hitEffect, x, y, b.rot());
Effects.shake(hitShake, hitShake, b);
if(fragBullet != null){
for(int i = 0; i < fragBullets; i++){
float len = Mathf.random(1f, 7f);
float a = Mathf.random(360f);
Bullet.create(fragBullet, b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax));
}
}
if(Mathf.chance(incendChance)){
Damage.createIncend(x, y, incendSpread, incendAmount);
}
if(splashDamageRadius > 0){
Damage.damage(b.getTeam(), x, y, splashDamageRadius, splashDamage);
}
}
public void despawned(Bullet b){
Effects.effect(despawnEffect, b.x, b.y, b.rot());
if(fragBullet != null || splashDamageRadius > 0){
hit(b);
}
for (int i = 0; i < lightining; i++) {
Lightning.create(b.getTeam(), Pal.surge, damage, b.x, b.y, Mathf.random(360f), lightningLength);
}
}
public void draw(Bullet b){
@ -96,6 +148,13 @@ public abstract class BulletType extends Content{
}
public void update(Bullet b){
if(homingPower > 0.0001f){
TargetTrait target = Units.getClosestTarget(b.getTeam(), b.x, b.y, homingRange);
if(target != null){
b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f));
}
}
}
@Override

View File

@ -48,6 +48,7 @@ public class Pal{
heal = Color.valueOf("98ffa9"),
bar = Color.SLATE,
accent = Color.valueOf("ffd37f"),
stat = Color.valueOf("ffd37f"),
locked = Color.valueOf("989aa4"),
accentBack = Color.valueOf("d4816b"),
place = Color.valueOf("6335f8"),

View File

@ -3,6 +3,8 @@ package io.anuke.mindustry.world.blocks.defense.turrets;
import io.anuke.arc.math.Mathf;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.StatUnit;
import static io.anuke.mindustry.Vars.tilesize;
@ -14,6 +16,14 @@ public class DoubleTurret extends ItemTurret{
shots = 2;
}
@Override
public void setStats(){
super.setStats();
stats.remove(BlockStat.reload);
stats.add(BlockStat.reload, 60f / reload, StatUnit.none);
}
@Override
protected void shoot(Tile tile, BulletType ammo){
TurretEntity entity = tile.entity();

View File

@ -1,6 +1,7 @@
package io.anuke.mindustry.world.blocks.defense.turrets;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.collection.OrderedMap;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.bullet.BulletType;
@ -11,7 +12,7 @@ import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.ui.Bar;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.values.ItemFilterValue;
import io.anuke.mindustry.world.meta.values.AmmoListValue;
import java.io.DataInput;
import java.io.DataOutput;
@ -28,7 +29,7 @@ public class ItemTurret extends CooledTurret{
/**Initializes accepted ammo map. Format: [item1, bullet1, item2, bullet2...]*/
protected void ammo(Object... objects){
ammo = ObjectMap.of(objects);
ammo = OrderedMap.of(objects);
}
@Override
@ -36,7 +37,7 @@ public class ItemTurret extends CooledTurret{
super.setStats();
stats.remove(BlockStat.itemCapacity);
stats.add(BlockStat.inputItems, new ItemFilterValue(item -> ammo.containsKey(item)));
stats.add(BlockStat.ammo, new AmmoListValue<>(ammo));
}

View File

@ -1,6 +1,7 @@
package io.anuke.mindustry.world.blocks.defense.turrets;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.collection.OrderedMap;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.entities.effect.Fire;
@ -8,7 +9,7 @@ import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.values.LiquidFilterValue;
import io.anuke.mindustry.world.meta.values.AmmoListValue;
import static io.anuke.mindustry.Vars.tilesize;
import static io.anuke.mindustry.Vars.world;
@ -23,14 +24,14 @@ public abstract class LiquidTurret extends Turret{
/**Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...]*/
protected void ammo(Object... objects){
ammo = ObjectMap.of(objects);
ammo = OrderedMap.of(objects);
}
@Override
public void setStats(){
super.setStats();
stats.add(BlockStat.inputLiquid, new LiquidFilterValue(item -> ammo.containsKey(item)));
stats.add(BlockStat.ammo, new AmmoListValue<>(ammo));
}
@Override

View File

@ -106,7 +106,7 @@ public abstract class Turret extends Block{
stats.add(BlockStat.shootRange, range, StatUnit.blocks);
stats.add(BlockStat.inaccuracy, (int) inaccuracy, StatUnit.degrees);
stats.add(BlockStat.reload, 60f / reload, StatUnit.none);
stats.add(BlockStat.reload, 60f / reload * shots, StatUnit.none);
stats.add(BlockStat.shots, shots, StatUnit.none);
stats.add(BlockStat.targetsAir, targetAir);
stats.add(BlockStat.targetsGround, targetGround);

View File

@ -41,6 +41,7 @@ public enum BlockStat{
drillSpeed(StatCategory.crafting),
maxUnits(StatCategory.crafting),
ammo(StatCategory.shooting),
shootRange(StatCategory.shooting),
inaccuracy(StatCategory.shooting),
shots(StatCategory.shooting),

View File

@ -0,0 +1,87 @@
package io.anuke.mindustry.world.meta.values;
import io.anuke.arc.Core;
import io.anuke.arc.collection.ObjectMap;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Strings;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Item.Icon;
import io.anuke.mindustry.world.meta.StatValue;
import static io.anuke.mindustry.Vars.tilesize;
public class AmmoListValue<T extends UnlockableContent> implements StatValue{
private final ObjectMap<T, BulletType> map;
public AmmoListValue(ObjectMap<T, BulletType> map){
this.map = map;
}
@Override
public void display(Table table){
table.row();
for(T t : map.keys()){
BulletType type = map.get(t);
table.addImage(icon(t)).size(3*8).padRight(4).right().top();
table.add(t.localizedName()).padRight(10).left().top();
table.table("underline", bt -> {
bt.left().defaults().padRight(3).left();
bt.add(Core.bundle.format("bullet.damage", type.damage));
if(type.splashDamage > 0){
sep(bt, Core.bundle.format("bullet.splashdamage", (int)type.splashDamage, Strings.toFixed(type.splashDamageRadius / tilesize, 1)));
}
if(!Mathf.isEqual(type.ammoMultiplier, 1f)) sep(bt, Core.bundle.format("bullet.multiplier", (int)type.ammoMultiplier));
if(!Mathf.isEqual(type.reloadMultiplier, 1f)) sep(bt, Core.bundle.format("bullet.reload", Strings.toFixed(type.reloadMultiplier, 1)));
if(type.knockback > 0){
sep(bt, Core.bundle.format("bullet.knockback", Strings.toFixed(type.knockback, 1)));
}
if((type.status == StatusEffects.burning || type.status == StatusEffects.melting) || type.incendAmount > 0){
sep(bt, "$bullet.incendiary");
}
if(type.status == StatusEffects.freezing){
sep(bt, "$bullet.freezing");
}
if(type.status == StatusEffects.tarred){
sep(bt, "$bullet.tarred");
}
if(type.homingPower > 0.01f){
sep(bt, "$bullet.homing");
}
if(type.lightining > 0){
sep(bt, "$bullet.shock");
}
if(type.fragBullet != null){
sep(bt, "$bullet.frag");
}
}).left().padTop(-9);
table.row();
}
}
void sep(Table table, String text){
table.row();
table.add(text);
}
TextureRegion icon(T t){
if(t instanceof Item){
return ((Item)t).icon(Icon.medium);
}
return t.getContentIcon();
}
}