DEATH AND DESTRUCTION
This commit is contained in:
@@ -442,7 +442,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
public void consume(){
|
||||
for(Consume cons : block.consumes.all){
|
||||
for(Consume cons : block.consumers){
|
||||
cons.trigger(self());
|
||||
}
|
||||
}
|
||||
@@ -465,7 +465,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
public float efficiency(){
|
||||
//disabled -> 0 efficiency
|
||||
if(!enabled) return 0;
|
||||
return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f;
|
||||
return power != null && (block.consPower != null && !block.consPower.buffered) ? power.status : 1f;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -702,11 +702,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
public boolean acceptItem(Building source, Item item){
|
||||
return block.consumes.consumesItem(item) && items.get(item) < getMaximumAccepted(item);
|
||||
return block.consumesItem(item) && items.get(item) < getMaximumAccepted(item);
|
||||
}
|
||||
|
||||
public boolean acceptLiquid(Building source, Liquid liquid){
|
||||
return block.hasLiquids && block.consumes.liquidfilters.get(liquid.id);
|
||||
return block.hasLiquids && block.consumesLiquid(liquid);
|
||||
}
|
||||
|
||||
public void handleLiquid(Building source, Liquid liquid, float amount){
|
||||
@@ -791,7 +791,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
liquids.remove(liquid, flow);
|
||||
return flow;
|
||||
//handle reactions between different liquid types ▼
|
||||
}else if(!next.block.consumes.consumesLiquid(liquid) && next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
|
||||
}else if(!next.block.consumesLiquid(liquid) && next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
|
||||
//TODO !IMPORTANT! uses current(), which is 1) wrong for multi-liquid blocks and 2) causes unwanted reactions, e.g. hydrogen + slag in pump
|
||||
//TODO these are incorrect effect positions
|
||||
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
|
||||
@@ -1043,7 +1043,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
public void drawStatus(){
|
||||
if(block.enableDrawStatus && block.consumes.any()){
|
||||
if(block.enableDrawStatus && block.consumers.length > 0){
|
||||
float multiplier = block.size > 1 ? 1 : 0.64f;
|
||||
float brcx = x + (block.size * tilesize / 2f) - (tilesize * multiplier / 2f);
|
||||
float brcy = y - (block.size * tilesize / 2f) + (tilesize * multiplier / 2f);
|
||||
@@ -1249,8 +1249,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
explosiveness += liquids.sum((liquid, amount) -> liquid.explosiveness * amount / 2f);
|
||||
}
|
||||
|
||||
if(block.consumes.hasPower() && block.consumes.getPower().buffered){
|
||||
power += this.power.status * block.consumes.getPower().capacity;
|
||||
if(block.consPower != null && block.consPower.buffered){
|
||||
power += this.power.status * block.consPower.capacity;
|
||||
}
|
||||
|
||||
if(block.hasLiquids && state.rules.damageExplosions){
|
||||
@@ -1397,14 +1397,14 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
public void displayConsumption(Table table){
|
||||
table.left();
|
||||
for(Consume cons : block.consumes.all){
|
||||
if(cons.isOptional() && cons.isBoost()) continue;
|
||||
for(Consume cons : block.consumers){
|
||||
if(cons.optional && cons.booster) continue;
|
||||
cons.build(self(), table);
|
||||
}
|
||||
}
|
||||
|
||||
public void displayBars(Table table){
|
||||
for(Func<Building, Bar> bar : block.bars.list()){
|
||||
for(Func<Building, Bar> bar : block.listBars()){
|
||||
table.add(bar.get(self())).growX();
|
||||
table.row();
|
||||
}
|
||||
@@ -1521,7 +1521,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
//TODO can lead to ghost graphs?
|
||||
power.graph = new PowerGraph();
|
||||
power.links.clear();
|
||||
if(block.consumes.hasPower() && !block.consumes.getPower().buffered){
|
||||
if(block.consPower != null && !block.consPower.buffered){
|
||||
power.status = 0f;
|
||||
}
|
||||
}
|
||||
@@ -1590,18 +1590,18 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
consOptionalValid = true;
|
||||
boolean docons = shouldConsume() && productionValid();
|
||||
|
||||
for(Consume cons : block.consumes.all){
|
||||
if(cons.isOptional()) continue;
|
||||
for(Consume cons : block.consumers){
|
||||
if(cons.optional) continue;
|
||||
|
||||
if(docons && cons.isUpdate() && prevValid && cons.valid(self())){
|
||||
if(docons && cons.update && prevValid && cons.valid(self())){
|
||||
cons.update(self());
|
||||
}
|
||||
|
||||
consValid &= cons.valid(self());
|
||||
}
|
||||
|
||||
for(Consume cons : block.consumes.optionals){
|
||||
if(docons && cons.isUpdate() && prevValid && cons.valid(self())){
|
||||
for(Consume cons : block.optionalConsumers){
|
||||
if(docons && cons.update && prevValid && cons.valid(self())){
|
||||
cons.update(self());
|
||||
}
|
||||
|
||||
@@ -1693,10 +1693,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
case totalItems -> items == null ? 0 : items.total();
|
||||
//TODO will give wildly fluctuating amounts due to switching of current() for multi-liquid blocks. totalLiquids is inherently bad design, but unfortunately it is useful for conduits/tanks
|
||||
case totalLiquids -> liquids == null ? 0 : liquids.currentAmount();
|
||||
case totalPower -> power == null || !block.consumes.hasPower() ? 0 : power.status * (block.consumes.getPower().buffered ? block.consumes.getPower().capacity : 1f);
|
||||
case totalPower -> power == null || block.consPower == null ? 0 : power.status * (block.consPower.buffered ? block.consPower.capacity : 1f);
|
||||
case itemCapacity -> block.hasItems ? block.itemCapacity : 0;
|
||||
case liquidCapacity -> block.hasLiquids ? block.liquidCapacity : 0;
|
||||
case powerCapacity -> block.consumes.hasPower() ? block.consumes.getPower().capacity : 0f;
|
||||
case powerCapacity -> block.consPower != null ? block.consPower.capacity : 0f;
|
||||
case powerNetIn -> power == null ? 0 : power.graph.getLastScaledPowerIn() * 60;
|
||||
case powerNetOut -> power == null ? 0 : power.graph.getLastScaledPowerOut() * 60;
|
||||
case powerNetStored -> power == null ? 0 : power.graph.getLastPowerStored();
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ai.formations.*;
|
||||
import mindustry.ai.types.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
/**
|
||||
* A unit that can command other units.
|
||||
* @deprecated This mechanic is likely to be removed or completely reworked in the future.
|
||||
* */
|
||||
@Deprecated
|
||||
@Component
|
||||
abstract class CommanderComp implements Entityc, Posc{
|
||||
private static final Seq<FormationMember> members = new Seq<>();
|
||||
private static final Seq<Unit> units = new Seq<>();
|
||||
|
||||
@Import float x, y, rotation, hitSize;
|
||||
@Import Team team;
|
||||
@Import UnitType type;
|
||||
|
||||
transient @Nullable Formation formation;
|
||||
transient Seq<Unit> controlling = new Seq<>(10);
|
||||
/** minimum speed of any unit in the formation. */
|
||||
transient float minFormationSpeed;
|
||||
|
||||
public void update(){
|
||||
if(controlling.isEmpty() && !Vars.net.client()){
|
||||
formation = null;
|
||||
}
|
||||
|
||||
if(formation != null){
|
||||
formation.anchor.set(x, y, 0);
|
||||
formation.updateSlots();
|
||||
controlling.removeAll(u -> u.dead || !(u.controller() instanceof FormationAI ai && ai.leader == self()));
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
clearCommand();
|
||||
}
|
||||
|
||||
public void killed(){
|
||||
clearCommand();
|
||||
}
|
||||
|
||||
//make sure to reset command state when the controller is switched
|
||||
public void controller(UnitController next){
|
||||
clearCommand();
|
||||
}
|
||||
|
||||
void commandNearby(FormationPattern pattern){
|
||||
commandNearby(pattern, u -> true);
|
||||
}
|
||||
|
||||
void commandNearby(FormationPattern pattern, Boolf<Unit> include){
|
||||
Formation formation = new Formation(new Vec3(x, y, rotation), pattern);
|
||||
formation.slotAssignmentStrategy = new DistanceAssignmentStrategy(pattern);
|
||||
|
||||
units.clear();
|
||||
|
||||
Units.nearby(team, x, y, type.commandRadius, u -> {
|
||||
if(u.isAI() && include.get(u) && u != self() && u.type.flying == type.flying && u.hitSize <= hitSize * 1.1f && u.type.playerControllable){
|
||||
units.add(u);
|
||||
}
|
||||
});
|
||||
|
||||
if(units.isEmpty()) return;
|
||||
|
||||
//sort by hitbox size, then by distance
|
||||
units.sort(Structs.comps(Structs.comparingFloat(u -> -u.hitSize), Structs.comparingFloat(u -> u.dst2(this))));
|
||||
units.truncate(type.commandLimit);
|
||||
|
||||
command(formation, units);
|
||||
}
|
||||
|
||||
void command(Formation formation, Seq<Unit> units){
|
||||
clearCommand();
|
||||
units.shuffle();
|
||||
|
||||
float spacing = hitSize * 0.9f;
|
||||
minFormationSpeed = type.speed;
|
||||
|
||||
controlling.addAll(units);
|
||||
for(Unit unit : units){
|
||||
FormationAI ai;
|
||||
unit.controller(ai = new FormationAI(self(), formation));
|
||||
spacing = Math.max(spacing, ai.formationSize());
|
||||
minFormationSpeed = Math.min(minFormationSpeed, unit.type.speed);
|
||||
}
|
||||
this.formation = formation;
|
||||
|
||||
//update formation spacing based on max size
|
||||
formation.pattern.spacing = spacing;
|
||||
|
||||
members.clear();
|
||||
for(Unitc u : units){
|
||||
members.add((FormationAI)u.controller());
|
||||
}
|
||||
|
||||
//TODO doesn't handle units that don't fit a formation
|
||||
formation.addMembers(members);
|
||||
}
|
||||
|
||||
boolean isCommanding(){
|
||||
return formation != null;
|
||||
}
|
||||
|
||||
void clearCommand(){
|
||||
//reset controlled units
|
||||
for(Unit unit : controlling){
|
||||
if(unit.controller().isBeingControlled(self())){
|
||||
unit.controller(unit.type.createController(unit));
|
||||
}
|
||||
}
|
||||
|
||||
controlling.clear();
|
||||
formation = null;
|
||||
}
|
||||
}
|
||||
@@ -124,12 +124,8 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
unit.aim(mouseX, mouseY);
|
||||
//this is only necessary when the thing being controlled isn't synced
|
||||
unit.controlWeapons(shooting, shooting);
|
||||
//save previous formation to prevent reset
|
||||
var formation = unit.formation;
|
||||
//extra precaution, necessary for non-synced things
|
||||
unit.controller(this);
|
||||
//keep previous formation
|
||||
unit.formation = formation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
@@ -32,10 +31,10 @@ import static mindustry.Vars.*;
|
||||
import static mindustry.logic.GlobalConstants.*;
|
||||
|
||||
@Component(base = true)
|
||||
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Commanderc, Displayable, Senseable, Ranged, Minerc, Builderc{
|
||||
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Displayable, Senseable, Ranged, Minerc, Builderc{
|
||||
|
||||
@Import boolean hovering, dead, disarmed;
|
||||
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo, minFormationSpeed, dragMultiplier;
|
||||
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health, ammo, dragMultiplier;
|
||||
@Import Team team;
|
||||
@Import int id;
|
||||
@Import @Nullable Tile mineTile;
|
||||
@@ -120,14 +119,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
public float speed(){
|
||||
float strafePenalty = isGrounded() || !isPlayer() ? 1f : Mathf.lerp(1f, type.strafePenalty, Angles.angleDist(vel().angle(), rotation) / 180f);
|
||||
float boost = Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation);
|
||||
//limit speed to minimum formation speed to preserve formation
|
||||
return (isCommanding() ? minFormationSpeed * 0.98f : type.speed) * strafePenalty * boost * floorSpeedMultiplier();
|
||||
}
|
||||
|
||||
/** Iterates through this unit and everything it is controlling. */
|
||||
public void eachGroup(Cons<Unit> cons){
|
||||
cons.get(self());
|
||||
controlling().each(cons);
|
||||
return type.speed * strafePenalty * boost * floorSpeedMultiplier();
|
||||
}
|
||||
|
||||
/** @return where the unit wants to look at. */
|
||||
@@ -185,9 +177,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
case controlled -> !isValid() ? 0 :
|
||||
controller instanceof LogicAI ? ctrlProcessor :
|
||||
controller instanceof Player ? ctrlPlayer :
|
||||
controller instanceof FormationAI ? ctrlFormation :
|
||||
0;
|
||||
case commanded -> controller instanceof FormationAI && isValid() ? 1 : 0;
|
||||
case payloadCount -> ((Object)this) instanceof Payloadc pay ? pay.payloads().size : 0;
|
||||
case size -> hitSize / tilesize;
|
||||
case color -> Color.toDoubleBits(team.color.r, team.color.g, team.color.b, 1f);
|
||||
@@ -201,7 +191,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
case type -> type;
|
||||
case name -> controller instanceof Player p ? p.name : null;
|
||||
case firstItem -> stack().amount == 0 ? null : item();
|
||||
case controller -> !isValid() ? null : controller instanceof LogicAI log ? log.controller : controller instanceof FormationAI form ? form.leader : this;
|
||||
case controller -> !isValid() ? null : controller instanceof LogicAI log ? log.controller : this;
|
||||
case payloadType -> ((Object)this) instanceof Payloadc pay ?
|
||||
(pay.payloads().isEmpty() ? null :
|
||||
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type :
|
||||
@@ -559,12 +549,11 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
remove();
|
||||
}
|
||||
|
||||
/** @return name of direct or indirect player controller. */
|
||||
/** @return name of direct or indirect player controller. TODO comamnd support*/
|
||||
@Override
|
||||
public @Nullable String getControllerName(){
|
||||
if(isPlayer()) return getPlayer().name;
|
||||
if(controller instanceof LogicAI ai && ai.controller != null) return ai.controller.lastAccessed;
|
||||
if(controller instanceof FormationAI ai && ai.leader != null && ai.leader.isPlayer()) return ai.leader.getPlayer().name;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user