Files
Mindustry/core/src/mindustry/entities/comp/MechComp.java
2025-05-21 23:07:59 -04:00

115 lines
3.4 KiB
Java

package mindustry.entities.comp;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*;
@Component
abstract class MechComp implements Posc, Hitboxc, Unitc, Mechc, ElevationMovec{
@Import float x, y, hitSize;
@Import UnitType type;
@SyncField(false) @SyncLocal float baseRotation;
transient float walkTime, walkExtension;
transient private boolean walked;
@Override
public void update(){
//trigger animation only when walking manually
if(walked || net.client() || isRemote()){
float len = deltaLen();
baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed / Time.delta) * Time.delta);
walkTime += len;
walked = false;
}
//update mech effects
float extend = walkExtend(false);
float base = walkExtend(true);
float extendScl = base % 1f;
float lastExtend = walkExtension;
if(!headless && extendScl < lastExtend && base % 2f > 1f && !isFlying() && !inFogTo(player.team())){
int side = -Mathf.sign(extend);
float width = hitSize / 2f * side, length = type.mechStride * 1.35f;
float cx = x + Angles.trnsx(baseRotation, length, width),
cy = y + Angles.trnsy(baseRotation, length, width);
if(type.stepShake > 0){
Effect.shake(type.stepShake, type.stepShake, cx, cy);
}
if(type.mechStepParticles){
Effect.floorDust(cx, cy, hitSize/8f);
}
}
walkExtension = extendScl;
}
@Replace
@Override
public @Nullable Floor drownFloor(){
//large mechs can only drown when all the nearby floors are deep
if(hitSize >= 12 && canDrown()){
for(Point2 p : Geometry.d8){
Floor f = world.floorWorld(x + p.x * tilesize, y + p.y * tilesize);
if(!f.isDeep()){
return null;
}
}
}
return floorOn();
}
public float walkExtend(boolean scaled){
//now ranges from -maxExtension to maxExtension*3
float raw = walkTime % (type.mechStride * 4);
if(scaled) return raw / type.mechStride;
if(raw > type.mechStride*3) raw = raw - type.mechStride * 4;
else if(raw > type.mechStride*2) raw = type.mechStride * 2 - raw;
else if(raw > type.mechStride) raw = type.mechStride * 2 - raw;
return raw;
}
@Override
@Replace
public void rotateMove(Vec2 vec){
//mechs use baseRotation to rotate, not rotation.
moveAt(Tmp.v2.trns(baseRotation, vec.len()));
if(!vec.isZero()){
baseRotation = Angles.moveToward(baseRotation, vec.angle(), type.rotateSpeed * Math.max(Time.delta, 1));
}
}
@Override
public void moveAt(Vec2 vector, float acceleration){
//mark walking state when moving in a controlled manner
if(!vector.isZero()){
walked = true;
}
}
@Override
public void approach(Vec2 vector){
//mark walking state when moving in a controlled manner
if(!vector.isZero(0.001f)){
walked = true;
}
}
}