Added dynamic status for custom speed/health/etc

This commit is contained in:
Anuken
2023-10-31 11:24:03 -04:00
parent 968fa2f9b1
commit e5047d752d
6 changed files with 139 additions and 12 deletions

View File

@@ -20,10 +20,12 @@ abstract class StatusComp implements Posc, Flyingc{
private transient Bits applied = new Bits(content.getBy(ContentType.status).size);
//these are considered read-only
transient float speedMultiplier = 1, damageMultiplier = 1, healthMultiplier = 1, reloadMultiplier = 1, buildSpeedMultiplier = 1, dragMultiplier = 1;
//note: armor is a special case; it is an override when >= 0, otherwise ignored
transient float speedMultiplier = 1, damageMultiplier = 1, healthMultiplier = 1, reloadMultiplier = 1, buildSpeedMultiplier = 1, dragMultiplier = 1, armorOverride = -1f;
transient boolean disarmed = false;
@Import UnitType type;
@Import float maxHealth;
/** Apply a status effect for 1 tick (for permanent effects) **/
void apply(StatusEffect effect){
@@ -108,6 +110,62 @@ abstract class StatusComp implements Posc, Flyingc{
return Tmp.c1.set(r / count, g / count, b / count, 1f);
}
/**
* Applies a dynamic status effect, with stat multipliers that can be customized.
* @return the entry to write multipliers to. If the dynamic status was already applied, returns the previous entry.
* */
public StatusEntry applyDynamicStatus(){
if(hasEffect(StatusEffects.dynamic)){
StatusEntry entry = statuses.find(s -> s.effect.dynamic);
if(entry != null) return entry;
}
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
entry.set(StatusEffects.dynamic, Float.POSITIVE_INFINITY);
statuses.add(entry);
entry.effect.applied(self(), entry.time, false);
return entry;
}
/** Uses a dynamic status effect to override speed. */
public void statusSpeed(float speed){
//type.speed should never be 0
applyDynamicStatus().speedMultiplier = speed / type.speed;
}
/** Uses a dynamic status effect to change damage. */
public void statusDamageMultiplier(float damageMultiplier){
applyDynamicStatus().damageMultiplier = damageMultiplier;
}
/** Uses a dynamic status effect to change reload. */
public void statusReloadMultiplier(float reloadMultiplier){
applyDynamicStatus().reloadMultiplier = reloadMultiplier;
}
/** Uses a dynamic status effect to override max health. */
public void statusMaxHealth(float health){
//maxHealth should never be zero
applyDynamicStatus().healthMultiplier = health / maxHealth;
}
/** Uses a dynamic status effect to override build speed. */
public void statusBuildSpeed(float buildSpeed){
//build speed should never be zero
applyDynamicStatus().buildSpeedMultiplier = buildSpeed / type.buildSpeed;
}
/** Uses a dynamic status effect to override drag. */
public void statusDrag(float drag){
//prevent divide by 0 (drag can be zero, if someone makes a broken unit)
applyDynamicStatus().dragMultiplier = type.drag == 0f ? 0f : drag / type.drag;
}
/** Uses a dynamic status effect to override armor. */
public void statusArmor(float armor){
applyDynamicStatus().armorOverride = armor;
}
@Override
public void update(){
Floor floor = floorOn();
@@ -117,6 +175,7 @@ abstract class StatusComp implements Posc, Flyingc{
}
applied.clear();
armorOverride = -1f;
speedMultiplier = damageMultiplier = healthMultiplier = reloadMultiplier = buildSpeedMultiplier = dragMultiplier = 1f;
disarmed = false;
@@ -136,12 +195,24 @@ abstract class StatusComp implements Posc, Flyingc{
}else{
applied.set(entry.effect.id);
speedMultiplier *= entry.effect.speedMultiplier;
healthMultiplier *= entry.effect.healthMultiplier;
damageMultiplier *= entry.effect.damageMultiplier;
reloadMultiplier *= entry.effect.reloadMultiplier;
buildSpeedMultiplier *= entry.effect.buildSpeedMultiplier;
dragMultiplier *= entry.effect.dragMultiplier;
//TODO this is very ugly...
if(entry.effect.dynamic){
speedMultiplier *= entry.speedMultiplier;
healthMultiplier *= entry.healthMultiplier;
damageMultiplier *= entry.damageMultiplier;
reloadMultiplier *= entry.reloadMultiplier;
buildSpeedMultiplier *= entry.buildSpeedMultiplier;
dragMultiplier *= entry.dragMultiplier;
//armor is a special case; many units have it set it to 0, so an override at values >= 0 is used
if(entry.armorOverride >= 0f) armorOverride = entry.armorOverride;
}else{
speedMultiplier *= entry.effect.speedMultiplier;
healthMultiplier *= entry.effect.healthMultiplier;
damageMultiplier *= entry.effect.damageMultiplier;
reloadMultiplier *= entry.effect.reloadMultiplier;
buildSpeedMultiplier *= entry.effect.buildSpeedMultiplier;
dragMultiplier *= entry.effect.dragMultiplier;
}
disarmed |= entry.effect.disarm;