Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -14,7 +14,7 @@ public class MissileAI extends AIController{
|
||||
|
||||
float time = unit instanceof TimedKillc t ? t.time() : 1000000f;
|
||||
|
||||
if(time >= unit.type.homingDelay && shooter != null){
|
||||
if(time >= unit.type.homingDelay && shooter != null && !shooter.dead()){
|
||||
unit.lookAt(shooter.aimX, shooter.aimY);
|
||||
}
|
||||
|
||||
|
||||
@@ -366,8 +366,8 @@ public class World{
|
||||
|
||||
if(!headless){
|
||||
if(state.teams.cores(checkRules.defaultTeam).size == 0 && !checkRules.pvp){
|
||||
ui.showErrorMessage(Core.bundle.format("map.nospawn", checkRules.defaultTeam.color, checkRules.defaultTeam.localized()));
|
||||
invalidMap = true;
|
||||
ui.showErrorMessage(Core.bundle.format("map.nospawn", checkRules.defaultTeam.coloredName()));
|
||||
}else if(checkRules.pvp){ //pvp maps need two cores to be valid
|
||||
if(state.teams.getActive().count(TeamData::hasCore) < 2){
|
||||
invalidMap = true;
|
||||
@@ -376,7 +376,7 @@ public class World{
|
||||
}else if(checkRules.attackMode){ //attack maps need two cores to be valid
|
||||
invalidMap = state.rules.waveTeam.data().noCores();
|
||||
if(invalidMap){
|
||||
ui.showErrorMessage(Core.bundle.format("map.nospawn.attack", checkRules.waveTeam.color, checkRules.waveTeam.localized()));
|
||||
ui.showErrorMessage(Core.bundle.format("map.nospawn.attack", checkRules.waveTeam.coloredName()));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
@@ -137,6 +137,16 @@ public class Damage{
|
||||
return found ? tmpBuilding : null;
|
||||
}
|
||||
|
||||
public static float findLength(Bullet b, float length, boolean laser, int pierceCap){
|
||||
if(pierceCap > 0){
|
||||
length = findPierceLength(b, pierceCap, laser, length);
|
||||
}else if(laser){
|
||||
length = findLaserLength(b, length);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
public static float findLaserLength(Bullet b, float length){
|
||||
vec.trnsExact(b.rotation(), length);
|
||||
|
||||
@@ -149,6 +159,10 @@ public class Damage{
|
||||
}
|
||||
|
||||
public static float findPierceLength(Bullet b, int pierceCap, float length){
|
||||
return findPierceLength(b, pierceCap, b.type.laserAbsorb, length);
|
||||
}
|
||||
|
||||
public static float findPierceLength(Bullet b, int pierceCap, boolean laser, float length){
|
||||
vec.trnsExact(b.rotation(), length);
|
||||
rect.setPosition(b.x, b.y).setSize(vec.x, vec.y).normalize().grow(3f);
|
||||
|
||||
@@ -163,7 +177,7 @@ public class Damage{
|
||||
if(build != null && build.team != b.team && build.collide(b) && b.checkUnderBuild(build, x * tilesize, y * tilesize)){
|
||||
distances.add(b.dst(build));
|
||||
|
||||
if(b.type.laserAbsorb && build.absorbLasers()){
|
||||
if(laser && build.absorbLasers()){
|
||||
maxDst = Math.min(maxDst, b.dst(build));
|
||||
return true;
|
||||
}
|
||||
@@ -189,7 +203,7 @@ public class Damage{
|
||||
|
||||
/** Collides a bullet with blocks in a laser, taking into account absorption blocks. Resulting length is stored in the bullet's fdata. */
|
||||
public static float collideLaser(Bullet b, float length, boolean large, boolean laser, int pierceCap){
|
||||
float resultLength = findPierceLength(b, pierceCap, length);
|
||||
float resultLength = findPierceLength(b, pierceCap, laser, length);
|
||||
|
||||
collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), resultLength, large, laser, pierceCap);
|
||||
|
||||
@@ -223,11 +237,7 @@ public class Damage{
|
||||
* Only enemies of the specified team are damaged.
|
||||
*/
|
||||
public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large, boolean laser, int pierceCap){
|
||||
if(laser){
|
||||
length = findLaserLength(hitter, length);
|
||||
}else if(pierceCap > 0){
|
||||
length = findPierceLength(hitter, pierceCap, length);
|
||||
}
|
||||
length = findLength(hitter, length, laser, pierceCap);
|
||||
|
||||
collidedBlocks.clear();
|
||||
vec.trnsExact(angle, length);
|
||||
|
||||
@@ -554,7 +554,7 @@ public class BulletType extends Content implements Cloneable{
|
||||
|
||||
public void init(Bullet b){
|
||||
|
||||
if(killShooter && b.owner() instanceof Healthc h){
|
||||
if(killShooter && b.owner() instanceof Healthc h && !h.dead()){
|
||||
h.kill();
|
||||
}
|
||||
|
||||
@@ -726,6 +726,10 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
|
||||
public @Nullable Bullet create(@Nullable Entityc owner, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data, @Nullable Mover mover, float aimX, float aimY){
|
||||
return create(owner, owner, team, x, y, angle, damage, velocityScl, lifetimeScl, data, mover, aimX, aimY);
|
||||
}
|
||||
|
||||
public @Nullable Bullet create(@Nullable Entityc owner, @Nullable Entityc shooter, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data, @Nullable Mover mover, float aimX, float aimY){
|
||||
if(spawnUnit != null){
|
||||
//don't spawn units clientside!
|
||||
if(!net.client()){
|
||||
@@ -738,17 +742,19 @@ public class BulletType extends Content implements Cloneable{
|
||||
}
|
||||
//assign unit owner
|
||||
if(spawned.controller() instanceof MissileAI ai){
|
||||
if(owner instanceof Unit unit){
|
||||
if(shooter instanceof Unit unit){
|
||||
ai.shooter = unit;
|
||||
}
|
||||
|
||||
if(owner instanceof ControlBlock control){
|
||||
if(shooter instanceof ControlBlock control){
|
||||
ai.shooter = control.unit();
|
||||
}
|
||||
|
||||
}
|
||||
spawned.add();
|
||||
}
|
||||
//Since bullet init is never called, handle killing shooter here
|
||||
if(killShooter && owner instanceof Healthc h && !h.dead()) h.kill();
|
||||
|
||||
//no bullet returned
|
||||
return null;
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ContinuousFlameBulletType extends ContinuousBulletType{
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
float mult = b.fin(lengthInterp);
|
||||
float realLength = (pierceCap <= 0 ? length : Damage.findPierceLength(b, pierceCap, length)) * mult;
|
||||
float realLength = Damage.findLength(b, length * mult, laserAbsorb, pierceCap);
|
||||
|
||||
float sin = Mathf.sin(Time.time, oscScl, oscMag);
|
||||
|
||||
|
||||
@@ -41,9 +41,8 @@ public class ContinuousLaserBulletType extends ContinuousBulletType{
|
||||
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
float realLength = Damage.findLaserLength(b, length);
|
||||
float fout = Mathf.clamp(b.time > b.lifetime - fadeTime ? 1f - (b.time - (lifetime - fadeTime)) / fadeTime : 1f);
|
||||
float baseLen = realLength * fout;
|
||||
float realLength = Damage.findLength(b, length * fout, laserAbsorb, pierceCap);
|
||||
float rot = b.rotation();
|
||||
|
||||
for(int i = 0; i < colors.length; i++){
|
||||
@@ -55,17 +54,17 @@ public class ContinuousLaserBulletType extends ContinuousBulletType{
|
||||
float ellipseLenScl = Mathf.lerp(1 - i / (float)(colors.length), 1f, pointyScaling);
|
||||
|
||||
Lines.stroke(stroke);
|
||||
Lines.lineAngle(b.x, b.y, rot, baseLen - frontLength, false);
|
||||
Lines.lineAngle(b.x, b.y, rot, realLength - frontLength, false);
|
||||
|
||||
//back ellipse
|
||||
Drawf.flameFront(b.x, b.y, divisions, rot + 180f, backLength, stroke / 2f);
|
||||
|
||||
//front ellipse
|
||||
Tmp.v1.trnsExact(rot, baseLen - frontLength);
|
||||
Tmp.v1.trnsExact(rot, realLength - frontLength);
|
||||
Drawf.flameFront(b.x + Tmp.v1.x, b.y + Tmp.v1.y, divisions, rot, frontLength * ellipseLenScl, stroke / 2f);
|
||||
}
|
||||
|
||||
Tmp.v1.trns(b.rotation(), baseLen * 1.1f);
|
||||
Tmp.v1.trns(b.rotation(), realLength * 1.1f);
|
||||
|
||||
Drawf.light(b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, lightStroke, lightColor, 0.7f);
|
||||
Draw.reset();
|
||||
@@ -76,4 +75,9 @@ public class ContinuousLaserBulletType extends ContinuousBulletType{
|
||||
//no light drawn here
|
||||
}
|
||||
|
||||
@Override
|
||||
public float currentLength(Bullet b){
|
||||
float fout = Mathf.clamp(b.time > b.lifetime - fadeTime ? 1f - (b.time - (lifetime - fadeTime)) / fadeTime : 1f);
|
||||
return length * fout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,10 @@ public class Team implements Comparable<Team>{
|
||||
public String localized(){
|
||||
return Core.bundle.get("team." + name + ".name", name);
|
||||
}
|
||||
|
||||
public String coloredName(){
|
||||
return emoji + "[#" + color + "]" + localized() + "[]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Team team){
|
||||
|
||||
@@ -10,6 +10,7 @@ import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.ai.types.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.audio.*;
|
||||
import mindustry.content.*;
|
||||
@@ -458,7 +459,8 @@ public class Weapon implements Cloneable{
|
||||
lifeScl = bullet.scaleLife ? Mathf.clamp(Mathf.dst(bulletX, bulletY, mount.aimX, mount.aimY) / bullet.range) : 1f,
|
||||
angle = angleOffset + shootAngle + Mathf.range(inaccuracy + bullet.inaccuracy);
|
||||
|
||||
mount.bullet = bullet.create(unit, unit.team, bulletX, bulletY, angle, -1f, (1f - velocityRnd) + Mathf.random(velocityRnd), lifeScl, null, mover, mount.aimX, mount.aimY);
|
||||
Entityc shooter = unit.controller() instanceof MissileAI ai ? ai.shooter : unit; //Pass the missile's shooter down to its bullets
|
||||
mount.bullet = bullet.create(unit, shooter, unit.team, bulletX, bulletY, angle, -1f, (1f - velocityRnd) + Mathf.random(velocityRnd), lifeScl, null, mover, mount.aimX, mount.aimY);
|
||||
handleBullet(unit, mount, mount.bullet);
|
||||
|
||||
if(!continuous){
|
||||
|
||||
@@ -201,7 +201,6 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
number("@rules.unitcostmultiplier", f -> rules.unitCostMultiplier = f, () -> rules.unitCostMultiplier);
|
||||
number("@rules.unithealthmultiplier", f -> rules.unitHealthMultiplier = f, () -> rules.unitHealthMultiplier);
|
||||
|
||||
|
||||
main.button("@bannedunits", () -> showBanned("@bannedunits", ContentType.unit, rules.bannedUnits, u -> !u.isHidden())).left().width(300f).row();
|
||||
check("@bannedunits.whitelist", b -> rules.unitWhitelist = b, () -> rules.unitWhitelist);
|
||||
|
||||
@@ -280,7 +279,7 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
boolean[] shown = {false};
|
||||
Table wasMain = main;
|
||||
|
||||
main.button("[#" + team.color + "]" + team.localized() + (team.emoji.isEmpty() ? "" : "[] " + team.emoji), Icon.downOpen, Styles.togglet, () -> {
|
||||
main.button(team.coloredName(), Icon.downOpen, Styles.togglet, () -> {
|
||||
shown[0] = !shown[0];
|
||||
}).marginLeft(14f).width(260f).height(55f).update(t -> {
|
||||
((Image)t.getChildren().get(1)).setDrawable(shown[0] ? Icon.upOpen : Icon.downOpen);
|
||||
@@ -300,8 +299,8 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
numberi("@rules.rtsmaxsquadsize", f -> teams.rtsMaxSquad = f, () -> teams.rtsMaxSquad, () -> teams.rtsAi, 1, 1000);
|
||||
number("@rules.rtsminattackweight", f -> teams.rtsMinWeight = f, () -> teams.rtsMinWeight, () -> teams.rtsAi);
|
||||
|
||||
check("@rules.buildai", b -> teams.buildAi = b, () -> teams.buildAi, () -> team != rules.defaultTeam && rules.env != Planets.erekir.defaultEnv && !rules.pvp);
|
||||
//disallow on Erekir (this is broken for mods I'm sure, but whatever)
|
||||
check("@rules.buildai", b -> teams.buildAi = b, () -> teams.buildAi, () -> team != rules.defaultTeam && rules.env != Planets.erekir.defaultEnv && !rules.pvp);
|
||||
number("@rules.buildaitier", false, f -> teams.buildAiTier = f, () -> teams.buildAiTier, () -> teams.buildAi && rules.env != Planets.erekir.defaultEnv && !rules.pvp, 0, 1);
|
||||
|
||||
check("@rules.infiniteresources", b -> teams.infiniteResources = b, () -> teams.infiniteResources);
|
||||
@@ -313,7 +312,6 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
number("@rules.unitcostmultiplier", f -> teams.unitCostMultiplier = f, () -> teams.unitCostMultiplier);
|
||||
number("@rules.unithealthmultiplier", f -> teams.unitHealthMultiplier = f, () -> teams.unitHealthMultiplier);
|
||||
|
||||
|
||||
main = wasMain;
|
||||
}, () -> shown[0]).growX().row();
|
||||
}
|
||||
@@ -327,7 +325,7 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
for(Team team : Team.baseTeams){
|
||||
t.button(Tex.whiteui, Styles.squareTogglei, 38f, () -> {
|
||||
cons.get(team);
|
||||
}).pad(1f).checked(b -> prov.get() == team).size(60f).tooltip(team.localized()).with(i -> i.getStyle().imageUpColor = team.color);
|
||||
}).pad(1f).checked(b -> prov.get() == team).size(60f).tooltip(team.coloredName()).with(i -> i.getStyle().imageUpColor = team.color);
|
||||
}
|
||||
}).padTop(0).row();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class GameOverDialog extends BaseDialog{
|
||||
|
||||
cont.table(t -> {
|
||||
if(state.rules.pvp && winner != null){
|
||||
t.add(Core.bundle.format("gameover.pvp", winner.localized())).center().pad(6);
|
||||
t.add(Core.bundle.format("gameover.pvp", winner.coloredName())).center().pad(6);
|
||||
}else{
|
||||
t.add(state.isCampaign() ? Core.bundle.format("sector.lost", state.getSector().name()) : "@gameover").center().pad(6);
|
||||
}
|
||||
|
||||
@@ -593,11 +593,6 @@ public class CoreBlock extends StorageBlock{
|
||||
|
||||
state.teams.unregisterCore(this);
|
||||
|
||||
int max = itemCapacity * state.teams.cores(team).size;
|
||||
for(Item item : content.items()){
|
||||
items.set(item, Math.min(items.get(item), max));
|
||||
}
|
||||
|
||||
for(CoreBuild other : state.teams.cores(team)){
|
||||
other.onProximityUpdate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user