Fog fixes / Weapon attack fixes / Avert weapon
This commit is contained in:
BIN
core/assets-raw/sprites/units/weapons/avert-weapon.png
Normal file
BIN
core/assets-raw/sprites/units/weapons/avert-weapon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
@@ -173,6 +173,6 @@ public class BuilderAI extends AIController{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldShoot(){
|
public boolean shouldShoot(){
|
||||||
return !unit.isBuilding();
|
return !unit.isBuilding() && unit.type.canAttack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3119,18 +3119,44 @@ public class UnitTypes{
|
|||||||
lowAltitude = false;
|
lowAltitude = false;
|
||||||
flying = true;
|
flying = true;
|
||||||
drag = 0.08f;
|
drag = 0.08f;
|
||||||
speed = 2.5f;
|
speed = 2f;
|
||||||
rotateSpeed = 5f;
|
rotateSpeed = 4f;
|
||||||
accel = 0.09f;
|
accel = 0.09f;
|
||||||
health = 600f;
|
health = 800f;
|
||||||
armor = 2f;
|
armor = 2f;
|
||||||
hitSize = 12f;
|
hitSize = 12f;
|
||||||
engineSize = 0;
|
engineSize = 0;
|
||||||
|
fogRadius = 25;
|
||||||
|
|
||||||
setEnginesMirror(
|
setEnginesMirror(
|
||||||
new UnitEngine(34 / 4f, 31 / 4f, 3f, 45f),
|
new UnitEngine(34 / 4f, 31 / 4f, 3f, 45f),
|
||||||
new UnitEngine(35 / 4f, -38 / 4f, 3f, 315f)
|
new UnitEngine(35 / 4f, -38 / 4f, 3f, 315f)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
weapons.add(new Weapon("avert-weapon"){{
|
||||||
|
reload = 35f;
|
||||||
|
x = 4f;
|
||||||
|
y = 6.25f;
|
||||||
|
shootY = 5.75f;
|
||||||
|
recoil = 1.5f;
|
||||||
|
top = false;
|
||||||
|
layerOffset = -0.01f;
|
||||||
|
rotate = false;
|
||||||
|
|
||||||
|
//TODO cooler + balancing
|
||||||
|
bullet = new BasicBulletType(5f, 15){{
|
||||||
|
width = 7f;
|
||||||
|
height = 12f;
|
||||||
|
lifetime = 25f;
|
||||||
|
shootEffect = Fx.sparkShoot;
|
||||||
|
smokeEffect = Fx.shootBigSmoke;
|
||||||
|
hitColor = backColor = trailColor = Pal.suppress;
|
||||||
|
frontColor = Color.white;
|
||||||
|
trailWidth = 1.5f;
|
||||||
|
trailLength = 5;
|
||||||
|
hitEffect = despawnEffect = Fx.hitBulletColor;
|
||||||
|
}};
|
||||||
|
}});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
quell = new ErekirUnitType("quell"){{
|
quell = new ErekirUnitType("quell"){{
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ public class AIController implements UnitController{
|
|||||||
float wrange = weapon.range();
|
float wrange = weapon.range();
|
||||||
|
|
||||||
//let uncontrollable weapons do their own thing
|
//let uncontrollable weapons do their own thing
|
||||||
if(!weapon.controllable) continue;
|
if(!weapon.controllable || weapon.noAttack) continue;
|
||||||
|
|
||||||
float mountX = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y),
|
float mountX = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y),
|
||||||
mountY = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y);
|
mountY = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public final class FogControl implements CustomChunk{
|
|||||||
private @Nullable Thread dynamicFogThread;
|
private @Nullable Thread dynamicFogThread;
|
||||||
|
|
||||||
private boolean justLoaded = false;
|
private boolean justLoaded = false;
|
||||||
|
private boolean loadedStatic = false;
|
||||||
|
|
||||||
public FogControl(){
|
public FogControl(){
|
||||||
Events.on(ResetEvent.class, e -> {
|
Events.on(ResetEvent.class, e -> {
|
||||||
@@ -44,19 +45,18 @@ public final class FogControl implements CustomChunk{
|
|||||||
Events.on(WorldLoadEvent.class, e -> {
|
Events.on(WorldLoadEvent.class, e -> {
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
|
loadedStatic = false;
|
||||||
justLoaded = true;
|
justLoaded = true;
|
||||||
ww = world.width();
|
ww = world.width();
|
||||||
wh = world.height();
|
wh = world.height();
|
||||||
|
|
||||||
//all old buildings have static light scheduled around them
|
//all old buildings have static light scheduled around them
|
||||||
if(state.rules.fog && state.rules.staticFog){
|
if(state.rules.fog && state.rules.staticFog){
|
||||||
synchronized(staticEvents){
|
pushStaticBlocks();
|
||||||
for(var build : Groups.build){
|
//force draw all static stuff immediately
|
||||||
if(build.block.flags.contains(BlockFlag.hasFogRadius)){
|
updateStatic();
|
||||||
staticEvents.add(FogEvent.get(build.tile.x, build.tile.y, Mathf.round(build.fogRadius()), build.team.id));
|
|
||||||
}
|
loadedStatic = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -133,6 +133,16 @@ public final class FogControl implements CustomChunk{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pushStaticBlocks(){
|
||||||
|
synchronized(staticEvents){
|
||||||
|
for(var build : Groups.build){
|
||||||
|
if(build.block.flags.contains(BlockFlag.hasFogRadius)){
|
||||||
|
pushEvent(FogEvent.get(build.tile.x, build.tile.y, Mathf.round(build.fogRadius()), build.team.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pushEvent(long event){
|
void pushEvent(long event){
|
||||||
if(!state.rules.staticFog) return;
|
if(!state.rules.staticFog) return;
|
||||||
|
|
||||||
@@ -159,6 +169,13 @@ public final class FogControl implements CustomChunk{
|
|||||||
fog = new FogData[256];
|
fog = new FogData[256];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//force update static
|
||||||
|
if(state.rules.staticFog && !loadedStatic){
|
||||||
|
pushStaticBlocks();
|
||||||
|
updateStatic();
|
||||||
|
loadedStatic = true;
|
||||||
|
}
|
||||||
|
|
||||||
//not run clientside, the CPU side isn't needed here.
|
//not run clientside, the CPU side isn't needed here.
|
||||||
if(staticFogThread == null && !net.client()){
|
if(staticFogThread == null && !net.client()){
|
||||||
staticFogThread = new StaticFogThread();
|
staticFogThread = new StaticFogThread();
|
||||||
@@ -271,25 +288,29 @@ public final class FogControl implements CustomChunk{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//I really don't like synchronizing here, but there should be *some* performance benefit at least
|
updateStatic();
|
||||||
synchronized(staticEvents){
|
|
||||||
int size = staticEvents.size;
|
|
||||||
for(int i = 0; i < size; i++){
|
|
||||||
long event = staticEvents.items[i];
|
|
||||||
int x = FogEvent.x(event), y = FogEvent.y(event), rad = FogEvent.radius(event), team = FogEvent.team(event);
|
|
||||||
var data = fog[team];
|
|
||||||
if(data != null){
|
|
||||||
circle(data.staticData, x, y, rad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
staticEvents.clear();
|
|
||||||
}
|
|
||||||
//ignore, don't want to crash this thread
|
//ignore, don't want to crash this thread
|
||||||
}catch(Exception e){}
|
}catch(Exception e){}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateStatic(){
|
||||||
|
//I really don't like synchronizing here, but there should be *some* performance benefit at least
|
||||||
|
synchronized(staticEvents){
|
||||||
|
int size = staticEvents.size;
|
||||||
|
for(int i = 0; i < size; i++){
|
||||||
|
long event = staticEvents.items[i];
|
||||||
|
int x = FogEvent.x(event), y = FogEvent.y(event), rad = FogEvent.radius(event), team = FogEvent.team(event);
|
||||||
|
var data = fog[team];
|
||||||
|
if(data != null){
|
||||||
|
circle(data.staticData, x, y, rad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
staticEvents.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class DynamicFogThread extends Thread{
|
class DynamicFogThread extends Thread{
|
||||||
final Bits cleared = new Bits();
|
final Bits cleared = new Bits();
|
||||||
|
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ public class UnitType extends UnlockableContent{
|
|||||||
/** If true, all weapons will attack the same target. */
|
/** If true, all weapons will attack the same target. */
|
||||||
public boolean singleTarget = false;
|
public boolean singleTarget = false;
|
||||||
public boolean forceMultiTarget = false;
|
public boolean forceMultiTarget = false;
|
||||||
|
/** If false, this unit has no weapons that can attack. */
|
||||||
|
public boolean canAttack = true;
|
||||||
public boolean hidden = false;
|
public boolean hidden = false;
|
||||||
public boolean internal = false;
|
public boolean internal = false;
|
||||||
/** Function used for calculating cost of moving with ControlPathfinder. Does not affect "normal" flow field pathfinding. */
|
/** Function used for calculating cost of moving with ControlPathfinder. Does not affect "normal" flow field pathfinding. */
|
||||||
@@ -464,7 +466,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(fogRadius < 0){
|
if(fogRadius < 0){
|
||||||
fogRadius = Math.max(lightRadius * 3.1f, 1f) / 8f;
|
fogRadius = Math.max(11f * 2.3f * 3f, hitSize * 2f) / 8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(weapons.isEmpty()){
|
if(weapons.isEmpty()){
|
||||||
@@ -529,6 +531,8 @@ public class UnitType extends UnlockableContent{
|
|||||||
|
|
||||||
weapons.each(Weapon::init);
|
weapons.each(Weapon::init);
|
||||||
|
|
||||||
|
canAttack = weapons.contains(w -> !w.noAttack);
|
||||||
|
|
||||||
//dynamically create ammo capacity based on firing rate
|
//dynamically create ammo capacity based on firing rate
|
||||||
if(ammoCapacity < 0){
|
if(ammoCapacity < 0){
|
||||||
float shotsPerSecond = weapons.sumf(w -> w.useAmmo ? 60f / w.reload : 0f);
|
float shotsPerSecond = weapons.sumf(w -> w.useAmmo ? 60f / w.reload : 0f);
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ public class Weapon implements Cloneable{
|
|||||||
public float soundPitchMin = 0.8f, soundPitchMax = 1f;
|
public float soundPitchMin = 0.8f, soundPitchMax = 1f;
|
||||||
/** whether shooter rotation is ignored when shooting. */
|
/** whether shooter rotation is ignored when shooting. */
|
||||||
public boolean ignoreRotation = false;
|
public boolean ignoreRotation = false;
|
||||||
|
/** If true, this weapon cannot be used to attack targets. */
|
||||||
|
public boolean noAttack = false;
|
||||||
/** min velocity required for this weapon to shoot */
|
/** min velocity required for this weapon to shoot */
|
||||||
public float minShootVelocity = -1f;
|
public float minShootVelocity = -1f;
|
||||||
/** should the shoot effects follow the unit (effects need followParent set to true for this to work) */
|
/** should the shoot effects follow the unit (effects need followParent set to true for this to work) */
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public class RepairBeamWeapon extends Weapon{
|
|||||||
useAmmo = false;
|
useAmmo = false;
|
||||||
mountType = HealBeamMount::new;
|
mountType = HealBeamMount::new;
|
||||||
recoil = 0f;
|
recoil = 0f;
|
||||||
|
noAttack = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user