116 lines
3.5 KiB
Java
116 lines
3.5 KiB
Java
package mindustry.entities.comp;
|
|
|
|
import arc.math.*;
|
|
import arc.math.geom.*;
|
|
import arc.util.*;
|
|
import mindustry.*;
|
|
import mindustry.ai.*;
|
|
import mindustry.annotations.Annotations.*;
|
|
import mindustry.content.*;
|
|
import mindustry.entities.*;
|
|
import mindustry.entities.EntityCollisions.*;
|
|
import mindustry.game.*;
|
|
import mindustry.gen.*;
|
|
import mindustry.type.*;
|
|
import mindustry.world.*;
|
|
import mindustry.world.blocks.environment.*;
|
|
|
|
import static mindustry.Vars.*;
|
|
|
|
@Component
|
|
abstract class CrawlComp implements Posc, Rotc, Hitboxc, Unitc{
|
|
@Import float x, y, speedMultiplier, rotation, hitSize;
|
|
@Import UnitType type;
|
|
@Import Team team;
|
|
@Import Vec2 vel;
|
|
|
|
transient Floor lastDeepFloor;
|
|
transient float lastCrawlSlowdown = 1f;
|
|
transient float segmentRot, crawlTime = Mathf.random(100f);
|
|
|
|
@Replace
|
|
@Override
|
|
public SolidPred solidity(){
|
|
return EntityCollisions::legsSolid;
|
|
}
|
|
|
|
@Override
|
|
@Replace
|
|
public int pathType(){
|
|
return Pathfinder.costLegs;
|
|
}
|
|
|
|
@Override
|
|
@Replace
|
|
public float floorSpeedMultiplier(){
|
|
Floor on = isFlying() ? Blocks.air.asFloor() : floorOn();
|
|
//TODO take into account extra blocks
|
|
return (on.isDeep() ? 0.45f : on.speedMultiplier) * speedMultiplier * lastCrawlSlowdown;
|
|
}
|
|
|
|
@Override
|
|
public void add(){
|
|
//reset segment rotation on add
|
|
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 * 2f);
|
|
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++){
|
|
for(int cy = -radius; cy <= radius; cy++){
|
|
if(cx*cx + cy*cy <= radius){
|
|
count ++;
|
|
Tile t = Vars.world.tileWorld(x + cx*tilesize, y + cy*tilesize);
|
|
if(t != null){
|
|
|
|
if(t.solid()){
|
|
solids ++;
|
|
}
|
|
|
|
if(t.floor().isDeep()){
|
|
deeps ++;
|
|
lastDeepFloor = t.floor();
|
|
}
|
|
|
|
//TODO area damage to units
|
|
if(t.build != null && t.build.team != team){
|
|
t.build.damage(team, type.crushDamage * Time.delta * state.rules.unitDamage(team));
|
|
}
|
|
|
|
if(Mathf.chanceDelta(0.025)){
|
|
Fx.crawlDust.at(t.worldx(), t.worldy(), t.floor().mapColor);
|
|
}
|
|
}else{
|
|
solids ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//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);
|
|
|
|
crawlTime += vel.len();
|
|
}
|
|
}
|