Partial 7.0 merge - API preview

This commit is contained in:
Anuken
2021-06-02 11:08:08 -04:00
parent ea75a357ca
commit 28b235ef07
531 changed files with 12356 additions and 6286 deletions
@@ -18,6 +18,24 @@ public class ArtilleryBulletType extends BasicBulletType{
hitSound = Sounds.explosion;
shootEffect = Fx.shootBig;
trailEffect = Fx.artilleryTrail;
//default settings:
shrinkX = 0.15f;
shrinkY = 0.63f;
//for trail:
/*
trailLength = 27;
trailWidth = 3.5f;
trailEffect = Fx.none;
trailColor = Pal.bulletYellowBack;
trailInterp = Interp.slope;
shrinkX = 0.8f;
shrinkY = 0.3f;
*/
}
public ArtilleryBulletType(float speed, float damage){
@@ -39,15 +57,13 @@ public class ArtilleryBulletType extends BasicBulletType{
@Override
public void draw(Bullet b){
float baseScale = 0.7f;
float scale = (baseScale + b.fslope() * (1f - baseScale));
float height = this.height * ((1f - shrinkY) + shrinkY * b.fout());
drawTrail(b);
float xscale = (1f - shrinkX + b.fslope() * (shrinkX)), yscale = (1f - shrinkY + b.fslope() * (shrinkY)), rot = b.rotation();
Draw.color(backColor);
Draw.rect(backRegion, b.x, b.y, width * scale, height * scale, b.rotation() - 90);
Draw.rect(backRegion, b.x, b.y, width * xscale, height * yscale, rot - 90);
Draw.color(frontColor);
Draw.rect(frontRegion, b.x, b.y, width * scale, height * scale, b.rotation() - 90);
Draw.rect(frontRegion, b.x, b.y, width * xscale, height * yscale, rot - 90);
Draw.color();
}
}
@@ -42,6 +42,7 @@ public class BasicBulletType extends BulletType{
@Override
public void draw(Bullet b){
super.draw(b);
float height = this.height * ((1f - shrinkY) + shrinkY * b.fout());
float width = this.width * ((1f - shrinkX) + shrinkX * b.fout());
float offset = -90 + (spin != 0 ? Mathf.randomSeed(b.id, 360f) + b.time * spin : 0f);
@@ -1,39 +1,60 @@
package mindustry.entities.bullet;
import arc.*;
import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.defense.Wall.*;
import static mindustry.Vars.*;
public abstract class BulletType extends Content{
public class BulletType extends Content implements Cloneable{
/** Lifetime in ticks. */
public float lifetime = 40f;
public float speed;
public float damage;
/** Speed in units/tick. */
public float speed = 1f;
/** Direct damage dealt on hit. */
public float damage = 1f;
/** Hitbox size. */
public float hitSize = 4;
/** Clipping hitbox. */
public float drawSize = 40f;
/** Drag as fraction of velocity. */
public float drag = 0f;
public boolean pierce, pierceBuilding;
/** Whether to pierce units. */
public boolean pierce;
/** Whether to pierce buildings. */
public boolean pierceBuilding;
/** Maximum # of pierced objects. */
public int pierceCap = -1;
public Effect hitEffect, despawnEffect;
/** Z layer to drawn on. */
public float layer = Layer.bullet;
/** Effect shown on direct hit. */
public Effect hitEffect = Fx.hitBulletSmall;
/** Effect shown when bullet despawns. */
public Effect despawnEffect = Fx.hitBulletSmall;
/** Effect created when shooting. */
public Effect shootEffect = Fx.shootSmall;
/** Extra smoke effect created when shooting. */
public Effect smokeEffect = Fx.shootSmallSmoke;
/** Sound made when hitting something or getting removed.*/
public Sound hitSound = Sounds.none;
/** Sound made when hitting something or getting removed.*/
public Sound despawnSound = Sounds.none;
/** Pitch of the sound made when hitting something*/
public float hitSoundPitch = 1;
/** Volume of the sound made when hitting something*/
@@ -80,15 +101,17 @@ public abstract class BulletType extends Content{
public boolean reflectable = true;
/** Whether this projectile can be absorbed by shields. */
public boolean absorbable = true;
/** Whether to move the bullet back depending on delta to fix some delta-time realted issues.
/** Whether to move the bullet back depending on delta to fix some delta-time related issues.
* Do not change unless you know what you're doing. */
public boolean backMove = true;
/** Bullet range override. */
public float maxRange = -1f;
/** % of block health healed **/
public float healPercent = 0f;
/** whether to make fire on impact */
/** Whether to make fire on impact */
public boolean makeFire = false;
/** Whether to create hit effects on despawn. Forced to true if this bullet has any special effects like splash damage. */
public boolean despawnHit = false;
//additional effects
@@ -101,8 +124,14 @@ public abstract class BulletType extends Content{
public Color trailColor = Pal.missileYellowBack;
public float trailChance = -0.0001f;
public float trailInterval = 0f;
public Effect trailEffect = Fx.missileTrail;
public float trailParam = 2f;
public boolean trailRotation = false;
public Interp trailInterp = Interp.one;
/** Any value <= 0 disables the trail. */
public int trailLength = -1;
public float trailWidth = 2f;
/** Use a negative value to disable splash damage. */
public float splashDamageRadius = -1f;
@@ -134,19 +163,27 @@ public abstract class BulletType extends Content{
public float puddleAmount = 5f;
public Liquid puddleLiquid = Liquids.water;
public float lightRadius = 16f;
public float lightRadius = -1f;
public float lightOpacity = 0.3f;
public Color lightColor = Pal.powerLight;
public BulletType(float speed, float damage){
this.speed = speed;
this.damage = damage;
hitEffect = Fx.hitBulletSmall;
despawnEffect = Fx.hitBulletSmall;
}
public BulletType(){
this(1f, 1f);
}
public BulletType copy(){
try{
BulletType copy = (BulletType)clone();
copy.id = (short)Vars.content.getBy(getContentType()).size;
Vars.content.handleContent(copy);
return copy;
}catch(Exception e){
throw new RuntimeException("death to checked exceptions", e);
}
}
/** @return estimated damage per shot. this can be very inaccurate. */
@@ -181,13 +218,13 @@ public abstract class BulletType extends Content{
if(healPercent > 0f && build.team == b.team && !(build.block instanceof ConstructBlock)){
Fx.healBlockFull.at(build.x, build.y, build.block.size, Pal.heal);
build.heal(healPercent / 100f * build.maxHealth());
build.heal(healPercent / 100f * build.maxHealth);
}else if(build.team != b.team && direct){
hit(b);
}
}
public void hitEntity(Bullet b, Hitboxc entity, float initialHealth){
public void hitEntity(Bullet b, Hitboxc entity, float health){
if(entity instanceof Healthc h){
h.damage(b.damage);
}
@@ -198,6 +235,11 @@ public abstract class BulletType extends Content{
unit.impulse(Tmp.v3);
unit.apply(status, statusDuration);
}
//for achievements
if(b.owner instanceof WallBuild && player != null && b.team == player.team() && entity instanceof Unit unit && unit.dead){
Events.fire(Trigger.phaseDeflectHit);
}
}
public void hit(Bullet b){
@@ -205,7 +247,6 @@ public abstract class BulletType extends Content{
}
public void hit(Bullet b, float x, float y){
b.hit = true;
hitEffect.at(x, y, b.rotation(), hitColor);
hitSound.at(x, y, hitSoundPitch, hitSoundVolume);
@@ -226,7 +267,7 @@ public abstract class BulletType extends Content{
}
}
if(Mathf.chance(incendChance)){
if(incendChance > 0 && Mathf.chance(incendChance)){
Damage.createIncend(x, y, incendSpread, incendAmount);
}
@@ -245,9 +286,7 @@ public abstract class BulletType extends Content{
}
if(makeFire){
indexer.eachBlock(null, x, y, splashDamageRadius, other -> other.team != b.team, other -> {
Fires.create(other.tile);
});
indexer.eachBlock(null, x, y, splashDamageRadius, other -> other.team != b.team, other -> Fires.create(other.tile));
}
}
@@ -256,21 +295,40 @@ public abstract class BulletType extends Content{
}
}
/** Called when the bullet reaches the end of its lifetime of is destroyed by something external. */
public void despawned(Bullet b){
if(despawnHit){
hit(b);
}
despawnEffect.at(b.x, b.y, b.rotation(), hitColor);
hitSound.at(b);
despawnSound.at(b);
Effect.shake(despawnShake, despawnShake, b);
}
if(!b.hit && (fragBullet != null || splashDamageRadius > 0 || lightning > 0)){
hit(b);
/** Called when the bullet is removed for any reason. */
public void removed(Bullet b){
if(trailLength > 0 && b.trail != null && b.trail.size() > 0){
Fx.trailFade.at(b.x, b.y, trailWidth, trailColor, b.trail.copy());
}
}
public void draw(Bullet b){
drawTrail(b);
}
public void drawTrail(Bullet b){
if(trailLength > 0 && b.trail != null){
//draw below bullets? TODO
float z = Draw.z();
Draw.z(z - 0.0001f);
b.trail.draw(trailColor, trailWidth);
Draw.z(z);
}
}
public void drawLight(Bullet b){
if(lightOpacity <= 0f || lightRadius <= 0f) return;
Drawf.light(b.team, b, lightRadius, lightColor, lightOpacity);
}
@@ -283,11 +341,37 @@ public abstract class BulletType extends Content{
if(instantDisappear){
b.time = lifetime;
}
if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){
despawnHit = true;
}
if(lightRadius == -1){
lightRadius = Math.max(18, hitSize * 5f);
}
drawSize = Math.max(drawSize, trailLength * speed * 2f);
}
public void update(Bullet b){
if(!headless && trailLength > 0){
if(b.trail == null){
b.trail = new Trail(trailLength);
}
b.trail.length = trailLength;
b.trail.update(b.x, b.y, trailInterp.apply(b.fin()));
}
if(homingPower > 0.0001f && b.time >= homingDelay){
Teamc target = Units.closestTarget(b.team, b.x, b.y, homingRange, e -> e.checkTarget(collidesAir, collidesGround), t -> collidesGround);
Teamc target;
//home in on allies if possible
if(healPercent > 0){
target = Units.closestTarget(null, b.x, b.y, homingRange,
e -> e.checkTarget(collidesAir, collidesGround) && e.team != b.team,
t -> collidesGround && (t.team != b.team || t.damaged()));
}else{
target = Units.closestTarget(b.team, b.x, b.y, homingRange, e -> e.checkTarget(collidesAir, collidesGround), t -> collidesGround);
}
if(target != null){
b.vel.setAngle(Angles.moveToward(b.rotation(), b.angleTo(target), homingPower * Time.delta * 50f));
}
@@ -299,7 +383,13 @@ public abstract class BulletType extends Content{
if(trailChance > 0){
if(Mathf.chanceDelta(trailChance)){
trailEffect.at(b.x, b.y, trailParam, trailColor);
trailEffect.at(b.x, b.y, trailRotation ? b.rotation() : trailParam, trailColor);
}
}
if(trailInterval > 0f){
if(b.timer(0, trailInterval)){
trailEffect.at(b.x, b.y, trailRotation ? b.rotation() : trailParam, trailColor);
}
}
}
@@ -366,6 +456,10 @@ public abstract class BulletType extends Content{
bullet.drag = drag;
bullet.hitSize = hitSize;
bullet.damage = (damage < 0 ? this.damage : damage) * bullet.damageMultiplier();
//reset trail
if(bullet.trail != null){
bullet.trail.clear();
}
bullet.add();
if(keepVelocity && owner instanceof Velc v) bullet.vel.add(v.vel().x, v.vel().y);
@@ -0,0 +1,70 @@
package mindustry.entities.bullet;
import mindustry.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
public class EmpBulletType extends BasicBulletType{
public float radius = 100f;
public float timeIncrease = 2.5f, timeDuration = 60f * 10f;
public float powerDamageScl = 2f, powerSclDecrease = 0.2f;
public Effect hitPowerEffect = Fx.hitEmpSpark, chainEffect = Fx.chainEmp, applyEffect = Fx.heal;
public boolean hitUnits = true;
public float unitDamageScl = 0.7f;
@Override
public void hit(Bullet b, float x, float y){
super.hit(b, x, y);
if(!b.absorbed){
Vars.indexer.allBuildings(x, y, radius, other -> {
if(other.team == b.team){
if(other.block.hasPower && other.block.canOverdrive && other.timeScale < timeIncrease){
if(timeIncrease >= other.timeScale){
other.timeScale = Math.max(other.timeScale, timeIncrease);
}
other.timeScaleDuration = Math.max(other.timeScaleDuration, timeDuration);
chainEffect.at(x, y, 0, hitColor, other);
applyEffect.at(other, other.block.size * 7f);
}
if(other.block.hasPower && other.damaged()){
other.heal(healPercent / 100f * other.maxHealth());
Fx.healBlockFull.at(other.x, other.y, other.block.size, hitColor);
applyEffect.at(other, other.block.size * 7f);
}
}else if(other.power != null){
var absorber = Damage.findAbsorber(b.team, x, y, other.x, other.y);
if(absorber != null){
other = absorber;
}
if(other.power != null && other.power.graph.getLastPowerProduced() > 0f){
other.timeScale = Math.min(other.timeScale, powerSclDecrease);
other.timeScaleDuration = timeDuration;
other.damage(damage * powerDamageScl);
hitPowerEffect.at(other.x, other.y, b.angleTo(other), hitColor);
chainEffect.at(x, y, 0, hitColor, other);
}
}
});
if(hitUnits){
Units.nearbyEnemies(b.team, x, y, radius, other -> {
if(other.team != b.team){
var absorber = Damage.findAbsorber(b.team, x, y, other.x, other.y);
if(absorber != null){
return;
}
hitPowerEffect.at(other.x, other.y, b.angleTo(other), hitColor);
chainEffect.at(x, y, 0, hitColor, other);
other.damage(damage * unitDamageScl);
other.apply(status, statusDuration);
}
});
}
}
}
}
@@ -6,7 +6,7 @@ import mindustry.entities.*;
import mindustry.gen.*;
public class FlakBulletType extends BasicBulletType{
public float explodeRange = 30f;
public float explodeRange = 30f, explodeDelay = 5f;
public FlakBulletType(float speed, float damage){
super(speed, damage, "shell");
@@ -25,17 +25,21 @@ public class FlakBulletType extends BasicBulletType{
@Override
public void update(Bullet b){
super.update(b);
if(b.data() instanceof Integer) return;
//don't check for targets if primed to explode
if(b.fdata < 0f) return;
if(b.timer(2, 6)){
Units.nearbyEnemies(b.team, Tmp.r1.setSize(explodeRange * 2f).setCenter(b.x, b.y), unit -> {
if(b.data() instanceof Float || !unit.checkTarget(collidesAir, collidesGround)) return;
//fadata < 0 means it's primed to explode
if(b.fdata < 0f || !unit.checkTarget(collidesAir, collidesGround)) return;
if(unit.dst(b) < explodeRange){
b.data(0);
Time.run(5f, () -> {
if(b.data() instanceof Integer){
b.time(b.lifetime());
if(unit.within(b, explodeRange)){
//mark as primed
b.fdata = -1f;
Time.run(explodeDelay, () -> {
//explode
if(b.fdata < 0){
b.time = b.lifetime;
}
});
}
@@ -3,6 +3,7 @@ package mindustry.entities.bullet;
import arc.graphics.g2d.*;
import mindustry.gen.*;
import mindustry.content.*;
import mindustry.graphics.*;
public class LaserBoltBulletType extends BasicBulletType{
public float width = 2f, height = 7f;
@@ -15,6 +16,8 @@ public class LaserBoltBulletType extends BasicBulletType{
despawnEffect = Fx.hitLaser;
hittable = false;
reflectable = false;
lightColor = Pal.heal;
lightOpacity = 0.6f;
}
public LaserBoltBulletType(){
@@ -23,6 +26,7 @@ public class LaserBoltBulletType extends BasicBulletType{
@Override
public void draw(Bullet b){
super.draw(b);
Draw.color(backColor);
Lines.stroke(width);
Lines.lineAngleCenter(b.x, b.y, b.rotation(), height);
@@ -63,9 +63,10 @@ public class LiquidBulletType extends BulletType{
@Override
public void draw(Bullet b){
super.draw(b);
Draw.color(liquid.color, Color.white, b.fout() / 100f);
Fill.circle(b.x, b.y, orbSize);
Draw.reset();
}
@Override
@@ -69,9 +69,9 @@ public class RailBulletType extends BulletType{
}
@Override
public void hitEntity(Bullet b, Hitboxc entity, float initialHealth){
handle(b, entity, initialHealth);
super.hitEntity(b, entity, initialHealth);
public void hitEntity(Bullet b, Hitboxc entity, float health){
handle(b, entity, health);
super.hitEntity(b, entity, health);
}
@Override
@@ -25,6 +25,8 @@ public class SapBulletType extends BulletType{
hittable = false;
hitEffect = Fx.hitLiquid;
status = StatusEffects.sapped;
lightColor = Pal.sap;
lightOpacity = 0.6f;
statusDuration = 60f * 3f;
impact = true;
}
@@ -40,7 +42,7 @@ public class SapBulletType extends BulletType{
Draw.reset();
Drawf.light(b.team, b.x, b.y, Tmp.v1.x, Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f);
Drawf.light(b.team, b.x, b.y, Tmp.v1.x, Tmp.v1.y, 15f * b.fout(), lightColor, lightOpacity);
}
}
@@ -29,6 +29,7 @@ public class ShrapnelBulletType extends BulletType{
pierce = true;
hittable = false;
absorbable = false;
lightOpacity = 0.6f;
}
@Override
@@ -52,11 +53,11 @@ public class ShrapnelBulletType extends BulletType{
@Override
public void draw(Bullet b){
float realLength = b.fdata;
float realLength = b.fdata, rot = b.rotation();
Draw.color(fromColor, toColor, b.fin());
for(int i = 0; i < (int)(serrations * realLength / length); i++){
Tmp.v1.trns(b.rotation(), i * serrationSpacing);
Tmp.v1.trns(rot, i * serrationSpacing);
float sl = Mathf.clamp(b.fout() - serrationFadeOffset) * (serrationSpaceOffset - i * serrationLenScl);
Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, serrationWidth, sl, b.rotation() + 90);
Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, serrationWidth, sl, b.rotation() - 90);
@@ -64,5 +65,7 @@ public class ShrapnelBulletType extends BulletType{
Drawf.tri(b.x, b.y, width * b.fout(), (realLength + 50), b.rotation());
Drawf.tri(b.x, b.y, width * b.fout(), 10f, b.rotation() + 180f);
Draw.reset();
Drawf.light(b.team, b.x, b.y, b.x + Angles.trnsx(rot, realLength), b.y + Angles.trnsy(rot, realLength), width * 2.5f * b.fout(), toColor, lightOpacity);
}
}