Drownable legged units

This commit is contained in:
Anuken
2021-08-22 11:06:25 -04:00
parent 1d46fb5425
commit 4af101bf7d
8 changed files with 77 additions and 29 deletions

View File

@@ -49,6 +49,7 @@ public class Pathfinder implements Runnable{
//legs
(team, tile) -> PathTile.legSolid(tile) ? impassable : 1 +
(PathTile.deep(tile) ? 6000 : 0) + //leg units can now drown
(PathTile.solid(tile) ? 5 : 0),
//water

View File

@@ -1835,7 +1835,7 @@ public class Fx{
bubble = new Effect(20, e -> {
color(Tmp.c1.set(e.color).shiftValue(0.1f));
stroke(e.fout() + 0.2f);
randLenVectors(e.id, 2, 8f, (x, y) -> {
randLenVectors(e.id, 2, e.rotation * 0.9f, (x, y) -> {
Lines.circle(e.x + x, e.y + y, 1f + e.fin() * 3f);
});
}),

View File

@@ -503,7 +503,6 @@ public class UnitTypes implements ContentList{
legTrns = 0.58f;
hovering = true;
visualElevation = 0.2f;
allowLegStep = true;
ammoType = new PowerAmmoType(4000);
groundLayer = Layer.legUnit;
@@ -593,7 +592,7 @@ public class UnitTypes implements ContentList{
}};
atrax = new UnitType("atrax"){{
speed = 0.54f;
speed = 0.56f;
drag = 0.4f;
hitSize = 13f;
rotateSpeed = 3f;
@@ -609,7 +608,6 @@ public class UnitTypes implements ContentList{
armor = 3f;
ammoType = new ItemAmmoType(Items.coal);
allowLegStep = true;
visualElevation = 0.2f;
groundLayer = Layer.legUnit - 1f;
@@ -623,8 +621,8 @@ public class UnitTypes implements ContentList{
shootSound = Sounds.flame;
bullet = new LiquidBulletType(Liquids.slag){{
damage = 11;
speed = 2.4f;
damage = 13;
speed = 2.5f;
drag = 0.009f;
shootEffect = Fx.shootSmall;
lifetime = 57f;
@@ -634,11 +632,11 @@ public class UnitTypes implements ContentList{
}};
spiroct = new UnitType("spiroct"){{
speed = 0.48f;
speed = 0.5f;
drag = 0.4f;
hitSize = 15f;
rotateSpeed = 3f;
health = 910;
health = 940;
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
legCount = 6;
legLength = 13f;
@@ -651,7 +649,6 @@ public class UnitTypes implements ContentList{
buildSpeed = 0.75f;
allowLegStep = true;
visualElevation = 0.3f;
groundLayer = Layer.legUnit;
@@ -669,7 +666,7 @@ public class UnitTypes implements ContentList{
bullet = new SapBulletType(){{
sapStrength = 0.5f;
length = 75f;
damage = 20;
damage = 23;
shootEffect = Fx.shootSmall;
hitColor = color = Color.valueOf("bf92f9");
despawnEffect = Fx.none;
@@ -689,7 +686,7 @@ public class UnitTypes implements ContentList{
bullet = new SapBulletType(){{
sapStrength = 0.8f;
length = 40f;
damage = 16;
damage = 18;
shootEffect = Fx.shootSmall;
hitColor = color = Color.valueOf("bf92f9");
despawnEffect = Fx.none;
@@ -724,16 +721,16 @@ public class UnitTypes implements ContentList{
legSplashDamage = 32;
legSplashRange = 30;
drownTimeMultiplier = 2f;
hovering = true;
allowLegStep = true;
visualElevation = 0.65f;
groundLayer = Layer.legUnit;
BulletType sapper = new SapBulletType(){{
sapStrength = 0.85f;
length = 55f;
damage = 37;
damage = 40;
shootEffect = Fx.shootSmall;
hitColor = color = Color.valueOf("bf92f9");
despawnEffect = Fx.none;
@@ -811,6 +808,7 @@ public class UnitTypes implements ContentList{
lightRadius = 140f;
rotateSpeed = 1.9f;
drownTimeMultiplier = 3f;
legCount = 8;
legMoveSpace = 0.8f;
@@ -829,7 +827,6 @@ public class UnitTypes implements ContentList{
legSplashRange = 60;
hovering = true;
allowLegStep = true;
visualElevation = 0.95f;
groundLayer = Layer.legUnit;

View File

@@ -129,7 +129,7 @@ public class Units{
nearby(x, y, width, height, unit -> {
if(boolResult) return;
if((unit.isGrounded() && !unit.type.hovering) == ground){
if((unit.isGrounded() && !unit.hovering) == ground){
unit.hitboxTile(hitrect);
if(hitrect.overlaps(x, y, width, height)){

View File

@@ -25,6 +25,7 @@ abstract class CrawlComp implements Posc, Rotc, Hitboxc, Unitc{
@Import Team team;
@Import Vec2 vel;
transient Floor lastDeepFloor;
//TODO segments
transient float lastCrawlSlowdown = 1f;
transient float segmentRot, crawlTime;
@@ -55,13 +56,20 @@ abstract class CrawlComp implements Posc, Rotc, Hitboxc, Unitc{
segmentRot = rotation;
}
@Override
@Replace
public Floor drownFloor(){
return lastDeepFloor;
}
@Override
public void update(){
if(moving()){
segmentRot = Angles.moveToward(segmentRot, rotation, type.segmentRotSpeed);
int radius = (int)Math.max(0, hitSize / tilesize);
int count = 0, solids = 0;
int count = 0, solids = 0, deeps = 0;
lastDeepFloor = null;
//calculate tiles under this unit, and apply slowdown + particle effects
for(int cx = -radius; cx <= radius; cx++){
@@ -75,6 +83,11 @@ abstract class CrawlComp implements Posc, Rotc, Hitboxc, Unitc{
solids ++;
}
if(t.floor().isDeep()){
deeps ++;
lastDeepFloor = t.floor();
}
if(t.build != null && t.build.team != team){
t.build.damage(team, type.crawlDamage * Time.delta);
}
@@ -89,6 +102,11 @@ abstract class CrawlComp implements Posc, Rotc, Hitboxc, Unitc{
}
}
//when most blocks under this unit cannot be drowned in, do not drown
if((float)deeps / count < 0.75f){
lastDeepFloor = null;
}
lastCrawlSlowdown = Mathf.lerp(1f, type.crawlSlowdown, Mathf.clamp((float)solids / count / type.crawlSlowdownFrac));
}
segmentRot = Angles.clampRange(segmentRot, rotation, type.segmentMaxRot);

View File

@@ -17,7 +17,7 @@ import static mindustry.Vars.*;
abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
private static final Vec2 tmp1 = new Vec2(), tmp2 = new Vec2();
@Import float x, y, speedMultiplier;
@Import float x, y, speedMultiplier, hitSize;
@Import Vec2 vel;
@Import UnitType type;
@@ -47,7 +47,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
//TODO
@Nullable
Floor drownFloor(){
return null;
return canDrown() ? floorOn() : null;
}
void landed(){
@@ -95,13 +95,17 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
}
}
//TODO separate method?
//TODO drown eligibility, store drown color.
if(canDrown() && floor.isLiquid && floor.drownTime > 0){
updateDrowning();
}
public void updateDrowning(){
Floor floor = drownFloor();
if(floor != null && floor.isLiquid && floor.drownTime > 0){
lastDrownFloor = floor;
drownTime += Time.delta / floor.drownTime / type.drownTimeMultiplier;
if(Mathf.chanceDelta(0.05f)){
floor.drownUpdateEffect.at(x, y, 1f, floor.mapColor);
floor.drownUpdateEffect.at(x, y, hitSize, floor.mapColor);
}
if(drownTime >= 0.999f && !net.client()){

View File

@@ -9,6 +9,7 @@ import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.entities.EntityCollisions.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
@@ -18,22 +19,30 @@ import mindustry.world.blocks.environment.*;
abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
@Import float x, y;
@Import UnitType type;
@Import Team team;
transient Leg[] legs = {};
transient float totalLength;
transient float moveSpace;
transient float baseRotation;
transient Floor lastDeepFloor;
@Replace
@Override
public SolidPred solidity(){
return !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid;
return type.allowLegStep ? EntityCollisions::legsSolid : EntityCollisions::solid;
}
@Override
@Replace
public int pathType(){
return Pathfinder.costLegs;
return type.allowLegStep ? Pathfinder.costGround : Pathfinder.costLegs;
}
@Override
@Replace
public Floor drownFloor(){
return lastDeepFloor;
}
@Override
@@ -85,6 +94,9 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
Vec2 moveOffset = Tmp.v4.trns(rot, trns);
boolean moving = moving();
lastDeepFloor = null;
int deeps = 0;
for(int i = 0; i < legs.length; i++){
float dstRot = legAngle(rot, i);
Vec2 baseOffset = Tmp.v5.trns(dstRot, type.legBaseOffset).add(x, y);
@@ -105,11 +117,16 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
l.moving = move;
l.stage = moving ? stageF % 1f : Mathf.lerpDelta(l.stage, 0f, 0.1f);
Floor floor = Vars.world.floorWorld(l.base.x, l.base.y);
if(floor.isDeep()){
deeps ++;
lastDeepFloor = floor;
}
if(l.group != group){
//create effect when transitioning to a group it can't move in
if(!move && i % div == l.group){
Floor floor = Vars.world.floorWorld(l.base.x, l.base.y);
if(floor.isLiquid){
floor.walkEffect.at(l.base.x, l.base.y, type.rippleScale, floor.mapColor);
floor.walkSound.at(x, y, 1f, floor.walkSoundVolume);
@@ -123,7 +140,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
}
if(type.legSplashDamage > 0){
Damage.damage(team(), l.base.x, l.base.y, type.legSplashRange, type.legSplashDamage, false, true);
Damage.damage(team, l.base.x, l.base.y, type.legSplashRange, type.legSplashDamage, false, true);
}
}
@@ -148,6 +165,11 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{
l.joint.lerpDelta(jointDest, moveSpeed / 4f);
}
//when at least 1 leg is touching land, it can't drown
if(deeps != legs.length){
lastDeepFloor = null;
}
}
/** @return outwards facing angle of leg at the specified index. */

View File

@@ -71,7 +71,9 @@ public class UnitType extends UnlockableContent{
public int commandLimit = 8;
public float commandRadius = 150f;
public float visualElevation = -1f;
public boolean allowLegStep = false;
/** If true and this is a legged unit, this unit can walk over blocks. */
public boolean allowLegStep = true;
/** If true, this unit cannot drown, and will not be affected by the floor under it. */
public boolean hovering = false;
public boolean omniMovement = true;
public Effect fallEffect = Fx.fallSmoke;
@@ -840,14 +842,16 @@ public class UnitType extends UnlockableContent{
public <T extends Unit & Legsc> void drawLegs(T unit){
applyColor(unit);
Tmp.c3.set(Draw.getMixColor());
Leg[] legs = unit.legs();
float ssize = footRegion.width * Draw.scl * 1.5f;
float rotation = unit.baseRotation();
float invDrown = 1f - unit.drownTime;
for(Leg leg : legs){
Drawf.shadow(leg.base.x, leg.base.y, ssize);
Drawf.shadow(leg.base.x, leg.base.y, ssize, invDrown);
}
//legs are drawn front first
@@ -863,13 +867,15 @@ public class UnitType extends UnlockableContent{
Tmp.v1.set(leg.base).sub(leg.joint).inv().setLength(legExtension);
if(leg.moving && visualElevation > 0){
float scl = visualElevation;
float scl = visualElevation * invDrown;
float elev = Mathf.slope(1f - leg.stage) * scl;
Draw.color(Pal.shadow);
Draw.rect(footRegion, leg.base.x + shadowTX * elev, leg.base.y + shadowTY * elev, position.angleTo(leg.base));
Draw.color();
}
Draw.mixcol(Tmp.c3, Tmp.c3.a);
Draw.rect(footRegion, leg.base.x, leg.base.y, position.angleTo(leg.base));
Lines.stroke(legRegion.height * Draw.scl * flips);