mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-10-02 03:00:29 +03:00
Merge branch 'JasonP01-statusChance'
This commit is contained in:
@@ -1238,7 +1238,9 @@ stat.buildspeedmultiplier = Build Speed Multiplier
|
||||
stat.reactive = Reacts
|
||||
stat.immunities = Immunities
|
||||
stat.healing = Healing
|
||||
stat.status = Status Effect
|
||||
stat.efficiency = [stat]{0}% Efficiency
|
||||
stat.chance = [stat]{0}%[lightgray] chance of [white]
|
||||
stat.hitsize = Hitbox Size
|
||||
stat.resettime = Reset Time
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ public class Damage{
|
||||
World.raycastEachNoDiagonalWorld(x, y, seg2.x, seg2.y, (cx, cy) -> {
|
||||
Building tile = world.build(cx, cy);
|
||||
boolean collide = tile != null && tile.collide(hitter) && hitter.checkUnderBuild(tile, cx * tilesize, cy * tilesize)
|
||||
&& ((tile.team != team && tile.collide(hitter)) || hitter.type.testCollision(hitter, tile)) && collidedBlocks.add(tile.pos());
|
||||
&& ((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));
|
||||
|
||||
@@ -468,14 +468,19 @@ public class Damage{
|
||||
damage(team, x, y, radius, damage, false, air, ground);
|
||||
}
|
||||
|
||||
/** Applies a status effect to all enemy units in a range. */
|
||||
public static void status(Team team, float x, float y, float radius, StatusEffect effect, float duration, boolean air, boolean ground){
|
||||
status(team, x, y, radius, effect, duration, air, ground, 1f);
|
||||
}
|
||||
|
||||
public static void status(Team team, float x, float y, float radius, StatusEffect effect, float duration, boolean air, boolean ground, float chance){
|
||||
Cons<Unit> cons = entity -> {
|
||||
if(entity.team == team || !entity.checkTarget(air, ground) || !entity.hittable() || !entity.within(x, y, radius)){
|
||||
return;
|
||||
}
|
||||
|
||||
entity.apply(effect, duration);
|
||||
if(Mathf.chance(chance)){
|
||||
entity.apply(effect, duration);
|
||||
}
|
||||
};
|
||||
|
||||
rect.setSize(radius * 2).setCenter(x, y);
|
||||
@@ -485,7 +490,6 @@ public class Damage{
|
||||
Units.nearby(rect, cons);
|
||||
}
|
||||
}
|
||||
|
||||
/** Damages all entities and blocks in a radius that are enemies of the team. */
|
||||
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete){
|
||||
damage(team, x, y, radius, damage, complete, true, true);
|
||||
@@ -676,4 +680,4 @@ public class Damage{
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,4 +93,4 @@ public class Lightning{
|
||||
|
||||
Fx.lightning.at(x, y, rotation, color, lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,6 +120,10 @@ public class BulletType extends Content implements Cloneable{
|
||||
public StatusEffect status = StatusEffects.none;
|
||||
/** Intensity of applied status effect in terms of duration. */
|
||||
public float statusDuration = 60 * 8f;
|
||||
/** Chance for this bullet to apply a status effect */
|
||||
public float statusChance = 1f;
|
||||
/** Chance for lightning chains to apply a status effect. If -1, uses the parent bullet's statusChance instead. */
|
||||
public float lightningStatusChance = -1f;
|
||||
/** Turret only. If false, blocks will not be targeted. */
|
||||
public boolean targetBlocks = true;
|
||||
/** Turret only. If false, missiles will not be targeted. */
|
||||
@@ -513,7 +517,10 @@ public class BulletType extends Content implements Cloneable{
|
||||
if(impact) Tmp.v3.setAngle(b.rotation() + (knockback < 0 ? 180f : 0f));
|
||||
unit.impulse(Tmp.v3);
|
||||
}
|
||||
unit.apply(status, statusDuration);
|
||||
|
||||
if(Mathf.chance(getStatusChance(b))){
|
||||
unit.apply(status, statusDuration);
|
||||
}
|
||||
|
||||
Events.fire(bulletDamageEvent.set(unit, b));
|
||||
}
|
||||
@@ -600,7 +607,7 @@ public class BulletType extends Content implements Cloneable{
|
||||
Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), splashDamagePierce, collidesAir, collidesGround, scaledSplashDamage, b, armorMultiplier);
|
||||
|
||||
if(status != StatusEffects.none){
|
||||
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround);
|
||||
Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround, getStatusChance(b));
|
||||
}
|
||||
|
||||
if(heals()){
|
||||
@@ -638,6 +645,21 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
}
|
||||
|
||||
// used for lightning bullets only
|
||||
public float getLightningStatusChance(){
|
||||
return lightningStatusChance < 0f ? statusChance : lightningStatusChance;
|
||||
}
|
||||
|
||||
/** Gets the status chance from lightning bullets */
|
||||
public float getStatusChance(Bullet b){
|
||||
if(b.data instanceof Bullet parent &&
|
||||
(parent.type.lightningType == b.type || parent.type.lightningType == null && b.type == Bullets.damageLightning)){
|
||||
return parent.type.getLightningStatusChance();
|
||||
}
|
||||
|
||||
return statusChance;
|
||||
}
|
||||
|
||||
/** Called when the bullet reaches the end of its lifetime or is destroyed by something external. */
|
||||
public void despawned(Bullet b){
|
||||
if(despawnHit){
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.entities.bullet;
|
||||
|
||||
import arc.math.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
@@ -57,7 +58,9 @@ public class EmpBulletType extends BasicBulletType{
|
||||
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);
|
||||
if(Mathf.chance(getStatusChance(b))){
|
||||
other.apply(status, statusDuration);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -260,4 +260,4 @@ abstract class StatusComp implements Posc{
|
||||
public boolean hasEffect(StatusEffect effect){
|
||||
return applied.get(effect.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class StatusEffect extends UnlockableContent{
|
||||
public float intervalDamage;
|
||||
/** If true, interval damage is armor piercing. */
|
||||
public boolean intervalDamagePierce = false;
|
||||
/** Chance of effect appearing. */
|
||||
/** Chance of visual effect(s) appearing. */
|
||||
public float effectChance = 0.15f;
|
||||
/** Should the effect be given a parent. */
|
||||
public boolean parentizeEffect;
|
||||
|
||||
@@ -30,6 +30,7 @@ public class TractorBeamTurret extends BaseTurret{
|
||||
public Color laserColor = Color.white;
|
||||
public StatusEffect status = StatusEffects.none;
|
||||
public float statusDuration = 300;
|
||||
public float statusChance = 1f;
|
||||
|
||||
public Sound shootSound = Sounds.beamParallax;
|
||||
public float shootSoundVolume = 0.9f;
|
||||
@@ -59,6 +60,9 @@ public class TractorBeamTurret extends BaseTurret{
|
||||
stats.add(Stat.targetsAir, targetAir);
|
||||
stats.add(Stat.targetsGround, targetGround);
|
||||
if(damage > 0) stats.add(Stat.damage, damage * 60f, StatUnit.perSecond);
|
||||
if(status != StatusEffects.none && statusChance > 0f){
|
||||
stats.add(Stat.status, StatValues.statusText(status, statusDuration, statusChance));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,7 +129,7 @@ public class TractorBeamTurret extends BaseTurret{
|
||||
target.damageContinuousPierce(damage * eff * timeScale * state.rules.blockDamage(team));
|
||||
}
|
||||
|
||||
if(status != StatusEffects.none){
|
||||
if(status != StatusEffects.none && Mathf.chance(statusChance)){
|
||||
target.apply(status, statusDuration);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ public class Stat implements Comparable<Stat>{
|
||||
targetsAir = new Stat("targetsAir", StatCat.function),
|
||||
targetsGround = new Stat("targetsGround", StatCat.function),
|
||||
damage = new Stat("damage", StatCat.function),
|
||||
status = new Stat("status", StatCat.function),
|
||||
frequency = new Stat("frequency", StatCat.function),
|
||||
ammo = new Stat("ammo", StatCat.function),
|
||||
ammoCapacity = new Stat("ammoCapacity", StatCat.function),
|
||||
|
||||
@@ -225,6 +225,16 @@ public class StatValues{
|
||||
return withTooltip(element, content, false);
|
||||
}
|
||||
|
||||
/** Displays the chance for status effects */
|
||||
public static String statusText(StatusEffect status, float duration, float chance){
|
||||
return (chance < 1f ? Core.bundle.format("stat.chance", Strings.autoFixed(chance * 100f, 4)) : "") +
|
||||
(status.hasEmoji() ? status.emoji() + " " : "") +
|
||||
"[stat]" + status.localizedName +
|
||||
(status.reactive ? "" :
|
||||
"[lightgray] ~ [stat]" + Strings.autoFixed(duration / 60f, 1) +
|
||||
"[lightgray] " + Core.bundle.get("unit.seconds"));
|
||||
}
|
||||
|
||||
/** Displays an item with a specified amount. */
|
||||
private static Stack stack(TextureRegion region, int amount, @Nullable UnlockableContent content, boolean tooltip){
|
||||
Stack stack = new Stack();
|
||||
@@ -713,8 +723,21 @@ public class StatValues{
|
||||
sep(bt, "@bullet.homing");
|
||||
}
|
||||
|
||||
// Showing the correct value for lightning damage is annoyinh
|
||||
if(type.lightning > 0){
|
||||
sep(bt, Core.bundle.format("bullet.lightning", type.lightning, type.lightningDamage < 0 ? type.damage : type.lightningDamage));
|
||||
sep(bt, Core.bundle.format(
|
||||
"bullet.lightning",
|
||||
type.lightning,
|
||||
type.lightningDamage < 0 ? type.damage : type.lightningDamage
|
||||
));
|
||||
|
||||
BulletType lightningType = type.lightningType == null ? Bullets.damageLightning : type.lightningType;
|
||||
float chance = type.getLightningStatusChance();
|
||||
|
||||
if(lightningType.status != StatusEffects.none && chance > 0f){
|
||||
sep(bt, statusText(lightningType.status, lightningType.statusDuration, chance))
|
||||
.with(c -> withTooltip(c, lightningType.status));
|
||||
}
|
||||
}
|
||||
|
||||
if(type instanceof LaserBulletType b && b.lightningSpacing > 0){
|
||||
@@ -778,9 +801,10 @@ public class StatValues{
|
||||
sep(bt, Core.bundle.format("bullet.suppression", Strings.autoFixed(type.suppressionDuration / 60f, 2), Strings.fixed(type.suppressionRange / tilesize, 1)));
|
||||
}
|
||||
|
||||
if(type.status != StatusEffects.none){
|
||||
sep(bt, (type.status.hasEmoji() ? type.status.emoji() : "") + "[stat]" + type.status.localizedName + (type.status.reactive ? "" : "[lightgray] ~ [stat]" +
|
||||
Strings.autoFixed(type.statusDuration / 60f, 1) + "[lightgray] " + Core.bundle.get("unit.seconds"))).with(c -> withTooltip(c, type.status));
|
||||
// It is redundant to show the status effect if it can't be applied
|
||||
if(type.status != StatusEffects.none && type.statusChance > 0f){
|
||||
sep(bt, statusText(type.status, type.statusDuration, type.statusChance))
|
||||
.with(c -> withTooltip(c, type.status));
|
||||
}
|
||||
|
||||
if(!type.targetMissiles){
|
||||
|
||||
Reference in New Issue
Block a user