mirror of
https://github.com/Anuken/Mindustry.git
synced 2024-09-22 05:47:44 +03:00
Added new wave spawning system
This commit is contained in:
parent
c89123b18a
commit
e799187aaf
@ -7,7 +7,7 @@
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.Player" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.units.BaseUnit" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Map" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.EnemySpawn" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.SpawnGroup" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.core.GameState" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.EventType" />
|
||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.SaveFileVersion" />
|
||||
|
@ -72,6 +72,8 @@ public class Vars{
|
||||
//whether to show block debug
|
||||
public static boolean showBlockDebug = false;
|
||||
|
||||
public static boolean showFog = true;
|
||||
|
||||
public static final int maxTextLength = 150;
|
||||
public static final int maxNameLength = 40;
|
||||
public static final int maxCharNameLength = 20;
|
||||
|
@ -2,12 +2,12 @@ package io.anuke.mindustry.ai;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Bits;
|
||||
import io.anuke.mindustry.content.AmmoTypes;
|
||||
import io.anuke.mindustry.content.UnitTypes;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.entities.units.Squad;
|
||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||
import io.anuke.mindustry.game.SpawnGroup;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.WaveCreator;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
@ -23,6 +23,8 @@ public class WaveSpawner {
|
||||
|
||||
private Bits quadrants;
|
||||
|
||||
private Array<SpawnGroup> groups;
|
||||
|
||||
private Array<FlyerSpawn> flySpawns = new Array<>();
|
||||
private Array<GroundSpawn> groundSpawns = new Array<>();
|
||||
|
||||
@ -62,11 +64,20 @@ public class WaveSpawner {
|
||||
}
|
||||
|
||||
public void spawnEnemies(){
|
||||
int spawned = Math.min(state.wave, 6);
|
||||
int groundGroups = 1 + state.wave / 20;
|
||||
int flyGroups = state.wave / 20;
|
||||
int flyGroups = 0;
|
||||
int groundGroups = 0;
|
||||
|
||||
//add extra groups if necessary
|
||||
//count total subgroups spawned by flying/group types
|
||||
for(SpawnGroup group : groups){
|
||||
int amount = group.getGroupsSpawned(state.wave);
|
||||
if(group.type.isFlying){
|
||||
flyGroups += amount;
|
||||
}else{
|
||||
groundGroups += amount;
|
||||
}
|
||||
}
|
||||
|
||||
//add extra groups if the total exceeds it
|
||||
for (int i = 0; i < groundGroups - groundSpawns.size; i++) {
|
||||
GroundSpawn spawn = new GroundSpawn();
|
||||
findLocation(spawn);
|
||||
@ -79,45 +90,49 @@ public class WaveSpawner {
|
||||
flySpawns.add(spawn);
|
||||
}
|
||||
|
||||
if(state.wave % 20 == 0){
|
||||
for(FlyerSpawn spawn : flySpawns) findLocation(spawn);
|
||||
for(GroundSpawn spawn : groundSpawns) findLocation(spawn);
|
||||
}
|
||||
//store index of last used fly/ground spawn locations
|
||||
int flyCount = 0, groundCount = 0;
|
||||
|
||||
for(GroundSpawn spawn : groundSpawns){
|
||||
checkQuadrant(spawn.x, spawn.y);
|
||||
if(!getQuad(spawn.x, spawn.y)){
|
||||
findLocation(spawn);
|
||||
}
|
||||
for(SpawnGroup group : groups){
|
||||
int groups = group.getGroupsSpawned(state.wave);
|
||||
int spawned = group.getUnitsSpawned(state.wave);
|
||||
|
||||
Squad squad = new Squad();
|
||||
for (int i = 0; i < groups; i++) {
|
||||
Squad squad = new Squad();
|
||||
float spawnX, spawnY;
|
||||
float spread;
|
||||
|
||||
for(int i = 0; i < spawned; i ++){
|
||||
BaseUnit unit = UnitTypes.scout.create(Team.red);
|
||||
unit.inventory.addAmmo(AmmoTypes.bulletLead);
|
||||
unit.setWave();
|
||||
unit.setSquad(squad);
|
||||
unit.set(spawn.x * quadsize * tilesize + quadsize * tilesize/2f + Mathf.range(quadsize*tilesize/3f),
|
||||
spawn.y * quadsize * tilesize + quadsize * tilesize/2f + Mathf.range(quadsize*tilesize/3));
|
||||
unit.add();
|
||||
}
|
||||
}
|
||||
if(group.type.isFlying){
|
||||
FlyerSpawn spawn = flySpawns.get(flyCount);
|
||||
//TODO verify flyer spawn
|
||||
|
||||
for(FlyerSpawn spawn : flySpawns){
|
||||
Squad squad = new Squad();
|
||||
float addition = 40f;
|
||||
float spread = addition / 1.5f;
|
||||
float margin = 40f; //how far away from the edge flying units spawn
|
||||
spawnX = world.width() *tilesize/2f + Mathf.sqrwavex(spawn.angle) * (world.width()/2f*tilesize + margin);
|
||||
spawnY = world.height() * tilesize/2f + Mathf.sqrwavey(spawn.angle) * (world.height()/2f*tilesize + margin);
|
||||
spread = margin / 1.5f;
|
||||
|
||||
float baseX = world.width() *tilesize/2f + Mathf.sqrwavex(spawn.angle) * (world.width()/2f*tilesize + addition),
|
||||
baseY = world.height() * tilesize/2f + Mathf.sqrwavey(spawn.angle) * (world.height()/2f*tilesize + addition);
|
||||
flyCount ++;
|
||||
}else{
|
||||
GroundSpawn spawn = groundSpawns.get(groundCount);
|
||||
checkQuadrant(spawn.x, spawn.y);
|
||||
if(!getQuad(spawn.x, spawn.y)){
|
||||
findLocation(spawn);
|
||||
}
|
||||
|
||||
for(int i = 0; i < spawned; i ++){
|
||||
BaseUnit unit = UnitTypes.vtol.create(Team.red);
|
||||
unit.inventory.addAmmo(AmmoTypes.bulletLead);
|
||||
unit.setWave();
|
||||
unit.setSquad(squad);
|
||||
unit.set(baseX + Mathf.range(spread), baseY + Mathf.range(spread));
|
||||
unit.add();
|
||||
spawnX = spawn.x * quadsize * tilesize + quadsize * tilesize/2f;
|
||||
spawnY = spawn.y * quadsize * tilesize + quadsize * tilesize/2f;
|
||||
spread = quadsize*tilesize/3f;
|
||||
|
||||
groundCount ++;
|
||||
}
|
||||
|
||||
for (int j = 0; j < spawned; j++) {
|
||||
BaseUnit unit = group.createUnit(Team.red);
|
||||
unit.setWave();
|
||||
unit.setSquad(squad);
|
||||
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
||||
unit.add();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,6 +165,10 @@ public class WaveSpawner {
|
||||
flySpawns.clear();
|
||||
groundSpawns.clear();
|
||||
quadrants = new Bits(quadWidth() * quadHeight());
|
||||
|
||||
if(groups == null){
|
||||
groups = WaveCreator.getSpawns();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getQuad(int quadx, int quady){
|
||||
@ -164,6 +183,7 @@ public class WaveSpawner {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO instead of randomly scattering locations around the map, find spawns close to each other
|
||||
private void findLocation(GroundSpawn spawn){
|
||||
spawn.x = -1;
|
||||
spawn.y = -1;
|
||||
@ -182,6 +202,7 @@ public class WaveSpawner {
|
||||
});
|
||||
}
|
||||
|
||||
//TODO instead of randomly scattering locations around the map, find spawns close to each other
|
||||
private void findLocation(FlyerSpawn spawn){
|
||||
spawn.angle = Mathf.random(360f);
|
||||
}
|
||||
@ -197,18 +218,10 @@ public class WaveSpawner {
|
||||
private class FlyerSpawn{
|
||||
//square angle
|
||||
float angle;
|
||||
|
||||
FlyerSpawn(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class GroundSpawn{
|
||||
//quadrant spawn coordinates
|
||||
int x, y;
|
||||
|
||||
GroundSpawn(){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ public class StatusEffects implements ContentList {
|
||||
if (Mathf.chance(Timers.delta() * 0.2f)) {
|
||||
Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class Weapons implements ContentList {
|
||||
ejectEffect = Fx.none;
|
||||
velocityRnd = 1f;
|
||||
inaccuracy = 40f;
|
||||
setAmmo(AmmoTypes.bombExplosive);
|
||||
setAmmo(AmmoTypes.bombExplosive, AmmoTypes.bombIncendiary);
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,13 @@ public class WeaponBullets extends BulletList {
|
||||
}
|
||||
};
|
||||
|
||||
bombIncendiary = new BombBulletType(20f, 20f, "shell"){
|
||||
bombIncendiary = new BombBulletType(15f, 10f, "shell"){
|
||||
{
|
||||
bulletWidth = 9f;
|
||||
bulletHeight = 13f;
|
||||
bulletWidth = 8f;
|
||||
bulletHeight = 12f;
|
||||
hiteffect = BulletFx.flakExplosion;
|
||||
backColor = Palette.darkFlame;
|
||||
frontColor = Palette.lightFlame;
|
||||
backColor = Palette.lightOrange;
|
||||
frontColor = Palette.lightishOrange;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,7 +247,9 @@ public class Renderer extends RendererModule{
|
||||
|
||||
batch.end();
|
||||
|
||||
fog.draw();
|
||||
if(showFog){
|
||||
fog.draw();
|
||||
}
|
||||
}
|
||||
|
||||
private void drawAllTeams(boolean flying){
|
||||
|
@ -169,7 +169,8 @@ public class Damage {
|
||||
|
||||
private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){
|
||||
float dist = Vector2.dst(x, y, tx, ty);
|
||||
float scaled = 1f - dist/radius;
|
||||
float falloff = 0.4f;
|
||||
float scaled = Mathf.lerp(1f - dist/radius, 1f, falloff);
|
||||
return damage * scaled;
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +228,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
float explosiveness = 2f + (player.inventory.hasItem() ? player.inventory.getItem().item.explosiveness * player.inventory.getItem().amount : 0f);
|
||||
float flammability = (player.inventory.hasItem() ? player.inventory.getItem().item.flammability * player.inventory.getItem().amount : 0f);
|
||||
Damage.dynamicExplosion(player.x, player.y, flammability, explosiveness, 0f, player.getSize()/2f, Palette.darkFlame);
|
||||
|
||||
ScorchDecal.create(player.x, player.y);
|
||||
Effects.sound("die", player);
|
||||
player.onDeath();
|
||||
@ -471,7 +472,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
|
||||
if(ui.chatfrag.chatOpen()) return;
|
||||
|
||||
float speed = isBoosting && !mech.flying ? mech.boostSpeed : mech.speed;
|
||||
float speed = isBoosting && !mech.flying ? debug ? 5f : mech.boostSpeed : mech.speed;
|
||||
//fraction of speed when at max load
|
||||
float carrySlowdown = 0.7f;
|
||||
|
||||
|
@ -6,6 +6,7 @@ import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||
import io.anuke.mindustry.entities.Damage;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
@ -15,9 +16,11 @@ import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
||||
import io.anuke.mindustry.gen.CallEntity;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Weapon;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.units.UnitFactory.UnitFactoryEntity;
|
||||
@ -25,9 +28,8 @@ import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.util.*;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -149,6 +151,23 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void drawItems(){
|
||||
float backTrns = 4f, itemSize = 5f;
|
||||
if(inventory.hasItem()){
|
||||
ItemStack stack = inventory.getItem();
|
||||
int stored = Mathf.clamp(stack.amount / 6, 1, 8);
|
||||
|
||||
for(int i = 0; i < stored; i ++) {
|
||||
float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 60f);
|
||||
float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 3, 1f) - 1f;
|
||||
Draw.rect(stack.item.region,
|
||||
x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT),
|
||||
y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT),
|
||||
itemSize, itemSize, rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timer getTimer() {
|
||||
return timer;
|
||||
@ -354,9 +373,14 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
public static void onUnitDeath(BaseUnit unit){
|
||||
if(unit == null) return;
|
||||
|
||||
unit.onSuperDeath();
|
||||
UnitDrops.dropItems(unit);
|
||||
|
||||
float explosiveness = 2f + (unit.inventory.hasItem() ? unit.inventory.getItem().item.explosiveness * unit.inventory.getItem().amount : 0f);
|
||||
float flammability = (unit.inventory.hasItem() ? unit.inventory.getItem().item.flammability * unit.inventory.getItem().amount : 0f);
|
||||
Damage.dynamicExplosion(unit.x, unit.y, flammability, explosiveness, 0f, unit.getSize()/2f, Palette.darkFlame);
|
||||
|
||||
unit.onSuperDeath();
|
||||
|
||||
ScorchDecal.create(unit.x, unit.y);
|
||||
Effects.effect(ExplosionFx.explosion, unit);
|
||||
Effects.shake(2f, 2f, unit);
|
||||
|
@ -9,7 +9,6 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Trail;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.type.AmmoType;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
@ -66,20 +65,7 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{
|
||||
|
||||
Draw.rect(type.name, x, y, rotation - 90);
|
||||
|
||||
float backTrns = 4f, itemSize = 5f;
|
||||
if(inventory.hasItem()){
|
||||
ItemStack stack = inventory.getItem();
|
||||
int stored = Mathf.clamp(stack.amount / 6, 1, 8);
|
||||
|
||||
for(int i = 0; i < stored; i ++) {
|
||||
float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 60f);
|
||||
float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 3, 1f) - 1f;
|
||||
Draw.rect(stack.item.region,
|
||||
x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT),
|
||||
y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT),
|
||||
itemSize, itemSize, rotation);
|
||||
}
|
||||
}
|
||||
drawItems();
|
||||
|
||||
Draw.alpha(1f);
|
||||
}
|
||||
|
@ -28,9 +28,6 @@ import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public abstract class GroundUnit extends BaseUnit {
|
||||
protected static Translator vec = new Translator();
|
||||
protected static float maxAim = 30f;
|
||||
|
||||
protected static final int timerReloadAlt = timerIndex++;
|
||||
|
||||
protected float walkTime;
|
||||
protected float baseRotation;
|
||||
@ -53,7 +50,9 @@ public abstract class GroundUnit extends BaseUnit {
|
||||
|
||||
@Override
|
||||
public void move(float x, float y){
|
||||
baseRotation = Mathf.slerpDelta(baseRotation, Mathf.atan2(x, y), type.baseRotateSpeed);
|
||||
if(Mathf.dst(x, y) > 0.01f){
|
||||
baseRotation = Mathf.slerpDelta(baseRotation, Mathf.atan2(x, y), type.baseRotateSpeed);
|
||||
}
|
||||
super.move(x, y);
|
||||
}
|
||||
|
||||
@ -66,7 +65,7 @@ public abstract class GroundUnit extends BaseUnit {
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
if(!velocity.isZero(0.001f) && (target == null || !inventory.hasAmmo() || (inventory.hasAmmo() && distanceTo(target) > inventory.getAmmoRange()))){
|
||||
if(!velocity.isZero(0.0001f) && (target == null || !inventory.hasAmmo() || (inventory.hasAmmo() && distanceTo(target) > inventory.getAmmoRange()))){
|
||||
rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.2f);
|
||||
}
|
||||
}
|
||||
@ -115,6 +114,8 @@ public abstract class GroundUnit extends BaseUnit {
|
||||
y + Angles.trnsy(tra, type.weaponOffsetX * i, trY), w, 12, rotation - 90);
|
||||
}
|
||||
|
||||
drawItems();
|
||||
|
||||
Draw.alpha(1f);
|
||||
}
|
||||
|
||||
|
@ -1,47 +0,0 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.state;
|
||||
|
||||
public class EnemySpawn{
|
||||
/**The enemy type spawned*/
|
||||
public final UnitType type;
|
||||
/**When this spawns should end*/
|
||||
protected int before = Integer.MAX_VALUE;
|
||||
/**When this spawns should start*/
|
||||
protected int after;
|
||||
/**The spacing, in waves, of spawns. 2 = spawns every other wave*/
|
||||
protected int spacing = 1;
|
||||
/**How many waves need to pass after the start of this spawn for the tier to increase by one*/
|
||||
protected int tierscale = 17;
|
||||
/**How many more enemies there are, every time the tier increases*/
|
||||
protected int tierscaleback = 0;
|
||||
/**The tier this spawn starts at.*/
|
||||
protected int tier = 1;
|
||||
/**Maximum amount of enemies that spawn*/
|
||||
protected int max = 60;
|
||||
/**How many waves need to pass before the amount of enemies increases by 1*/
|
||||
protected float scaling = 9999f;
|
||||
/**Amount of enemies spawned initially, with no scaling*/
|
||||
protected int amount = 1;
|
||||
|
||||
public EnemySpawn(UnitType type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
//TODO
|
||||
public int evaluate(int wave, int lane){
|
||||
if(wave < after || wave > before || (wave - after) % spacing != 0){
|
||||
return 0;
|
||||
}
|
||||
float scaling = this.scaling * state.difficulty.enemyScaling;
|
||||
|
||||
return Math.min(amount-1 + Math.max((int)((wave / spacing) / scaling), 1) + (tier(wave, lane)-1) * tierscaleback, max);
|
||||
}
|
||||
|
||||
public int tier(int wave, int lane){
|
||||
return Mathf.clamp(tier + (wave-after)/tierscale, 1, 5);
|
||||
}
|
||||
}
|
93
core/src/io/anuke/mindustry/game/SpawnGroup.java
Normal file
93
core/src/io/anuke/mindustry/game/SpawnGroup.java
Normal file
@ -0,0 +1,93 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.entities.units.GroundUnit;
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.StatusEffect;
|
||||
import io.anuke.mindustry.type.Weapon;
|
||||
|
||||
import static io.anuke.mindustry.Vars.state;
|
||||
|
||||
/**A spawn group defines spawn information for a specific type of unit, with optional extra information like
|
||||
* weapon equipped, ammo used, and status effects.
|
||||
* Each spawn group can have multiple sub-groups spawned in different areas of the map.*/
|
||||
public class SpawnGroup {
|
||||
/**The unit type spawned*/
|
||||
public final UnitType type;
|
||||
/**When this spawn should end*/
|
||||
protected int end = Integer.MAX_VALUE;
|
||||
/**When this spawn should start*/
|
||||
protected int begin;
|
||||
/**The spacing, in waves, of spawns. For example, 2 = spawns every other wave*/
|
||||
protected int spacing = 1;
|
||||
/**Maximum amount of units that spawn*/
|
||||
protected int max = 60;
|
||||
/**How many waves need to pass before the amount of units spawned increases by 1*/
|
||||
protected float unitScaling = 9999f;
|
||||
/**How many waves need to pass before the amount of instances of this group increases by 1*/
|
||||
protected float groupScaling = 9999f;
|
||||
/**Amount of enemies spawned initially, with no scaling*/
|
||||
protected int unitAmount = 1;
|
||||
/**Amount of enemies spawned initially, with no scaling*/
|
||||
protected int groupAmount = 1;
|
||||
/**Weapon used by the spawned unit. Null to disable. Only applicable to ground units.*/
|
||||
protected Weapon weapon;
|
||||
/**Status effect applied to the spawned unit. Null to disable.*/
|
||||
protected StatusEffect effect;
|
||||
/**Items this unit spawns with. Null to disable.*/
|
||||
protected ItemStack items;
|
||||
/**Ammo type this unit spawns with. Null to use the first available ammo.*/
|
||||
protected Item ammoItem;
|
||||
|
||||
public SpawnGroup(UnitType type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**Returns the amount of units spawned on a specific wave.*/
|
||||
public int getUnitsSpawned(int wave){
|
||||
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
|
||||
return 0;
|
||||
}
|
||||
float scaling = this.unitScaling * state.difficulty.enemyScaling;
|
||||
|
||||
return Math.min(unitAmount-1 + Math.max((int)((wave / spacing) / scaling), 1), max);
|
||||
}
|
||||
|
||||
/**Returns the amount of different unit groups at a specific wave.*/
|
||||
public int getGroupsSpawned(int wave){
|
||||
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
|
||||
return 0;
|
||||
}
|
||||
float scaling = this.groupScaling;
|
||||
|
||||
return Math.min(groupAmount-1 + Math.max((int)((wave / spacing) / groupScaling), 1), max);
|
||||
}
|
||||
|
||||
/**Creates a unit, and assigns correct values based on this group's data.
|
||||
* This method does not add() the unit.*/
|
||||
public BaseUnit createUnit(Team team){
|
||||
BaseUnit unit = type.create(team);
|
||||
|
||||
if(unit instanceof GroundUnit && weapon != null){
|
||||
((GroundUnit) unit).setWeapon(weapon);
|
||||
}
|
||||
|
||||
if(effect != null){
|
||||
unit.applyEffect(effect, 1f);
|
||||
}
|
||||
|
||||
if(items != null){
|
||||
unit.inventory.addItem(items.item, items.amount);
|
||||
}
|
||||
|
||||
if(ammoItem != null){
|
||||
unit.inventory.addAmmo(unit.getWeapon().getAmmoType(ammoItem));
|
||||
}else{
|
||||
unit.inventory.addAmmo(unit.getWeapon().getAmmoType(unit.getWeapon().getAcceptedItems().iterator().next()));
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
||||
}
|
@ -1,26 +1,48 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.content.Items;
|
||||
import io.anuke.mindustry.content.UnitTypes;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
|
||||
public class WaveCreator{
|
||||
|
||||
public static Array<EnemySpawn> getSpawns(){
|
||||
//TODO
|
||||
return null;
|
||||
public static Array<SpawnGroup> getSpawns(){
|
||||
return Array.with(
|
||||
new SpawnGroup(UnitTypes.scout){{
|
||||
end = 5;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.titan){{
|
||||
begin = 6;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.scout){{
|
||||
begin = 6;
|
||||
items = new ItemStack(Items.thermite, 100);
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.vtol){{
|
||||
begin = 8;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.monsoon){{
|
||||
begin = 16;
|
||||
}}
|
||||
);
|
||||
}
|
||||
|
||||
public static void testWaves(int from, int to){
|
||||
Array<EnemySpawn> spawns = getSpawns();
|
||||
Array<SpawnGroup> spawns = getSpawns();
|
||||
for(int i = from; i <= to; i ++){
|
||||
System.out.print(i+": ");
|
||||
int total = 0;
|
||||
for(EnemySpawn spawn : spawns){
|
||||
int a = spawn.evaluate(i, 0);
|
||||
int t = spawn.tier(i, 0);
|
||||
for(SpawnGroup spawn : spawns){
|
||||
int a = spawn.getUnitsSpawned(i);
|
||||
total += a;
|
||||
|
||||
if(a > 0){
|
||||
System.out.print(a+"x" + spawn.type.name + "-" + t + " ");
|
||||
System.out.print(a+"x" + spawn.type.name);
|
||||
}
|
||||
}
|
||||
System.out.print(" (" + total + ")");
|
||||
|
@ -14,9 +14,9 @@ public class StatusEffect implements Content{
|
||||
public final float baseDuration;
|
||||
public final int id;
|
||||
|
||||
public float damageMultiplier; //damage dealt
|
||||
public float armorMultiplier; //armor points
|
||||
public float speedMultiplier; //speed
|
||||
public float damageMultiplier = 1f; //damage dealt
|
||||
public float armorMultiplier = 1f; //armor points
|
||||
public float speedMultiplier = 1f; //speed
|
||||
|
||||
/**Set of 'opposite' effects, which will decrease the duration of this effect when applied.*/
|
||||
protected ObjectSet<StatusEffect> opposites = new ObjectSet<>();
|
||||
|
@ -1,7 +1,7 @@
|
||||
package io.anuke.mindustry.type;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.OrderedMap;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.Vars;
|
||||
@ -23,7 +23,7 @@ public class Weapon extends Upgrade {
|
||||
/**minimum cursor distance from player, fixes 'cross-eyed' shooting.*/
|
||||
protected static float minPlayerDist = 20f;
|
||||
/**ammo type map. set with setAmmo()*/
|
||||
protected ObjectMap<Item, AmmoType> ammoMap = new ObjectMap<>();
|
||||
protected OrderedMap<Item, AmmoType> ammoMap = new OrderedMap<>();
|
||||
/**shell ejection effect*/
|
||||
protected Effect ejectEffect = Fx.none;
|
||||
/**weapon reload in frames*/
|
||||
@ -112,7 +112,7 @@ public class Weapon extends Upgrade {
|
||||
}
|
||||
|
||||
public Iterable<Item> getAcceptedItems(){
|
||||
return ammoMap.keys();
|
||||
return ammoMap.orderedKeys();
|
||||
}
|
||||
|
||||
public AmmoType getAmmoType(Item item){
|
||||
|
@ -14,6 +14,7 @@ import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
import static io.anuke.mindustry.Vars.renderer;
|
||||
import static io.anuke.mindustry.Vars.showFog;
|
||||
|
||||
public class Minimap extends Table {
|
||||
|
||||
@ -35,18 +36,19 @@ public class Minimap extends Table {
|
||||
renderer.minimap().drawEntities(x, y, width, height);
|
||||
}
|
||||
|
||||
renderer.fog().getTexture().setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
|
||||
if(showFog) {
|
||||
renderer.fog().getTexture().setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
|
||||
|
||||
draw.getRegion().setTexture(renderer.fog().getTexture());
|
||||
draw.getRegion().setV(1f - draw.getRegion().getV());
|
||||
draw.getRegion().setV2(1f - draw.getRegion().getV2());
|
||||
draw.getRegion().setTexture(renderer.fog().getTexture());
|
||||
draw.getRegion().setV(1f - draw.getRegion().getV());
|
||||
draw.getRegion().setV2(1f - draw.getRegion().getV2());
|
||||
|
||||
Graphics.shader(Shaders.fog);
|
||||
super.draw(batch, parentAlpha);
|
||||
Graphics.shader();
|
||||
|
||||
Graphics.shader(Shaders.fog);
|
||||
super.draw(batch, parentAlpha);
|
||||
Graphics.shader();
|
||||
|
||||
renderer.fog().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
|
||||
renderer.fog().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,10 +2,9 @@ package io.anuke.mindustry.ui.fragments;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import io.anuke.mindustry.content.bullets.TurretBullets;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||
import io.anuke.mindustry.entities.effect.Fire;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
@ -58,19 +57,21 @@ public class DebugFragment implements Fragment {
|
||||
row();
|
||||
new button("noclip", "toggle", () -> noclip = !noclip);
|
||||
row();
|
||||
new button("fire", () -> {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Fire.create(world.tileWorld(player.x + Mathf.range(20), player.y + Mathf.range(20)));
|
||||
}
|
||||
});
|
||||
row();
|
||||
new button("team", "toggle", () -> player.toggleTeam());
|
||||
row();
|
||||
new button("blocks", "toggle", () -> showBlockDebug = !showBlockDebug);
|
||||
row();
|
||||
new button("effect", () -> {
|
||||
for(int i = 0; i < 20; i ++){
|
||||
Bullet.create(TurretBullets.fireball, player, player.getTeam(), player.x, player.y, Mathf.random(360f));
|
||||
}
|
||||
});
|
||||
new button("fog", () -> showFog = !showFog);
|
||||
row();
|
||||
new button("wave", () -> state.wavetime = 0f);
|
||||
row();
|
||||
new button("death", () -> player.damage(99999, false));
|
||||
new button("death", () -> player.damage(99999, true));
|
||||
row();
|
||||
new button("spawn", () -> {
|
||||
FloatingDialog dialog = new FloatingDialog("debug spawn");
|
||||
|
Loading…
Reference in New Issue
Block a user