Cleanup
This commit is contained in:
@@ -5,6 +5,24 @@ import java.lang.annotation.*;
|
|||||||
public class Annotations{
|
public class Annotations{
|
||||||
//region entity interfaces
|
//region entity interfaces
|
||||||
|
|
||||||
|
/** Indicates that a component field is read-only. */
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Render{
|
||||||
|
RenderLayer value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RenderLayer{
|
||||||
|
floor,
|
||||||
|
groundShadows,
|
||||||
|
ground,
|
||||||
|
flyingShadows,
|
||||||
|
flying,
|
||||||
|
bullets,
|
||||||
|
effects,
|
||||||
|
names,
|
||||||
|
}
|
||||||
|
|
||||||
/** Indicates that a component field is read-only. */
|
/** Indicates that a component field is read-only. */
|
||||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mindustry.annotations;
|
|||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.struct.Array;
|
import arc.struct.Array;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import arc.util.Log.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import com.sun.source.util.*;
|
import com.sun.source.util.*;
|
||||||
import mindustry.annotations.util.*;
|
import mindustry.annotations.util.*;
|
||||||
@@ -151,6 +152,10 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
elementu = env.getElementUtils();
|
elementu = env.getElementUtils();
|
||||||
filer = env.getFiler();
|
filer = env.getFiler();
|
||||||
messager = env.getMessager();
|
messager = env.getMessager();
|
||||||
|
|
||||||
|
if(System.getProperty("debug") == null){
|
||||||
|
Log.setLogLevel(LogLevel.err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -159,7 +164,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
if(rootDirectory == null){
|
if(rootDirectory == null){
|
||||||
try{
|
try{
|
||||||
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
||||||
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
|
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
|
||||||
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
|
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
|
||||||
rootDirectory = Fi.get(path);
|
rootDirectory = Fi.get(path);
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import java.lang.annotation.*;
|
|||||||
|
|
||||||
@SupportedAnnotationTypes({
|
@SupportedAnnotationTypes({
|
||||||
"mindustry.annotations.Annotations.EntityDef",
|
"mindustry.annotations.Annotations.EntityDef",
|
||||||
|
"mindustry.annotations.Annotations.GroupDef",
|
||||||
"mindustry.annotations.Annotations.EntityInterface",
|
"mindustry.annotations.Annotations.EntityInterface",
|
||||||
"mindustry.annotations.Annotations.BaseComponent"
|
"mindustry.annotations.Annotations.BaseComponent"
|
||||||
})
|
})
|
||||||
@@ -64,7 +65,8 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
|
|
||||||
//create component interfaces
|
//create component interfaces
|
||||||
for(Stype component : allComponents){
|
for(Stype component : allComponents){
|
||||||
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component)).addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component))
|
||||||
|
.addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
||||||
|
|
||||||
//implement extra interfaces these components may have, e.g. position
|
//implement extra interfaces these components may have, e.g. position
|
||||||
for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){
|
for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#Maps entity names to IDs. Autogenerated.
|
#Maps entity names to IDs. Autogenerated.
|
||||||
|
|
||||||
mindustry.entities.def.EntityDefs.DecalDef=1
|
mindustry.entities.def.AllEntities.GenericBuilderDef=6
|
||||||
mindustry.entities.def.EntityDefs.EffectDef=2
|
mindustry.entities.def.AllEntities.BulletDef=0
|
||||||
mindustry.entities.def.EntityDefs.TileDef=3
|
mindustry.entities.def.AllEntities.PlayerDef=4
|
||||||
mindustry.entities.def.EntityDefs.GenericUnitDef=5
|
mindustry.entities.def.AllEntities.GenericUnitDef=5
|
||||||
mindustry.entities.def.EntityDefs.GenericBuilderDef=6
|
mindustry.entities.def.AllEntities.EffectDef=2
|
||||||
mindustry.entities.def.EntityDefs.BulletDef=0
|
mindustry.entities.def.AllEntities.DecalDef=1
|
||||||
mindustry.entities.def.EntityDefs.PlayerDef=4
|
mindustry.entities.def.AllEntities.TileDef=3
|
||||||
@@ -240,6 +240,7 @@ public class Renderer implements ApplicationListener{
|
|||||||
|
|
||||||
overlays.drawTop();
|
overlays.drawTop();
|
||||||
|
|
||||||
|
render(RenderLayer.names);
|
||||||
//TODO should use (draw)
|
//TODO should use (draw)
|
||||||
Groups.player.each(p -> !p.dead(), Playerc::drawName);
|
Groups.player.each(p -> !p.dead(), Playerc::drawName);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package mindustry.entities;
|
package mindustry.entities;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
@@ -7,13 +8,14 @@ import mindustry.gen.*;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.collisions;
|
||||||
|
|
||||||
/** Represents a group of a certain type of entity.*/
|
/** Represents a group of a certain type of entity.*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class EntityGroup<T extends Entityc> implements Iterable<T>{
|
public class EntityGroup<T extends Entityc> implements Iterable<T>{
|
||||||
private final Array<T> array;
|
private final Array<T> array;
|
||||||
private final Array<T> intersectArray = new Array<>();
|
private final Array<T> intersectArray = new Array<>();
|
||||||
|
private final Rect viewport = new Rect();
|
||||||
private final Rect intersectRect = new Rect();
|
private final Rect intersectRect = new Rect();
|
||||||
private IntMap<T> map;
|
private IntMap<T> map;
|
||||||
private QuadTree tree;
|
private QuadTree tree;
|
||||||
@@ -60,6 +62,17 @@ public class EntityGroup<T extends Entityc> implements Iterable<T>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void draw(Cons<T> cons){
|
||||||
|
Core.camera.bounds(viewport);
|
||||||
|
|
||||||
|
each(e -> {
|
||||||
|
Drawc draw = (Drawc)e;
|
||||||
|
if(viewport.overlaps(draw.x() - draw.clipSize()/2f, draw.y() - draw.clipSize()/2f, draw.clipSize(), draw.clipSize())){
|
||||||
|
cons.get(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public boolean useTree(){
|
public boolean useTree(){
|
||||||
return map != null;
|
return map != null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package mindustry.entities.def;
|
package mindustry.entities.def;
|
||||||
|
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.entities.def.EntityComps.*;
|
|
||||||
|
|
||||||
class EntityDefs{
|
class AllEntities{
|
||||||
|
|
||||||
@EntityDef({BulletComp.class, VelComp.class, TimedComp.class})
|
@EntityDef({BulletComp.class, VelComp.class, TimedComp.class})
|
||||||
class BulletDef{}
|
class BulletDef{}
|
||||||
@@ -25,4 +24,34 @@ class EntityDefs{
|
|||||||
|
|
||||||
@EntityDef({BuilderComp.class})
|
@EntityDef({BuilderComp.class})
|
||||||
class GenericBuilderDef{}
|
class GenericBuilderDef{}
|
||||||
|
|
||||||
|
@GroupDef(EntityComp.class)
|
||||||
|
void all(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GroupDef(PlayerComp.class)
|
||||||
|
void player(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GroupDef(value = UnitComp.class, spatial = true)
|
||||||
|
void unit(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GroupDef(TileComp.class)
|
||||||
|
void tile(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GroupDef(DrawComp.class)
|
||||||
|
void drawer(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GroupDef(SyncComp.class)
|
||||||
|
void sync(){
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
36
core/src/mindustry/entities/def/BoundedComp.java
Normal file
36
core/src/mindustry/entities/def/BoundedComp.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
|
||||||
|
static final float warpDst = 180f;
|
||||||
|
|
||||||
|
transient float x, y;
|
||||||
|
transient Vec2 vel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
//repel unit out of bounds
|
||||||
|
if(x < 0) vel.x += (-x/warpDst);
|
||||||
|
if(y < 0) vel.y += (-y/warpDst);
|
||||||
|
if(x > world.unitWidth()) vel.x -= (x - world.unitWidth())/warpDst;
|
||||||
|
if(y > world.unitHeight()) vel.y -= (y - world.unitHeight())/warpDst;
|
||||||
|
|
||||||
|
//clamp position if not flying
|
||||||
|
if(isGrounded()){
|
||||||
|
x = Mathf.clamp(x, 0, world.width() * tilesize - tilesize);
|
||||||
|
y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//kill when out of bounds
|
||||||
|
if(x < -finalWorldBounds || y < -finalWorldBounds || x >= world.width() * tilesize + finalWorldBounds || y >= world.height() * tilesize + finalWorldBounds){
|
||||||
|
kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
229
core/src/mindustry/entities/def/BuilderComp.java
Normal file
229
core/src/mindustry/entities/def/BuilderComp.java
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.struct.Queue;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
|
import mindustry.world.blocks.BuildBlock.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class BuilderComp implements Unitc{
|
||||||
|
static final Vec2[] tmptr = new Vec2[]{new Vec2(), new Vec2(), new Vec2(), new Vec2()};
|
||||||
|
|
||||||
|
transient float x, y, rotation;
|
||||||
|
|
||||||
|
Queue<BuildRequest> requests = new Queue<>();
|
||||||
|
float buildSpeed = 1f;
|
||||||
|
//boolean building;
|
||||||
|
|
||||||
|
void updateBuilding(){
|
||||||
|
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
|
||||||
|
|
||||||
|
Iterator<BuildRequest> it = requests.iterator();
|
||||||
|
while(it.hasNext()){
|
||||||
|
BuildRequest req = it.next();
|
||||||
|
Tile tile = world.tile(req.x, req.y);
|
||||||
|
if(tile == null || (req.breaking && tile.block() == Blocks.air) || (!req.breaking && (tile.rotation() == req.rotation || !req.block.rotate) && tile.block() == req.block)){
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tilec core = closestCore();
|
||||||
|
|
||||||
|
//nothing to build.
|
||||||
|
if(buildRequest() == null) return;
|
||||||
|
|
||||||
|
//find the next build request
|
||||||
|
if(requests.size > 1){
|
||||||
|
int total = 0;
|
||||||
|
BuildRequest req;
|
||||||
|
while((dst((req = buildRequest()).tile()) > finalPlaceDst || shouldSkip(req, core)) && total < requests.size){
|
||||||
|
requests.removeFirst();
|
||||||
|
requests.addLast(req);
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildRequest current = buildRequest();
|
||||||
|
|
||||||
|
if(dst(current.tile()) > finalPlaceDst) return;
|
||||||
|
|
||||||
|
Tile tile = world.tile(current.x, current.y);
|
||||||
|
|
||||||
|
if(!(tile.block() instanceof BuildBlock)){
|
||||||
|
if(!current.initialized && !current.breaking && Build.validPlace(team(), current.x, current.y, current.block, current.rotation)){
|
||||||
|
Build.beginPlace(team(), current.x, current.y, current.block, current.rotation);
|
||||||
|
}else if(!current.initialized && current.breaking && Build.validBreak(team(), current.x, current.y)){
|
||||||
|
Build.beginBreak(team(), current.x, current.y);
|
||||||
|
}else{
|
||||||
|
requests.removeFirst();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tile.entity instanceof BuildEntity && !current.initialized){
|
||||||
|
Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, team(), (Builderc)this, current.breaking)));
|
||||||
|
current.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if there is no core to build with or no build entity, stop building!
|
||||||
|
if((core == null && !state.rules.infiniteResources) || !(tile.entity instanceof BuildEntity)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise, update it.
|
||||||
|
BuildEntity entity = tile.ent();
|
||||||
|
|
||||||
|
if(entity == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dst(tile) <= finalPlaceDst){
|
||||||
|
rotation = Mathf.slerpDelta(rotation, angleTo(entity), 0.4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current.breaking){
|
||||||
|
entity.deconstruct(this, core, 1f / entity.buildCost * Time.delta() * buildSpeed * state.rules.buildSpeedMultiplier);
|
||||||
|
}else{
|
||||||
|
if(entity.construct(this, core, 1f / entity.buildCost * Time.delta() * buildSpeed * state.rules.buildSpeedMultiplier, current.hasConfig)){
|
||||||
|
if(current.hasConfig){
|
||||||
|
Call.onTileConfig(null, tile, current.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current.stuck = Mathf.equal(current.progress, entity.progress);
|
||||||
|
current.progress = entity.progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
||||||
|
void drawBuildRequests(){
|
||||||
|
|
||||||
|
for(BuildRequest request : requests){
|
||||||
|
if(request.progress > 0.01f || (buildRequest() == request && request.initialized && (dst(request.x * tilesize, request.y * tilesize) <= buildingRange || state.isEditor()))) continue;
|
||||||
|
|
||||||
|
request.animScale = 1f;
|
||||||
|
if(request.breaking){
|
||||||
|
control.input.drawBreaking(request);
|
||||||
|
}else{
|
||||||
|
request.block.drawRequest(request, control.input.allRequests(),
|
||||||
|
Build.validPlace(team(), request.x, request.y, request.block, request.rotation) || control.input.requestMatches(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return whether this request should be skipped, in favor of the next one. */
|
||||||
|
boolean shouldSkip(BuildRequest request, @Nullable Tilec core){
|
||||||
|
//requests that you have at least *started* are considered
|
||||||
|
if(state.rules.infiniteResources || request.breaking || !request.initialized || core == null) return false;
|
||||||
|
return request.stuck && !core.items().has(request.block.requirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeBuild(int x, int y, boolean breaking){
|
||||||
|
//remove matching request
|
||||||
|
int idx = requests.indexOf(req -> req.breaking == breaking && req.x == x && req.y == y);
|
||||||
|
if(idx != -1){
|
||||||
|
requests.removeIndex(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return whether this builder's place queue contains items. */
|
||||||
|
boolean isBuilding(){
|
||||||
|
return requests.size != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clears the placement queue. */
|
||||||
|
void clearBuilding(){
|
||||||
|
requests.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
||||||
|
void addBuild(BuildRequest place){
|
||||||
|
addBuild(place, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add another build requests to the queue, if it doesn't exist there yet. */
|
||||||
|
void addBuild(BuildRequest place, boolean tail){
|
||||||
|
BuildRequest replace = null;
|
||||||
|
for(BuildRequest request : requests){
|
||||||
|
if(request.x == place.x && request.y == place.y){
|
||||||
|
replace = request;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(replace != null){
|
||||||
|
requests.remove(replace);
|
||||||
|
}
|
||||||
|
Tile tile = world.tile(place.x, place.y);
|
||||||
|
if(tile != null && tile.entity instanceof BuildEntity){
|
||||||
|
place.progress = tile.<BuildEntity>ent().progress;
|
||||||
|
}
|
||||||
|
if(tail){
|
||||||
|
requests.addLast(place);
|
||||||
|
}else{
|
||||||
|
requests.addFirst(place);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the build requests currently active, or the one at the top of the queue.*/
|
||||||
|
@Nullable BuildRequest buildRequest(){
|
||||||
|
return requests.size == 0 ? null : requests.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawOver(){
|
||||||
|
if(!isBuilding()) return;
|
||||||
|
BuildRequest request = buildRequest();
|
||||||
|
Tile tile = world.tile(request.x, request.y);
|
||||||
|
|
||||||
|
if(dst(tile) > buildingRange && !state.isEditor()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lines.stroke(1f, Pal.accent);
|
||||||
|
float focusLen = 3.8f + Mathf.absin(Time.time(), 1.1f, 0.6f);
|
||||||
|
float px = x + Angles.trnsx(rotation, focusLen);
|
||||||
|
float py = y + Angles.trnsy(rotation, focusLen);
|
||||||
|
|
||||||
|
float sz = Vars.tilesize * tile.block().size / 2f;
|
||||||
|
float ang = angleTo(tile);
|
||||||
|
|
||||||
|
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
|
||||||
|
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
|
||||||
|
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
|
||||||
|
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
|
||||||
|
|
||||||
|
Arrays.sort(tmptr, Structs.comparingFloat(vec -> Angles.angleDist(angleTo(vec), ang)));
|
||||||
|
|
||||||
|
float x1 = tmptr[0].x, y1 = tmptr[0].y,
|
||||||
|
x3 = tmptr[1].x, y3 = tmptr[1].y;
|
||||||
|
|
||||||
|
Draw.alpha(1f);
|
||||||
|
|
||||||
|
Lines.line(px, py, x1, y1);
|
||||||
|
Lines.line(px, py, x3, y3);
|
||||||
|
|
||||||
|
Fill.circle(px, py, 1.6f + Mathf.absin(Time.time(), 0.8f, 1.5f));
|
||||||
|
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
}
|
||||||
121
core/src/mindustry/entities/def/BulletComp.java
Normal file
121
core/src/mindustry/entities/def/BulletComp.java
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.entities.bullet.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Drawc, Shielderc, Ownerc, Velc, Bulletc, Timerc{
|
||||||
|
private float lifeScl;
|
||||||
|
|
||||||
|
Object data;
|
||||||
|
BulletType type;
|
||||||
|
float damage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(){
|
||||||
|
type.init(this);
|
||||||
|
|
||||||
|
drag(type.drag);
|
||||||
|
hitSize(type.hitSize);
|
||||||
|
lifetime(lifeScl * type.lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(){
|
||||||
|
type.despawned(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getLifetime(){
|
||||||
|
return type.lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float damageMultiplier(){
|
||||||
|
if(owner() instanceof Unitc){
|
||||||
|
return ((Unitc)owner()).damageMultiplier();
|
||||||
|
}
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void absorb(){
|
||||||
|
//TODO
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float clipSize(){
|
||||||
|
return type.drawSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float damage(){
|
||||||
|
return type.damage * damageMultiplier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collision(Hitboxc other, float x, float y){
|
||||||
|
if(!type.pierce) remove();
|
||||||
|
type.hit(this, x, y);
|
||||||
|
|
||||||
|
if(other instanceof Unitc){
|
||||||
|
Unitc unit = (Unitc)other;
|
||||||
|
unit.vel().add(Tmp.v3.set(other.x(), other.y()).sub(x, y).setLength(type.knockback / unit.mass()));
|
||||||
|
unit.apply(type.status, type.statusDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
type.update(this);
|
||||||
|
|
||||||
|
if(type.hitTiles){
|
||||||
|
world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
|
||||||
|
|
||||||
|
Tile tile = world.ltile(x, y);
|
||||||
|
if(tile == null) return false;
|
||||||
|
|
||||||
|
if(tile.entity != null && tile.entity.collide(this) && type.collides(this, tile) && !tile.entity.dead() && (type.collidesTeam || tile.team() != team())){
|
||||||
|
if(tile.team() != team()){
|
||||||
|
tile.entity.collision(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
type.hitTile(this, tile);
|
||||||
|
remove();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
type.draw(this);
|
||||||
|
//TODO refactor
|
||||||
|
renderer.lights.add(x(), y(), 16f, Pal.powerLight, 0.3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the bullet's rotation in degrees. */
|
||||||
|
@Override
|
||||||
|
public void rotation(float angle){
|
||||||
|
vel().setAngle(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the bullet's rotation. */
|
||||||
|
@Override
|
||||||
|
public float rotation(){
|
||||||
|
float angle = Mathf.atan2(vel().x, vel().y) * Mathf.radiansToDegrees;
|
||||||
|
if(angle < 0) angle += 360;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
core/src/mindustry/entities/def/ChildComp.java
Normal file
29
core/src/mindustry/entities/def/ChildComp.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class ChildComp implements Posc{
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
private @Nullable Posc parent;
|
||||||
|
private float offsetX, offsetY;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(){
|
||||||
|
if(parent != null){
|
||||||
|
offsetX = x - parent.getX();
|
||||||
|
offsetY = y - parent.getY();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
if(parent != null){
|
||||||
|
x = parent.getX() + offsetX;
|
||||||
|
y = parent.getY() + offsetY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
core/src/mindustry/entities/def/DamageComp.java
Normal file
8
core/src/mindustry/entities/def/DamageComp.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DamageComp{
|
||||||
|
abstract float damage();
|
||||||
|
}
|
||||||
25
core/src/mindustry/entities/def/DecalComp.java
Normal file
25
core/src/mindustry/entities/def/DecalComp.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DecalComp implements Drawc, Timedc, Rotc, Posc{
|
||||||
|
Color color = new Color(1, 1, 1, 1);
|
||||||
|
TextureRegion region;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
Draw.color(color);
|
||||||
|
Draw.rect(region, x(), y(), rotation());
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float clipSize(){
|
||||||
|
return region.getWidth()*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
core/src/mindustry/entities/def/DrawComp.java
Normal file
14
core/src/mindustry/entities/def/DrawComp.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DrawComp implements Posc{
|
||||||
|
|
||||||
|
abstract float clipSize();
|
||||||
|
|
||||||
|
void draw(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
57
core/src/mindustry/entities/def/DrawItemsComp.java
Normal file
57
core/src/mindustry/entities/def/DrawItemsComp.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.itemSize;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DrawItemsComp implements Drawc, Itemsc, Posc, Rotc{
|
||||||
|
transient float x, y, rotation;
|
||||||
|
|
||||||
|
float itemTime;
|
||||||
|
|
||||||
|
//drawn after base
|
||||||
|
@Override
|
||||||
|
@MethodPriority(3)
|
||||||
|
public void draw(){
|
||||||
|
boolean number = isLocal();
|
||||||
|
itemTime = Mathf.lerpDelta(itemTime, Mathf.num(hasItem()), 0.05f);
|
||||||
|
|
||||||
|
//draw back items
|
||||||
|
if(itemTime > 0.01f){
|
||||||
|
float backTrns = 5f;
|
||||||
|
float size = (itemSize + Mathf.absin(Time.time(), 5f, 1f)) * itemTime;
|
||||||
|
|
||||||
|
Draw.mixcol(Pal.accent, Mathf.absin(Time.time(), 5f, 0.5f));
|
||||||
|
Draw.rect(item().icon(Cicon.medium),
|
||||||
|
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||||
|
y + Angles.trnsy(rotation + 180f, backTrns),
|
||||||
|
size, size, rotation);
|
||||||
|
|
||||||
|
Draw.mixcol();
|
||||||
|
|
||||||
|
Lines.stroke(1f, Pal.accent);
|
||||||
|
Lines.circle(
|
||||||
|
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||||
|
y + Angles.trnsy(rotation + 180f, backTrns),
|
||||||
|
(3f + Mathf.absin(Time.time(), 5f, 1f)) * itemTime);
|
||||||
|
|
||||||
|
if(isLocal()){
|
||||||
|
Fonts.outline.draw(stack().amount + "",
|
||||||
|
x + Angles.trnsx(rotation + 180f, backTrns),
|
||||||
|
y + Angles.trnsy(rotation + 180f, backTrns) - 3,
|
||||||
|
Pal.accent, 0.25f * itemTime / Scl.scl(1f), false, Align.center
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
core/src/mindustry/entities/def/DrawLightComp.java
Normal file
9
core/src/mindustry/entities/def/DrawLightComp.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DrawLightComp implements Drawc{
|
||||||
|
void drawLight(){}
|
||||||
|
}
|
||||||
9
core/src/mindustry/entities/def/DrawOverComp.java
Normal file
9
core/src/mindustry/entities/def/DrawOverComp.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DrawOverComp implements Drawc{
|
||||||
|
void drawOver(){}
|
||||||
|
}
|
||||||
23
core/src/mindustry/entities/def/DrawShadowComp.java
Normal file
23
core/src/mindustry/entities/def/DrawShadowComp.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DrawShadowComp implements Drawc, Rotc, Flyingc{
|
||||||
|
static final float shadowTX = -12, shadowTY = -13, shadowColor = Color.toFloatBits(0, 0, 0, 0.22f);
|
||||||
|
|
||||||
|
transient float x, y, rotation;
|
||||||
|
|
||||||
|
abstract TextureRegion getShadowRegion();
|
||||||
|
|
||||||
|
void drawShadow(){
|
||||||
|
if(!isGrounded()){
|
||||||
|
Draw.color(shadowColor);
|
||||||
|
Draw.rect(getShadowRegion(), x + shadowTX * elevation(), y + shadowTY * elevation(), rotation - 90);
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
core/src/mindustry/entities/def/DrawUnderComp.java
Normal file
9
core/src/mindustry/entities/def/DrawUnderComp.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class DrawUnderComp implements Drawc{
|
||||||
|
void drawUnder(){}
|
||||||
|
}
|
||||||
23
core/src/mindustry/entities/def/EffectComp.java
Normal file
23
core/src/mindustry/entities/def/EffectComp.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.entities.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class EffectComp implements Posc, Drawc, Timedc, Rotc{
|
||||||
|
Effect effect;
|
||||||
|
Color color = new Color(Color.white);
|
||||||
|
Object data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
effect.render(id(), color, time(), rotation(), x(), y(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float clipSize(){
|
||||||
|
return effect.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
core/src/mindustry/entities/def/EntityComp.java
Normal file
60
core/src/mindustry/entities/def/EntityComp.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.player;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@BaseComponent
|
||||||
|
abstract class EntityComp{
|
||||||
|
private boolean added;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
boolean isAdded(){
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(){}
|
||||||
|
|
||||||
|
void update(){}
|
||||||
|
|
||||||
|
void remove(){
|
||||||
|
added = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(){
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLocal(){
|
||||||
|
return ((Object)this) == player || ((Object)this) instanceof Unitc && ((Unitc)((Object)this)).controller() == player;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isNull(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
<T> T as(Class<T> type){
|
||||||
|
return (T)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
<T> T with(Cons<T> cons){
|
||||||
|
cons.get((T)this);
|
||||||
|
return (T)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@InternalImpl
|
||||||
|
abstract int classId();
|
||||||
|
|
||||||
|
void read(DataInput input) throws IOException{
|
||||||
|
//TODO dynamic io
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(DataOutput output) throws IOException{
|
||||||
|
//TODO dynamic io
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +0,0 @@
|
|||||||
package mindustry.entities.def;
|
|
||||||
|
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import mindustry.entities.def.EntityComps.*;
|
|
||||||
|
|
||||||
public class EntityGroupDefs{
|
|
||||||
|
|
||||||
@GroupDef(EntityComp.class)
|
|
||||||
void all(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@GroupDef(PlayerComp.class)
|
|
||||||
void player(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@GroupDef(value = UnitComp.class, spatial = true)
|
|
||||||
void unit(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@GroupDef(TileComp.class)
|
|
||||||
void tile(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@GroupDef(DrawComp.class)
|
|
||||||
void drawer(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@GroupDef(SyncComp.class)
|
|
||||||
void sync(){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
48
core/src/mindustry/entities/def/FlyingComp.java
Normal file
48
core/src/mindustry/entities/def/FlyingComp.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.net;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class FlyingComp implements Posc, Velc, Healthc{
|
||||||
|
transient float x, y;
|
||||||
|
transient Vec2 vel;
|
||||||
|
|
||||||
|
float elevation;
|
||||||
|
float drownTime;
|
||||||
|
|
||||||
|
boolean isGrounded(){
|
||||||
|
return elevation < 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
Floor floor = floorOn();
|
||||||
|
|
||||||
|
if(isGrounded() && floor.isLiquid && vel.len2() > 0.4f*0.4f && Mathf.chance((vel.len2() * floor.speedMultiplier) * 0.03f * Time.delta())){
|
||||||
|
floor.walkEffect.at(x, y, 0, floor.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isGrounded() && floor.isLiquid && floor.drownTime > 0){
|
||||||
|
drownTime += Time.delta() * 1f / floor.drownTime;
|
||||||
|
drownTime = Mathf.clamp(drownTime);
|
||||||
|
if(Mathf.chance(Time.delta() * 0.05f)){
|
||||||
|
floor.drownUpdateEffect.at(x, y, 0f, floor.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO is the netClient check necessary?
|
||||||
|
if(drownTime >= 0.999f && !net.client()){
|
||||||
|
kill();
|
||||||
|
//TODO drown event!
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
drownTime = Mathf.lerpDelta(drownTime, 0f, 0.03f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
76
core/src/mindustry/entities/def/HealthComp.java
Normal file
76
core/src/mindustry/entities/def/HealthComp.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class HealthComp implements Entityc{
|
||||||
|
static final float hitDuration = 9f;
|
||||||
|
|
||||||
|
float health, maxHealth, hitTime;
|
||||||
|
boolean dead;
|
||||||
|
|
||||||
|
boolean isValid(){
|
||||||
|
return !dead && isAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
float healthf(){
|
||||||
|
return health / maxHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
hitTime -= Time.delta() / hitDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void killed(){
|
||||||
|
//implement by other components
|
||||||
|
}
|
||||||
|
|
||||||
|
void kill(){
|
||||||
|
health = 0;
|
||||||
|
dead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heal(){
|
||||||
|
dead = false;
|
||||||
|
health = maxHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean damaged(){
|
||||||
|
return health <= maxHealth - 0.0001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void damage(float amount){
|
||||||
|
health -= amount;
|
||||||
|
if(health <= 0 && !dead){
|
||||||
|
dead = true;
|
||||||
|
killed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void damage(float amount, boolean withEffect){
|
||||||
|
float pre = hitTime;
|
||||||
|
|
||||||
|
damage(amount);
|
||||||
|
|
||||||
|
if(!withEffect){
|
||||||
|
hitTime = pre;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void damageContinuous(float amount){
|
||||||
|
damage(amount * Time.delta(), hitTime <= -20 + hitDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clampHealth(){
|
||||||
|
health = Mathf.clamp(health, 0, maxHealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void heal(float amount){
|
||||||
|
health += amount;
|
||||||
|
clampHealth();
|
||||||
|
}
|
||||||
|
}
|
||||||
51
core/src/mindustry/entities/def/HitboxComp.java
Normal file
51
core/src/mindustry/entities/def/HitboxComp.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.math.geom.QuadTree.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class HitboxComp implements Posc, QuadTreeObject{
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
float hitSize;
|
||||||
|
float lastX, lastY;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLastPosition(){
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void collision(Hitboxc other, float x, float y){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float deltaX(){
|
||||||
|
return x - lastX;
|
||||||
|
}
|
||||||
|
|
||||||
|
float deltaY(){
|
||||||
|
return y - lastY;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean collides(Hitboxc other){
|
||||||
|
return Intersector.overlapsRect(x - hitSize/2f, y - hitSize/2f, hitSize, hitSize,
|
||||||
|
other.x() - other.hitSize()/2f, other.y() - other.hitSize()/2f, other.hitSize(), other.hitSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hitbox(Rect rect){
|
||||||
|
rect.setCentered(x, y, hitSize, hitSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hitboxTile(Rect rect){
|
||||||
|
float scale = 0.6f;
|
||||||
|
rect.setCentered(x, y, hitSize * scale, hitSize * scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
core/src/mindustry/entities/def/ItemsComp.java
Normal file
48
core/src/mindustry/entities/def/ItemsComp.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class ItemsComp implements Posc{
|
||||||
|
@ReadOnly ItemStack stack = new ItemStack();
|
||||||
|
|
||||||
|
abstract int itemCapacity();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
stack.amount = Mathf.clamp(stack.amount, 0, itemCapacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item(){
|
||||||
|
return stack.item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearItem(){
|
||||||
|
stack.amount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean acceptsItem(Item item){
|
||||||
|
return !hasItem() || item == stack.item && stack.amount + 1 <= itemCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasItem(){
|
||||||
|
return stack.amount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addItem(Item item){
|
||||||
|
addItem(item, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addItem(Item item, int amount){
|
||||||
|
stack.amount = stack.item == item ? stack.amount + amount : amount;
|
||||||
|
stack.item = item;
|
||||||
|
stack.amount = Mathf.clamp(stack.amount, 0, itemCapacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxAccepted(Item item){
|
||||||
|
return stack.item != item && stack.amount > 0 ? 0 : itemCapacity() - stack.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
core/src/mindustry/entities/def/LegsComp.java
Normal file
9
core/src/mindustry/entities/def/LegsComp.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class LegsComp implements Posc, Flyingc{
|
||||||
|
float baseRotation;
|
||||||
|
}
|
||||||
13
core/src/mindustry/entities/def/MassComp.java
Normal file
13
core/src/mindustry/entities/def/MassComp.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class MassComp implements Velc{
|
||||||
|
float mass = 1f;
|
||||||
|
|
||||||
|
public void applyImpulse(float x, float y){
|
||||||
|
vel().add(x / mass, y / mass);
|
||||||
|
}
|
||||||
|
}
|
||||||
100
core/src/mindustry/entities/def/MinerComp.java
Normal file
100
core/src/mindustry/entities/def/MinerComp.java
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.input.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc{
|
||||||
|
transient float x, y, rotation;
|
||||||
|
|
||||||
|
@Nullable Tile mineTile;
|
||||||
|
|
||||||
|
abstract boolean canMine(Item item);
|
||||||
|
|
||||||
|
abstract float miningSpeed();
|
||||||
|
|
||||||
|
abstract boolean offloadImmediately();
|
||||||
|
|
||||||
|
boolean mining(){
|
||||||
|
return mineTile != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateMining(){
|
||||||
|
Tilec core = closestCore();
|
||||||
|
|
||||||
|
if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && dst(core) < mineTransferRange){
|
||||||
|
int accepted = core.tile().block().acceptStack(item(), stack().amount, core.tile(), this);
|
||||||
|
if(accepted > 0){
|
||||||
|
Call.transferItemTo(item(), accepted,
|
||||||
|
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||||
|
mineTile.worldy() + Mathf.range(tilesize / 2f), core.tile());
|
||||||
|
clearItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mineTile == null || core == null || mineTile.block() != Blocks.air || dst(mineTile.worldx(), mineTile.worldy()) > miningRange
|
||||||
|
|| mineTile.drop() == null || !acceptsItem(mineTile.drop()) || !canMine(mineTile.drop())){
|
||||||
|
mineTile = null;
|
||||||
|
}else{
|
||||||
|
Item item = mineTile.drop();
|
||||||
|
rotation(Mathf.slerpDelta(rotation(), angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f));
|
||||||
|
|
||||||
|
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * miningSpeed())){
|
||||||
|
|
||||||
|
if(dst(core) < mineTransferRange && core.tile().block().acceptStack(item, 1, core.tile(), this) == 1 && offloadImmediately()){
|
||||||
|
Call.transferItemTo(item, 1,
|
||||||
|
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||||
|
mineTile.worldy() + Mathf.range(tilesize / 2f), core.tile());
|
||||||
|
}else if(acceptsItem(item)){
|
||||||
|
//this is clientside, since items are synced anyway
|
||||||
|
InputHandler.transferItemToUnit(item,
|
||||||
|
mineTile.worldx() + Mathf.range(tilesize / 2f),
|
||||||
|
mineTile.worldy() + Mathf.range(tilesize / 2f),
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Mathf.chance(0.06 * Time.delta())){
|
||||||
|
Fx.pulverizeSmall.at(mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawOver(){
|
||||||
|
if(!mining()) return;
|
||||||
|
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
|
||||||
|
float swingScl = 12f, swingMag = tilesize / 8f;
|
||||||
|
float flashScl = 0.3f;
|
||||||
|
|
||||||
|
float px = x + Angles.trnsx(rotation, focusLen);
|
||||||
|
float py = y + Angles.trnsy(rotation, focusLen);
|
||||||
|
|
||||||
|
float ex = mineTile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
|
||||||
|
float ey = mineTile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
|
||||||
|
|
||||||
|
Draw.color(Color.lightGray, Color.white, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
|
||||||
|
|
||||||
|
Drawf.laser(Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f);
|
||||||
|
|
||||||
|
//TODO hack?
|
||||||
|
if(isLocal()){
|
||||||
|
Lines.stroke(1f, Pal.accent);
|
||||||
|
Lines.poly(mineTile.worldx(), mineTile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
core/src/mindustry/entities/def/OwnerComp.java
Normal file
9
core/src/mindustry/entities/def/OwnerComp.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class OwnerComp{
|
||||||
|
Entityc owner;
|
||||||
|
}
|
||||||
203
core/src/mindustry/entities/def/PlayerComp.java
Normal file
203
core/src/mindustry/entities/def/PlayerComp.java
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import arc.util.pooling.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.core.*;
|
||||||
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.game.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.net.*;
|
||||||
|
import mindustry.net.Administration.*;
|
||||||
|
import mindustry.net.Packets.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc{
|
||||||
|
@NonNull
|
||||||
|
@ReadOnly Unitc unit = Nulls.unit;
|
||||||
|
|
||||||
|
@ReadOnly Team team = Team.sharded;
|
||||||
|
String name = "noname";
|
||||||
|
@Nullable NetConnection con;
|
||||||
|
boolean admin, typing;
|
||||||
|
Color color = new Color();
|
||||||
|
float mouseX, mouseY;
|
||||||
|
|
||||||
|
@Nullable String lastText;
|
||||||
|
float textFadeTime;
|
||||||
|
|
||||||
|
public boolean isBuilder(){
|
||||||
|
return unit instanceof Builderc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMiner(){
|
||||||
|
return unit instanceof Minerc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Tilec closestCore(){
|
||||||
|
return state.teams.closestCore(x(), y(), team);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset(){
|
||||||
|
team = state.rules.defaultTeam;
|
||||||
|
admin = typing = false;
|
||||||
|
lastText = null;
|
||||||
|
textFadeTime = 0f;
|
||||||
|
if(!dead()){
|
||||||
|
unit.controller(unit.type().createController());
|
||||||
|
unit = Nulls.unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(){
|
||||||
|
if(!dead()){
|
||||||
|
x(unit.x());
|
||||||
|
y(unit.y());
|
||||||
|
unit.team(team);
|
||||||
|
}
|
||||||
|
textFadeTime -= Time.delta() / (60 * 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void team(Team team){
|
||||||
|
if(unit != null){
|
||||||
|
unit.team(team);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearUnit(){
|
||||||
|
unit(Nulls.unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unitc unit(){
|
||||||
|
if(dead()){
|
||||||
|
//TODO remove
|
||||||
|
Log.err("WARNING: DEAD PLAYER UNIT ACCESSED");
|
||||||
|
new RuntimeException().printStackTrace();
|
||||||
|
}
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Minerc miner(){
|
||||||
|
return !(unit instanceof Minerc) ? Nulls.miner : (Minerc)unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builderc builder(){
|
||||||
|
return !(unit instanceof Builderc) ? Nulls.builder : (Builderc)unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unit(Unitc unit){
|
||||||
|
if(unit == null) throw new IllegalArgumentException("Unit cannot be null. Use clearUnit() instead.");
|
||||||
|
this.unit = unit;
|
||||||
|
if(unit != Nulls.unit){
|
||||||
|
unit.team(team);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean dead(){
|
||||||
|
return unit.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
String uuid(){
|
||||||
|
return con == null ? "[LOCAL]" : con.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
String usid(){
|
||||||
|
return con == null ? "[LOCAL]" : con.usid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kick(KickReason reason){
|
||||||
|
con.kick(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kick(String reason){
|
||||||
|
con.kick(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawName(){
|
||||||
|
BitmapFont font = Fonts.def;
|
||||||
|
GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
|
||||||
|
final float nameHeight = 11;
|
||||||
|
final float textHeight = 15;
|
||||||
|
|
||||||
|
boolean ints = font.usesIntegerPositions();
|
||||||
|
font.setUseIntegerPositions(false);
|
||||||
|
font.getData().setScale(0.25f / Scl.scl(1f));
|
||||||
|
layout.setText(font, name);
|
||||||
|
|
||||||
|
if(!isLocal()){
|
||||||
|
Draw.color(0f, 0f, 0f, 0.3f);
|
||||||
|
Fill.rect(unit.x(), unit.y() + nameHeight - layout.height / 2, layout.width + 2, layout.height + 3);
|
||||||
|
Draw.color();
|
||||||
|
font.setColor(color);
|
||||||
|
font.draw(name, unit.x(), unit.y() + nameHeight, 0, Align.center, false);
|
||||||
|
|
||||||
|
if(admin){
|
||||||
|
float s = 3f;
|
||||||
|
Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f);
|
||||||
|
Draw.rect(Icon.adminSmall.getRegion(), unit.x() + layout.width / 2f + 2 + 1, unit.y() + nameHeight - 1.5f, s, s);
|
||||||
|
Draw.color(color);
|
||||||
|
Draw.rect(Icon.adminSmall.getRegion(), unit.x() + layout.width / 2f + 2 + 1, unit.y() + nameHeight - 1f, s, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Core.settings.getBool("playerchat") && ((textFadeTime > 0 && lastText != null) || typing)){
|
||||||
|
String text = textFadeTime <= 0 || lastText == null ? "[LIGHT_GRAY]" + Strings.animated(Time.time(), 4, 15f, ".") : lastText;
|
||||||
|
float width = 100f;
|
||||||
|
float visualFadeTime = 1f - Mathf.curve(1f - textFadeTime, 0.9f);
|
||||||
|
font.setColor(1f, 1f, 1f, textFadeTime <= 0 || lastText == null ? 1f : visualFadeTime);
|
||||||
|
|
||||||
|
layout.setText(font, text, Color.white, width, Align.bottom, true);
|
||||||
|
|
||||||
|
Draw.color(0f, 0f, 0f, 0.3f * (textFadeTime <= 0 || lastText == null ? 1f : visualFadeTime));
|
||||||
|
Fill.rect(unit.x(), unit.y() + textHeight + layout.height - layout.height/2f, layout.width + 2, layout.height + 3);
|
||||||
|
font.draw(text, unit.x() - width/2f, unit.y() + textHeight + layout.height, width, Align.center, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
|
Pools.free(layout);
|
||||||
|
font.getData().setScale(1f);
|
||||||
|
font.setColor(Color.white);
|
||||||
|
font.setUseIntegerPositions(ints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessage(String text){
|
||||||
|
if(isLocal()){
|
||||||
|
if(ui != null){
|
||||||
|
ui.chatfrag.addMessage(text, null);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Call.sendMessage(con, text, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessage(String text, Playerc from){
|
||||||
|
sendMessage(text, from, NetClient.colorizeName(from.id(), from.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessage(String text, Playerc from, String fromName){
|
||||||
|
if(isLocal()){
|
||||||
|
if(ui != null){
|
||||||
|
ui.chatfrag.addMessage(text, fromName);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Call.sendMessage(con, text, fromName, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerInfo getInfo(){
|
||||||
|
if(isLocal()){
|
||||||
|
throw new IllegalArgumentException("Local players cannot be traced and do not have info.");
|
||||||
|
}else{
|
||||||
|
return netServer.admins.getInfo(uuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
core/src/mindustry/entities/def/PosComp.java
Normal file
54
core/src/mindustry/entities/def/PosComp.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.world;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class PosComp implements Position{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
void set(float x, float y){
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void trns(float x, float y){
|
||||||
|
set(this.x + x, this.y + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tileX(){
|
||||||
|
return Vars.world.toTile(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tileY(){
|
||||||
|
return Vars.world.toTile(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns air if this unit is on a non-air top block. */
|
||||||
|
public Floor floorOn(){
|
||||||
|
Tile tile = tileOn();
|
||||||
|
return tile == null || tile.block() != Blocks.air ? (Floor)Blocks.air : tile.floor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable
|
||||||
|
Tile tileOn(){
|
||||||
|
return world.tileWorld(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getX(){
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getY(){
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
core/src/mindustry/entities/def/RotComp.java
Normal file
17
core/src/mindustry/entities/def/RotComp.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class RotComp implements Entityc{
|
||||||
|
float rotation;
|
||||||
|
|
||||||
|
void interpolate(){
|
||||||
|
Syncc sync = as(Syncc.class);
|
||||||
|
|
||||||
|
if(sync.interpolator().values.length > 0){
|
||||||
|
rotation = sync.interpolator().values[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
core/src/mindustry/entities/def/ShielderComp.java
Normal file
12
core/src/mindustry/entities/def/ShielderComp.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class ShielderComp implements Damagec, Teamc, Posc{
|
||||||
|
|
||||||
|
void absorb(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
147
core/src/mindustry/entities/def/StatusComp.java
Normal file
147
core/src/mindustry/entities/def/StatusComp.java
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.pooling.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.content;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class StatusComp implements Posc, Flyingc{
|
||||||
|
private Array<StatusEntry> statuses = new Array<>();
|
||||||
|
private Bits applied = new Bits(content.getBy(ContentType.status).size);
|
||||||
|
|
||||||
|
@ReadOnly float speedMultiplier;
|
||||||
|
@ReadOnly float damageMultiplier;
|
||||||
|
@ReadOnly float armorMultiplier;
|
||||||
|
|
||||||
|
/** @return damage taken based on status armor multipliers */
|
||||||
|
float getShieldDamage(float amount){
|
||||||
|
return amount * Mathf.clamp(1f - armorMultiplier / 100f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(StatusEffect effect, float duration){
|
||||||
|
if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects
|
||||||
|
|
||||||
|
if(statuses.size > 0){
|
||||||
|
//check for opposite effects
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
//extend effect
|
||||||
|
if(entry.effect == effect){
|
||||||
|
entry.time = Math.max(entry.time, duration);
|
||||||
|
return;
|
||||||
|
}else if(entry.effect.reactsWith(effect)){ //find opposite
|
||||||
|
StatusEntry.tmp.effect = entry.effect;
|
||||||
|
entry.effect.getTransition((Unitc)this, effect, entry.time, duration, StatusEntry.tmp);
|
||||||
|
entry.time = StatusEntry.tmp.time;
|
||||||
|
|
||||||
|
if(StatusEntry.tmp.effect != entry.effect){
|
||||||
|
entry.effect = StatusEntry.tmp.effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
//stop looking when one is found
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise, no opposites found, add direct effect
|
||||||
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
|
entry.set(effect, duration);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isBoss(){
|
||||||
|
return hasEffect(StatusEffects.boss);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isImmune(StatusEffect effect){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color statusColor(){
|
||||||
|
if(statuses.size == 0){
|
||||||
|
return Tmp.c1.set(Color.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
float r = 0f, g = 0f, b = 0f;
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
r += entry.effect.color.r;
|
||||||
|
g += entry.effect.color.g;
|
||||||
|
b += entry.effect.color.b;
|
||||||
|
}
|
||||||
|
return Tmp.c1.set(r / statuses.size, g / statuses.size, b / statuses.size, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
Floor floor = floorOn();
|
||||||
|
if(isGrounded() && floor.status != null){
|
||||||
|
//apply effect
|
||||||
|
apply(floor.status, floor.statusDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
applied.clear();
|
||||||
|
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
|
||||||
|
|
||||||
|
if(statuses.isEmpty()) return;
|
||||||
|
|
||||||
|
statuses.eachFilter(entry -> {
|
||||||
|
entry.time = Math.max(entry.time - Time.delta(), 0);
|
||||||
|
applied.set(entry.effect.id);
|
||||||
|
|
||||||
|
if(entry.time <= 0){
|
||||||
|
Pools.free(entry);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
speedMultiplier *= entry.effect.speedMultiplier;
|
||||||
|
armorMultiplier *= entry.effect.armorMultiplier;
|
||||||
|
damageMultiplier *= entry.effect.damageMultiplier;
|
||||||
|
//TODO ugly casting
|
||||||
|
entry.effect.update((Unitc)this, entry.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasEffect(StatusEffect effect){
|
||||||
|
return applied.get(effect.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSave(DataOutput stream) throws IOException{
|
||||||
|
stream.writeByte(statuses.size);
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
stream.writeByte(entry.effect.id);
|
||||||
|
stream.writeFloat(entry.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readSave(DataInput stream, byte version) throws IOException{
|
||||||
|
for(StatusEntry effect : statuses){
|
||||||
|
Pools.free(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
statuses.clear();
|
||||||
|
|
||||||
|
byte amount = stream.readByte();
|
||||||
|
for(int i = 0; i < amount; i++){
|
||||||
|
byte id = stream.readByte();
|
||||||
|
float time = stream.readFloat();
|
||||||
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
|
entry.set(content.getByID(ContentType.status, id), time);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
core/src/mindustry/entities/def/SyncComp.java
Normal file
37
core/src/mindustry/entities/def/SyncComp.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.net.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class SyncComp implements Posc{
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
Interpolator interpolator = new Interpolator();
|
||||||
|
|
||||||
|
void setNet(float x, float y){
|
||||||
|
set(x, y);
|
||||||
|
|
||||||
|
//TODO change interpolator API
|
||||||
|
interpolator.target.set(x, y);
|
||||||
|
interpolator.last.set(x, y);
|
||||||
|
interpolator.pos.set(0, 0);
|
||||||
|
interpolator.updateSpacing = 16;
|
||||||
|
interpolator.lastUpdated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
if(Vars.net.client() && !isLocal()){
|
||||||
|
interpolate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void interpolate(){
|
||||||
|
interpolator.update();
|
||||||
|
x = interpolator.pos.x;
|
||||||
|
y = interpolator.pos.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
core/src/mindustry/entities/def/TeamComp.java
Normal file
20
core/src/mindustry/entities/def/TeamComp.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.game.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.state;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class TeamComp implements Posc{
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
Team team = Team.sharded;
|
||||||
|
|
||||||
|
public @Nullable
|
||||||
|
Tilec closestCore(){
|
||||||
|
return state.teams.closestCore(x, y, team);
|
||||||
|
}
|
||||||
|
}
|
||||||
241
core/src/mindustry/entities/def/TileComp.java
Normal file
241
core/src/mindustry/entities/def/TileComp.java
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.game.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.consumers.*;
|
||||||
|
import mindustry.world.modules.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
|
||||||
|
static final float timeToSleep = 60f * 1;
|
||||||
|
static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
|
||||||
|
static int sleepingEntities = 0;
|
||||||
|
|
||||||
|
Tile tile;
|
||||||
|
Block block;
|
||||||
|
Array<Tile> proximity = new Array<>(8);
|
||||||
|
|
||||||
|
PowerModule power;
|
||||||
|
ItemModule items;
|
||||||
|
LiquidModule liquids;
|
||||||
|
ConsumeModule cons;
|
||||||
|
|
||||||
|
private float timeScale = 1f, timeScaleDuration;
|
||||||
|
|
||||||
|
private @Nullable SoundLoop sound;
|
||||||
|
|
||||||
|
private boolean sleeping;
|
||||||
|
private float sleepTime;
|
||||||
|
|
||||||
|
/** Sets this tile entity data to this tile, and adds it if necessary. */
|
||||||
|
@Override
|
||||||
|
public Tilec init(Tile tile, boolean shouldAdd){
|
||||||
|
this.tile = tile;
|
||||||
|
this.block = tile.block();
|
||||||
|
|
||||||
|
set(tile.drawx(), tile.drawy());
|
||||||
|
if(block.activeSound != Sounds.none){
|
||||||
|
sound = new SoundLoop(block.activeSound, block.activeSoundVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
health(block.health);
|
||||||
|
maxHealth(block.health);
|
||||||
|
timer(new Interval(block.timers));
|
||||||
|
|
||||||
|
if(shouldAdd){
|
||||||
|
add();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyBoost(float intensity, float duration){
|
||||||
|
timeScale = Math.max(timeScale, intensity);
|
||||||
|
timeScaleDuration = Math.max(timeScaleDuration, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float timeScale(){
|
||||||
|
return timeScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean consValid(){
|
||||||
|
return cons.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consume(){
|
||||||
|
cons.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Scaled delta. */
|
||||||
|
@Override
|
||||||
|
public float delta(){
|
||||||
|
return Time.delta() * timeScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Base efficiency. If this entity has non-buffered power, returns the power %, otherwise returns 1. */
|
||||||
|
@Override
|
||||||
|
public float efficiency(){
|
||||||
|
return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Call when nothing is happening to the entity. This increments the internal sleep timer. */
|
||||||
|
@Override
|
||||||
|
public void sleep(){
|
||||||
|
sleepTime += Time.delta();
|
||||||
|
if(!sleeping && sleepTime >= timeToSleep){
|
||||||
|
remove();
|
||||||
|
sleeping = true;
|
||||||
|
sleepingEntities++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Call when this entity is updating. This wakes it up. */
|
||||||
|
@Override
|
||||||
|
public void noSleep(){
|
||||||
|
sleepTime = 0f;
|
||||||
|
if(sleeping){
|
||||||
|
add();
|
||||||
|
sleeping = false;
|
||||||
|
sleepingEntities--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the version of this TileEntity IO code.*/
|
||||||
|
@Override
|
||||||
|
public byte version(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean collide(Bulletc other){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collision(Bulletc other){
|
||||||
|
block.handleBulletHit(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Implement damage!
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeFromProximity(){
|
||||||
|
block.onProximityRemoved(tile);
|
||||||
|
|
||||||
|
Point2[] nearby = Edges.getEdges(block.size);
|
||||||
|
for(Point2 point : nearby){
|
||||||
|
Tile other = world.ltile(tile.x + point.x, tile.y + point.y);
|
||||||
|
//remove this tile from all nearby tile's proximities
|
||||||
|
if(other != null){
|
||||||
|
other.block().onProximityUpdate(other);
|
||||||
|
|
||||||
|
if(other.entity != null){
|
||||||
|
other.entity.proximity().remove(tile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateProximity(){
|
||||||
|
tmpTiles.clear();
|
||||||
|
proximity.clear();
|
||||||
|
|
||||||
|
Point2[] nearby = Edges.getEdges(block.size);
|
||||||
|
for(Point2 point : nearby){
|
||||||
|
Tile other = world.ltile(tile.x + point.x, tile.y + point.y);
|
||||||
|
|
||||||
|
if(other == null) continue;
|
||||||
|
if(other.entity == null || !(other.interactable(tile.team()))) continue;
|
||||||
|
|
||||||
|
//add this tile to proximity of nearby tiles
|
||||||
|
if(!other.entity.proximity().contains(tile, true)){
|
||||||
|
other.entity.proximity().add(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpTiles.add(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
//using a set to prevent duplicates
|
||||||
|
for(Tile tile : tmpTiles){
|
||||||
|
proximity.add(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
block.onProximityAdded(tile);
|
||||||
|
block.onProximityUpdate(tile);
|
||||||
|
|
||||||
|
for(Tile other : tmpTiles){
|
||||||
|
other.block().onProximityUpdate(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Array<Tile> proximity(){
|
||||||
|
return proximity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tile configuration. Defaults to 0. Used for block rebuilding. */
|
||||||
|
@Override
|
||||||
|
public int config(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(){
|
||||||
|
if(sound != null){
|
||||||
|
sound.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void killed(){
|
||||||
|
Events.fire(new BlockDestroyEvent(tile));
|
||||||
|
block.breakSound.at(tile);
|
||||||
|
block.onDestroyed(tile);
|
||||||
|
tile.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
timeScaleDuration -= Time.delta();
|
||||||
|
if(timeScaleDuration <= 0f || !block.canOverdrive){
|
||||||
|
timeScale = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sound != null){
|
||||||
|
sound.update(x(), y(), block.shouldActiveSound(tile));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(block.idleSound != Sounds.none && block.shouldIdleSound(tile)){
|
||||||
|
loops.play(block.idleSound, this, block.idleSoundVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
block.update(tile);
|
||||||
|
|
||||||
|
if(liquids != null){
|
||||||
|
liquids.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cons != null){
|
||||||
|
cons.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(power != null){
|
||||||
|
power.graph.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
core/src/mindustry/entities/def/TimedComp.java
Normal file
25
core/src/mindustry/entities/def/TimedComp.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class TimedComp implements Entityc, Scaled{
|
||||||
|
float time, lifetime;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
time = Math.min(time + Time.delta(), lifetime);
|
||||||
|
|
||||||
|
if(time >= lifetime){
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float fin(){
|
||||||
|
return time / lifetime;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
core/src/mindustry/entities/def/TimerComp.java
Normal file
13
core/src/mindustry/entities/def/TimerComp.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class TimerComp{
|
||||||
|
Interval timer = new Interval(6);
|
||||||
|
|
||||||
|
public boolean timer(int index, float time){
|
||||||
|
return timer.get(index, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
127
core/src/mindustry/entities/def/UnitComp.java
Normal file
127
core/src/mindustry/entities/def/UnitComp.java
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.entities.*;
|
||||||
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class UnitComp implements Healthc, Velc, Statusc, Teamc, Itemsc, Hitboxc, Rotc, Massc, Unitc, Weaponsc{
|
||||||
|
private UnitController controller;
|
||||||
|
private UnitDef type;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int itemCapacity(){
|
||||||
|
return type.itemCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float bounds(){
|
||||||
|
return hitSize() * 2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void controller(UnitController controller){
|
||||||
|
this.controller = controller;
|
||||||
|
controller.unit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UnitController controller(){
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(UnitDef def, UnitController controller){
|
||||||
|
type(type);
|
||||||
|
controller(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void type(UnitDef type){
|
||||||
|
this.type = type;
|
||||||
|
controller(type.createController());
|
||||||
|
setupWeapons(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UnitDef type(){
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
//apply knockback based on spawns
|
||||||
|
//TODO move elsewhere
|
||||||
|
if(team() != state.rules.waveTeam){
|
||||||
|
float relativeSize = state.rules.dropZoneRadius + bounds()/2f + 1f;
|
||||||
|
for(Tile spawn : spawner.getGroundSpawns()){
|
||||||
|
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||||
|
vel().add(Tmp.v1.set(this).sub(spawn.worldx(), spawn.worldy()).setLength(0.1f + 1f - dst(spawn) / relativeSize).scl(0.45f * Time.delta()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tile tile = tileOn();
|
||||||
|
Floor floor = floorOn();
|
||||||
|
|
||||||
|
if(tile != null){
|
||||||
|
//unit block update
|
||||||
|
tile.block().unitOn(tile, this);
|
||||||
|
|
||||||
|
//apply damage
|
||||||
|
if(floor.damageTaken > 0f){
|
||||||
|
damageContinuous(floor.damageTaken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawLight(){
|
||||||
|
//TODO move
|
||||||
|
if(type.lightRadius > 0){
|
||||||
|
renderer.lights.add(getX(), getY(), type.lightRadius, type.lightColor, 0.6f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
//draw power cell - TODO move
|
||||||
|
Draw.color(Color.black, team().color, healthf() + Mathf.absin(Time.time(), Math.max(healthf() * 5f, 1f), 1f - healthf()));
|
||||||
|
Draw.rect(type.cellRegion, getX(), getY(), rotation() - 90);
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void killed(){
|
||||||
|
float explosiveness = 2f + item().explosiveness * stack().amount;
|
||||||
|
float flammability = item().flammability * stack().amount;
|
||||||
|
Damage.dynamicExplosion(getX(), getY(), flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame);
|
||||||
|
|
||||||
|
//TODO cleanup
|
||||||
|
//ScorchDecal.create(getX(), getY());
|
||||||
|
Fx.explosion.at(this);
|
||||||
|
Effects.shake(2f, 2f, this);
|
||||||
|
|
||||||
|
Sounds.bang.at(this);
|
||||||
|
Events.fire(new UnitDestroyEvent(this));
|
||||||
|
|
||||||
|
//TODO implement suicide bomb trigger
|
||||||
|
//if(explosiveness > 7f && this == player){
|
||||||
|
// Events.fire(Trigger.suicideBomb);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
core/src/mindustry/entities/def/VelComp.java
Normal file
22
core/src/mindustry/entities/def/VelComp.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class VelComp implements Posc{
|
||||||
|
transient float x, y;
|
||||||
|
|
||||||
|
final Vec2 vel = new Vec2();
|
||||||
|
float drag = 0f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
//TODO handle solidity
|
||||||
|
x += vel.x;
|
||||||
|
y += vel.y;
|
||||||
|
vel.scl(1f - drag * Time.delta());
|
||||||
|
}
|
||||||
|
}
|
||||||
148
core/src/mindustry/entities/def/WeaponsComp.java
Normal file
148
core/src/mindustry/entities/def/WeaponsComp.java
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.entities.*;
|
||||||
|
import mindustry.entities.bullet.*;
|
||||||
|
import mindustry.entities.units.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
abstract class WeaponsComp implements Teamc, Posc, Rotc{
|
||||||
|
transient float x, y, rotation;
|
||||||
|
|
||||||
|
/** 1 */
|
||||||
|
static final int[] one = {1};
|
||||||
|
/** minimum cursor distance from player, fixes 'cross-eyed' shooting */
|
||||||
|
static final float minAimDst = 20f;
|
||||||
|
/** temporary weapon sequence number */
|
||||||
|
static int sequenceNum = 0;
|
||||||
|
|
||||||
|
/** weapon mount array, never null */
|
||||||
|
@ReadOnly WeaponMount[] mounts = {};
|
||||||
|
|
||||||
|
void setupWeapons(UnitDef def){
|
||||||
|
mounts = new WeaponMount[def.weapons.size];
|
||||||
|
for(int i = 0; i < mounts.length; i++){
|
||||||
|
mounts[i] = new WeaponMount(def.weapons.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Aim at something. This will make all mounts point at it. */
|
||||||
|
void aim(Unitc unit, float x, float y){
|
||||||
|
Tmp.v1.set(x, y).sub(this.x, this.y);
|
||||||
|
if(Tmp.v1.len() < minAimDst) Tmp.v1.setLength(minAimDst);
|
||||||
|
|
||||||
|
x = Tmp.v1.x + this.x;
|
||||||
|
y = Tmp.v1.y + this.y;
|
||||||
|
|
||||||
|
for(WeaponMount mount : mounts){
|
||||||
|
mount.aimX = x;
|
||||||
|
mount.aimY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update shooting and rotation for this unit. */
|
||||||
|
@Override
|
||||||
|
public void update(){
|
||||||
|
for(WeaponMount mount : mounts){
|
||||||
|
Weapon weapon = mount.weapon;
|
||||||
|
mount.reload -= Time.delta();
|
||||||
|
|
||||||
|
float rotation = this.rotation - 90;
|
||||||
|
|
||||||
|
//rotate if applicable
|
||||||
|
if(weapon.rotate){
|
||||||
|
float axisXOffset = weapon.mirror ? 0f : weapon.x;
|
||||||
|
float axisX = this.x + Angles.trnsx(rotation, axisXOffset, weapon.y),
|
||||||
|
axisY = this.y + Angles.trnsy(rotation, axisXOffset, weapon.y);
|
||||||
|
|
||||||
|
mount.rotation = Angles.moveToward(mount.rotation, Angles.angle(axisX, axisY, mount.aimX, mount.aimY), weapon.rotateSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
//shoot if applicable
|
||||||
|
//TODO only shoot if angle is reached, don't shoot inaccurately
|
||||||
|
if(mount.reload <= 0){
|
||||||
|
for(int i : (weapon.mirror && !weapon.alternate ? Mathf.signs : one)){
|
||||||
|
i *= Mathf.sign(weapon.flipped) * Mathf.sign(mount.side);
|
||||||
|
|
||||||
|
//m a t h
|
||||||
|
float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0);
|
||||||
|
float mountX = this.x + Angles.trnsx(rotation, weapon.x * i, weapon.y),
|
||||||
|
mountY = this.y + Angles.trnsy(rotation, weapon.x * i, weapon.y);
|
||||||
|
float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX * i, weapon.shootY),
|
||||||
|
shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX * i, weapon.shootY);
|
||||||
|
float shootAngle = weapon.rotate ? weaponRotation : Angles.angle(shootX, shootY, mount.aimX, mount.aimY);
|
||||||
|
|
||||||
|
shoot(weapon, shootX, shootY, shootAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mount.side = !mount.side;
|
||||||
|
mount.reload = weapon.reload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draw weapon mounts. */
|
||||||
|
void draw(){
|
||||||
|
for(WeaponMount mount : mounts){
|
||||||
|
Weapon weapon = mount.weapon;
|
||||||
|
|
||||||
|
for(int i : (weapon.mirror ? Mathf.signs : one)){
|
||||||
|
i *= Mathf.sign(weapon.flipped);
|
||||||
|
|
||||||
|
float rotation = this.rotation - 90 + (weapon.rotate ? mount.rotation : 0);
|
||||||
|
float trY = weapon.y - (mount.reload / weapon.reload * weapon.recoil) * (weapon.alternate ? Mathf.num(i == Mathf.sign(mount.side)) : 1);
|
||||||
|
float width = i > 0 ? -weapon.region.getWidth() : weapon.region.getWidth();
|
||||||
|
|
||||||
|
Draw.rect(weapon.region,
|
||||||
|
x + Angles.trnsx(rotation, weapon.x * i, trY),
|
||||||
|
y + Angles.trnsy(rotation, weapon.x * i, trY),
|
||||||
|
width * Draw.scl,
|
||||||
|
weapon.region.getHeight() * Draw.scl,
|
||||||
|
rotation - 90);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shoot(Weapon weapon, float x, float y, float rotation){
|
||||||
|
float baseX = this.x, baseY = this.y;
|
||||||
|
|
||||||
|
weapon.shootSound.at(x, y, Mathf.random(0.8f, 1.0f));
|
||||||
|
|
||||||
|
sequenceNum = 0;
|
||||||
|
if(weapon.shotDelay > 0.01f){
|
||||||
|
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> {
|
||||||
|
Time.run(sequenceNum * weapon.shotDelay, () -> bullet(weapon, x + this.x - baseX, y + this.y - baseY, f + Mathf.range(weapon.inaccuracy)));
|
||||||
|
sequenceNum++;
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BulletType ammo = weapon.bullet;
|
||||||
|
|
||||||
|
Tmp.v1.trns(rotation + 180f, ammo.recoil);
|
||||||
|
|
||||||
|
if(this instanceof Velc){
|
||||||
|
//TODO apply force?
|
||||||
|
((Velc)this).vel().add(Tmp.v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tmp.v1.trns(rotation, 3f);
|
||||||
|
boolean parentize = ammo.keepVelocity;
|
||||||
|
|
||||||
|
Effects.shake(weapon.shake, weapon.shake, x, y);
|
||||||
|
weapon.ejectEffect.at(x, y, rotation);
|
||||||
|
ammo.shootEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? this : null);
|
||||||
|
ammo.smokeEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? this : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bullet(Weapon weapon, float x, float y, float angle){
|
||||||
|
Tmp.v1.trns(angle, 3f);
|
||||||
|
weapon.bullet.create(this, team(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,5 +7,6 @@ public enum RenderLayer{
|
|||||||
flyingShadows,
|
flyingShadows,
|
||||||
flying,
|
flying,
|
||||||
bullets,
|
bullets,
|
||||||
effects
|
effects,
|
||||||
|
names,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=6c4b3d49c647e1d594bfd9c3e40db922f8516e5d
|
archash=a57e709113a364ff718821de4c40366e17353329
|
||||||
|
|||||||
Reference in New Issue
Block a user