diff --git a/core/assets-raw/sprites/weapons/blaster-equip.png b/core/assets-raw/sprites/weapons/blaster-equip.png index 9f6fd9dc06..4d31fe6f16 100644 Binary files a/core/assets-raw/sprites/weapons/blaster-equip.png and b/core/assets-raw/sprites/weapons/blaster-equip.png differ diff --git a/core/assets/ui/uiskin.json b/core/assets/ui/uiskin.json index 6da4b2bc62..02946c88b5 100644 --- a/core/assets/ui/uiskin.json +++ b/core/assets/ui/uiskin.json @@ -41,9 +41,9 @@ io.anuke.ucore.scene.Skin$TintedDrawable: { invis: {name: white, color: {r: 0, g: 0, b: 0, a: 0} } loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} }, chatfield: {name: white, color: {r: 0, g: 0, b: 0, a: 0.2}}, - clear: {name: white, color: {r: 0.1, g: 0.1, b: 0.1, a: 0.75}}, - clear-over: {name: white, color: {r: 1, g: 1, b: 1, a: 0.2} }, - clear-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} } + clear: {name: white, color: {r: 0.1, g: 0.1, b: 0.1, a: 0.75}}, + clear-over: {name: white, color: {r: 1, g: 1, b: 1, a: 0.2} }, + clear-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} } }, io.anuke.ucore.scene.ui.Button$ButtonStyle: { default: {down: button-down, up: button }, @@ -68,10 +68,6 @@ io.anuke.ucore.scene.ui.ImageButton$ImageButtonStyle: { select: {checked: button-select, up: clear }, close-window: {up: button, imageUp: icon-close, imageOver: icon-close-over, imageDown: icon-close-down, disabled: button } }, -io.anuke.ucore.scene.ui.ImageTextButton$ImageTextButtonStyle: { - default: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey }, - toggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey } -}, io.anuke.ucore.scene.ui.ScrollPane$ScrollPaneStyle: { default: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical}, horizontal: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal}, @@ -102,8 +98,5 @@ io.anuke.ucore.scene.ui.TextField$TextFieldStyle: { } io.anuke.ucore.scene.ui.CheckBox$CheckBoxStyle: { default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOnOver: check-on-over, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: grey } -}, -io.anuke.ucore.scene.ui.List$ListStyle: { - default: {fontColorUnselected: white, fontColorSelected: white, font: default-font } } } diff --git a/core/assets/version.properties b/core/assets/version.properties index 9b3e7182db..afdb9929b7 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Mon Apr 23 21:27:41 EDT 2018 +#Tue Apr 24 21:35:40 EDT 2018 version=pre-alpha -androidBuildCode=1090 +androidBuildCode=1094 name=Mindustry code=4.0 build=custom build diff --git a/core/src/io/anuke/mindustry/content/Weapons.java b/core/src/io/anuke/mindustry/content/Weapons.java index b501d8821c..28248934d7 100644 --- a/core/src/io/anuke/mindustry/content/Weapons.java +++ b/core/src/io/anuke/mindustry/content/Weapons.java @@ -1,16 +1,16 @@ package io.anuke.mindustry.content; -import io.anuke.mindustry.content.bullets.TurretBullets; import io.anuke.mindustry.content.fx.ShootFx; import io.anuke.mindustry.resource.Weapon; public class Weapons { public static final Weapon - blaster = new Weapon("blaster", 12, TurretBullets.basicIron) { - { - effect = ShootFx.shootSmall; - length = 2f; - } - }; + blaster = new Weapon("blaster") {{ + length = 1.5f; + reload = 15f; + roundrobin = true; + ejectEffect = ShootFx.shellEjectSmall; + setAmmo(AmmoTypes.basicIron); + }}; } diff --git a/core/src/io/anuke/mindustry/content/fx/ShootFx.java b/core/src/io/anuke/mindustry/content/fx/ShootFx.java index cf30c3155f..13c659f221 100644 --- a/core/src/io/anuke/mindustry/content/fx/ShootFx.java +++ b/core/src/io/anuke/mindustry/content/fx/ShootFx.java @@ -90,15 +90,16 @@ public class ShootFx { shellEjectSmall = new GroundEffect(30f, 400f, e -> { Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); - float rot = e.rotation + 90f; - for(int i : Mathf.signs){ - float len = (2f + e.finpow()*6f) * i; - float lr = rot + e.fin()*30f*i; - Draw.rect("white", - e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 1f, 2f, rot + e.fin()*50f*i); - } + float rot = Math.abs(e.rotation) + 90f; + + int i = Mathf.sign(e.rotation); + + float len = (2f + e.finpow()*6f) * i; + float lr = rot + e.fin()*30f*i; + Draw.rect("white", + e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 1f, 2f, rot + e.fin()*50f*i); Draw.color(); }), diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index e40c263f28..5b4d652508 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -143,7 +143,7 @@ public class Control extends Module{ Events.on(ResetEvent.class, () -> { upgrades.reset(); - player.weaponLeft = player.weaponRight = Weapons.blaster; + player.weapon = Weapons.blaster; player.team = Team.blue; player.inventory.clear(); diff --git a/core/src/io/anuke/mindustry/core/NetCommon.java b/core/src/io/anuke/mindustry/core/NetCommon.java index 174b58d4f7..32b2f7b7d6 100644 --- a/core/src/io/anuke/mindustry/core/NetCommon.java +++ b/core/src/io/anuke/mindustry/core/NetCommon.java @@ -26,8 +26,8 @@ public class NetCommon extends Module { if (player == null) return; - player.weaponLeft = Upgrade.getByID(packet.left); - player.weaponRight = Upgrade.getByID(packet.right); + player.weapon = Upgrade.getByID(packet.weapon); + player.weapon = Upgrade.getByID(packet.weapon); }); Net.handle(BlockTapPacket.class, (packet) -> { diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 540e1ba762..4f3b1981e7 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -35,6 +35,7 @@ import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.*; import io.anuke.ucore.entities.EffectEntity; import io.anuke.ucore.entities.Entities; +import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.function.Callable; import io.anuke.ucore.graphics.*; @@ -65,7 +66,7 @@ public class Renderer extends RendererModule{ Lines.setCircleVertices(14); Core.cameraScale = baseCameraScale; - Effects.setEffectProvider((effect, color, x, y, rotation) -> { + Effects.setEffectProvider((effect, color, x, y, rotation, data) -> { if(effect == Fx.none) return; if(Settings.getBool("effects")){ Rectangle view = rect.setSize(camera.viewportWidth, camera.viewportHeight) @@ -82,6 +83,10 @@ public class Renderer extends RendererModule{ entity.rotation = rotation; entity.lifetime = effect.lifetime; id = entity.set(x, y).add(effectGroup).id; + + if(data instanceof Entity){ + entity.setParent((Entity)data); + } } if(effect instanceof GroundEffect){ diff --git a/core/src/io/anuke/mindustry/entities/Bullet.java b/core/src/io/anuke/mindustry/entities/Bullet.java index cfdd7f7aaf..043052a43e 100644 --- a/core/src/io/anuke/mindustry/entities/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/Bullet.java @@ -27,6 +27,7 @@ public class Bullet extends BulletEntity{ bullet.owner = owner; bullet.velocity.set(0, type.speed).setAngle(angle); + bullet.velocity.add(owner instanceof Unit ? ((Unit)owner).velocity : Vector2.Zero); bullet.hitbox.setSize(type.hitsize); bullet.team = team; diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index b2ae08d7fb..885a575cb0 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -11,10 +11,7 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; -import io.anuke.mindustry.resource.ItemStack; -import io.anuke.mindustry.resource.Mech; -import io.anuke.mindustry.resource.Upgrade; -import io.anuke.mindustry.resource.Weapon; +import io.anuke.mindustry.resource.*; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.ucore.core.Effects; @@ -23,10 +20,7 @@ import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Timer; -import io.anuke.ucore.util.Translator; +import io.anuke.ucore.util.*; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -46,8 +40,7 @@ public class Player extends Unit{ public boolean isAdmin; public Color color = new Color(); - public Weapon weaponLeft = Weapons.blaster; - public Weapon weaponRight = Weapons.blaster; + public Weapon weapon = Weapons.blaster; public Mech mech = Mechs.standard; public float targetAngle = 0f; @@ -72,8 +65,8 @@ public class Player extends Unit{ @Override public void onRemoteShoot(BulletType type, float x, float y, float rotation, short data) { - Weapon weapon = Upgrade.getByID((byte)data); - weapon.shoot(player, x, y, rotation); + Weapon weapon = Upgrade.getByID(Bits.getLeftByte(data)); + weapon.shoot(player, x, y, rotation, Bits.getRightByte(data) == 1); } @Override @@ -184,8 +177,7 @@ public class Player extends Unit{ Draw.rect(mname, x, y, rotation -90); for (int i : Mathf.signs) { - Weapon weapon = i < 0 ? weaponLeft : weaponRight; - tr.trns(rotation - 90, 4*i, 3); + tr.trns(rotation - 90, 4*i, 3 - weapon.getRecoil(this, i > 0)*1.5f); float w = i > 0 ? -8 : 8; Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, rotation - 90); } @@ -269,8 +261,8 @@ public class Player extends Unit{ boolean shooting = control.input().canShoot() && control.input().isShooting(); if(shooting){ - weaponLeft.update(player, true); - weaponRight.update(player, false); + weapon.update(player, true); + weapon.update(player, false); } if(dashing && timer.get(timerDash, 3) && movement.len() > 0){ @@ -302,6 +294,16 @@ public class Player extends Unit{ rotation = Mathf.slerpDelta(rotation, targetAngle, 0.2f); } + @Override + public boolean acceptsAmmo(Item item) { + return weapon.getAmmoType(item) != null && inventory.canAcceptAmmo(weapon.getAmmoType(item)); + } + + @Override + public void addAmmo(Item item) { + inventory.addAmmo(weapon.getAmmoType(item)); + } + @Override public Player add(){ return add(playerGroup); @@ -339,8 +341,7 @@ public class Player extends Unit{ public void writeSpawn(ByteBuffer buffer) { buffer.put((byte)name.getBytes().length); buffer.put(name.getBytes()); - buffer.put(weaponLeft.id); - buffer.put(weaponRight.id); + buffer.put(weapon.id); buffer.put(mech.id); buffer.put(isAdmin ? 1 : (byte)0); buffer.putInt(Color.rgba8888(color)); @@ -355,8 +356,7 @@ public class Player extends Unit{ byte[] n = new byte[nlength]; buffer.get(n); name = new String(n); - weaponLeft = Upgrade.getByID(buffer.get()); - weaponRight = Upgrade.getByID(buffer.get()); + weapon = Upgrade.getByID(buffer.get()); mech = Upgrade.getByID(buffer.get()); isAdmin = buffer.get() == 1; color.set(buffer.getInt()); diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index 3508e6449e..bb5dd5fc0a 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.entities; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.ucore.core.Effects; @@ -18,12 +19,13 @@ import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.world; public abstract class Unit extends SyncEntity implements SerializableEntity { - //total duration of hit effect + /**total duration of hit flash effect*/ public static final float hitDuration = 9f; public StatusController status = new StatusController(); - public UnitInventory inventory = new UnitInventory(100); + public UnitInventory inventory = new UnitInventory(100, 100); public Team team = Team.blue; + public Vector2 velocity = new Vector2(); public float hitTime; public float drownTime; @@ -146,6 +148,8 @@ public abstract class Unit extends SyncEntity implements SerializableEntity { } } + public abstract boolean acceptsAmmo(Item item); + public abstract void addAmmo(Item item); public abstract float getMass(); public abstract boolean isFlying(); public abstract float getSize(); diff --git a/core/src/io/anuke/mindustry/entities/UnitInventory.java b/core/src/io/anuke/mindustry/entities/UnitInventory.java index 0f3b4dd919..21b297998e 100644 --- a/core/src/io/anuke/mindustry/entities/UnitInventory.java +++ b/core/src/io/anuke/mindustry/entities/UnitInventory.java @@ -5,10 +5,37 @@ import io.anuke.mindustry.resource.*; public class UnitInventory { private final AmmoEntry ammo = new AmmoEntry(AmmoType.getByID(0), 0); private ItemStack item; - private int capacity; + private int capacity, ammoCapacity; - public UnitInventory(int capacity) { + public UnitInventory(int capacity, int ammoCapacity) { this.capacity = capacity; + this.ammoCapacity = ammoCapacity; + } + + public AmmoType getAmmo() { + return ammo.type; + } + + public boolean hasAmmo(){ + return ammo.amount > 0; + } + + public void useAmmo(){ + ammo.amount --; + } + + public int ammoCapacity(){ + return ammoCapacity; + } + + public boolean canAcceptAmmo(AmmoType type){ + return ammo.amount + type.quantityMultiplier <= ammoCapacity; + } + + public void addAmmo(AmmoType type){ + if(ammo.type != type) ammo.amount = 0; + ammo.type = type; + ammo.amount += Math.min((int)type.quantityMultiplier, ammoCapacity - ammo.amount); } public int capacity(){ @@ -33,6 +60,8 @@ public class UnitInventory { public void clear(){ item = null; + ammo.amount = 0; + ammo.type = AmmoType.getByID(0); } public boolean hasItem(){ @@ -48,7 +77,6 @@ public class UnitInventory { } } - public ItemStack getItem(){ if(!hasItem()) throw new RuntimeException("This inventory has no item! Check hasItem() first."); return item; diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index e19ea20849..cb9bf12519 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -96,6 +96,20 @@ public class Units { return result[0]; } + /**Iterates over all units in a rectangle.*/ + public static void getNearby(Team team, Rectangle rect, Consumer cons){ + + EntityGroup group = unitGroups[team.ordinal()]; + if(!group.isEmpty()){ + Entities.getNearby(group, rect, entity -> cons.accept((Unit)entity)); + } + + //now check all enemy players + Entities.getNearby(playerGroup, rect, player -> { + if(((Unit)player).team == team) cons.accept((Unit)player); + }); + } + /**Iterates over all units in a rectangle.*/ public static void getNearby(Rectangle rect, Consumer cons){ @@ -128,4 +142,6 @@ public class Units { } }); } + + } diff --git a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java index bc27e2df2a..65f2f4321a 100644 --- a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java +++ b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java @@ -47,7 +47,7 @@ public class GroundEffectEntity extends EffectEntity { public GroundEffect(float life, float staticLife, EffectRenderer draw) { super(life, draw); this.staticLife = staticLife; - this.isStatic = false; + this.isStatic = true; } public GroundEffect(boolean isStatic, float life, EffectRenderer draw) { diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemTransferEffect.java b/core/src/io/anuke/mindustry/entities/effect/ItemTransferEffect.java new file mode 100644 index 0000000000..f6bc4745f1 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/effect/ItemTransferEffect.java @@ -0,0 +1,44 @@ +package io.anuke.mindustry.entities.effect; + +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.resource.Item; +import io.anuke.ucore.entities.Entity; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.util.Mathf; + +public class ItemTransferEffect extends Entity { + private static final float size = 5f; + private static final float alpha = 0.1f; + + private final Item item; + private final Entity target; + + public ItemTransferEffect(Item item, float x, float y, Entity target) { + this.x = x; + this.y = y; + this.item = item; + this.target = target; + } + + @Override + public void update() { + + x = Mathf.lerpDelta(x, target.x, alpha); + y = Mathf.lerpDelta(y, target.y, alpha); + + if(distanceTo(target) <= 2f){ + remove(); + } + } + + @Override + public void draw() { + float s = size; + Draw.rect(item.region, x, y, s, s); + } + + @Override + public T add() { + return super.add(Vars.effectGroup); + } +} diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index 84b265449c..d2d332c4e8 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -6,6 +6,7 @@ import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.resource.Item; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Timer; @@ -39,6 +40,16 @@ public class BaseUnit extends Unit{ rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); } + //TODO + @Override + public boolean acceptsAmmo(Item item) { + return false; + } + + @Override + public void addAmmo(Item item) { + + } //TODO @Override public float getSize() { diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 29efffda5c..20f63c0653 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -106,7 +106,7 @@ public class DesktopInput extends InputHandler{ for(int i = 1; i <= 6 && i <= control.upgrades().getWeapons().size; i ++){ if(Inputs.keyTap("weapon_" + i)){ - player.weaponLeft = player.weaponRight = control.upgrades().getWeapons().get(i - 1); + player.weapon = control.upgrades().getWeapons().get(i - 1); if(Net.active()) NetEvents.handleWeaponSwitch(); } } diff --git a/core/src/io/anuke/mindustry/net/NetEvents.java b/core/src/io/anuke/mindustry/net/NetEvents.java index 359d521650..6b622dc355 100644 --- a/core/src/io/anuke/mindustry/net/NetEvents.java +++ b/core/src/io/anuke/mindustry/net/NetEvents.java @@ -63,8 +63,7 @@ public class NetEvents { public static void handleWeaponSwitch(){ WeaponSwitchPacket packet = new WeaponSwitchPacket(); - packet.left = Vars.player.weaponLeft.id; - packet.right = Vars.player.weaponRight.id; + packet.weapon = Vars.player.weapon.id; packet.playerid = Vars.player.id; Net.send(packet, SendMode.tcp); } diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index 9528c3eca3..4fac2899b1 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -123,7 +123,7 @@ public class NetworkIO { control.upgrades().getWeapons().add(Upgrade.getByID(stream.readByte())); } - player.weaponLeft = player.weaponRight = control.upgrades().getWeapons().peek(); + player.weapon = control.upgrades().getWeapons().peek(); Entities.clear(); player.id = pid; diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 7bca405807..c70952582d 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -376,20 +376,18 @@ public class Packets { public static class WeaponSwitchPacket implements Packet{ public int playerid; - public byte left, right; + public byte weapon; @Override public void write(ByteBuffer buffer) { buffer.putInt(playerid); - buffer.put(left); - buffer.put(right); + buffer.put(weapon); } @Override public void read(ByteBuffer buffer) { playerid = buffer.getInt(); - left = buffer.get(); - right = buffer.get(); + weapon = buffer.get(); } } diff --git a/core/src/io/anuke/mindustry/resource/Weapon.java b/core/src/io/anuke/mindustry/resource/Weapon.java index c1143da3c3..a8cb46c5f6 100644 --- a/core/src/io/anuke/mindustry/resource/Weapon.java +++ b/core/src/io/anuke/mindustry/resource/Weapon.java @@ -1,21 +1,30 @@ package io.anuke.mindustry.resource; +import com.badlogic.gdx.utils.ObjectMap; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.content.fx.Fx; +import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; +import io.anuke.ucore.core.Graphics; import io.anuke.ucore.util.Angles; +import io.anuke.ucore.util.Bits; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Translator; 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 ammoMap = new ObjectMap<>(); + /**shell ejection effect*/ + protected Effect ejectEffect = Fx.none; /**weapon reload in frames*/ protected float reload; - /**sound made when shooting*/ - protected String shootsound = "shoot"; /**amount of shots per fire*/ protected int shots = 1; /**spacing in degrees between multiple shots, if applicable*/ @@ -24,56 +33,79 @@ public class Weapon extends Upgrade{ protected float inaccuracy = 0f; /**intensity and duration of each shot's screen shake*/ protected float shake = 0f; - /**effect displayed when shooting*/ - protected Effect effect; /**shoot barrel length*/ protected float length = 3f; - /**whether to shoot the weapons in different arms one after another, rather an all at once*/ + /**whether to shoot the weapons in different arms one after another, rather than all at once*/ protected boolean roundrobin = false; /**translator for vector calulations*/ protected Translator tr = new Translator(); - protected Weapon(String name, float reload){ + protected Weapon(String name){ super(name); - this.reload = reload; } public void update(Player p, boolean left){ int t = left ? 1 : 2; int t2 = !left ? 1 : 2; - if(p.timer.get(t, reload)){ + if(p.inventory.hasAmmo() && p.timer.get(t, reload)){ if(roundrobin){ p.timer.reset(t2, reload/2f); } - float ang = Angles.mouseAngle(p.x, p.y); + + tr.set(Graphics.mouseWorld()).sub(p.x, p.y); + if(tr.len() < minPlayerDist) tr.setLength(minPlayerDist); + + float cx = tr.x + p.x, cy = tr.y + p.y; + + float ang = tr.angle(); tr.trns(ang - 90, 4f * Mathf.sign(left), length + 1f); - shoot(p, p.x + tr.x, p.y + tr.y, Angles.mouseAngle(p.x + tr.x, p.y + tr.y)); + + shoot(p, p.x + tr.x, p.y + tr.y, Angles.angle(p.x + tr.x, p.y + tr.y, cx, cy), left); } } - void shootInternal(Player p, float x, float y, float rotation){ - Angles.shotgun(shots, spacing, rotation, f -> bullet(p, x, y, f + Mathf.range(inaccuracy))); - tr.trns(rotation, 3f); - if(effect != null) Effects.effect(effect, x + tr.x, y + tr.y, rotation); - Effects.shake(shake, shake, x, y); - Effects.sound(shootsound, x, y); + public float getRecoil(Player player, boolean left){ + return 1f-Mathf.clamp(player.timer.getTime(left ? 1 : 2)/reload); } public float getReload(){ return reload; } - public void shoot(Player p, float x, float y, float angle){ - shootInternal(p, x, y, angle); + public void shoot(Player p, float x, float y, float angle, boolean left){ + shootInternal(p, x, y, angle, left); if(Net.active() && p == Vars.player){ - NetEvents.handleShoot(Vars.player, x, y, angle, id); + NetEvents.handleShoot(Vars.player, x, y, angle, Bits.packShort(id, (byte)(left ? 1 : 0))); } + + p.inventory.useAmmo(); + } + + public AmmoType getAmmoType(Item item){ + return ammoMap.get(item); + } + + protected void setAmmo(AmmoType... types){ + for(AmmoType type : types){ + ammoMap.put(type.item, type); + } + } + + void shootInternal(Player p, float x, float y, float rotation, boolean left){ + Angles.shotgun(shots, spacing, rotation, f -> bullet(p, x, y, f + Mathf.range(inaccuracy))); + tr.trns(rotation, 3f); + + AmmoType type = p.inventory.getAmmo(); + + Effects.shake(shake, shake, x, y); + Effects.effect(ejectEffect, x, y, rotation * -Mathf.sign(left)); + Effects.effect(type.shootEffect, x + tr.x, y + tr.y, rotation, p); + Effects.effect(type.smokeEffect, x + tr.x, y + tr.y, rotation, p); } void bullet(Unit owner, float x, float y, float angle){ tr.trns(angle, 3f); - //TODO implement! - //Bullet.create(type, owner, x + tr.x, y + tr.y, angle); + Bullet.create(owner.inventory.getAmmo().bullet, owner, x + tr.x, y + tr.y, angle); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index c25dc549c6..e1300c6259 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -104,7 +104,7 @@ public class PlayerListFragment implements Fragment{ public void draw(){ float s = getWidth() / 12f; for(int i : Mathf.signs){ - Draw.rect((i < 0 ? player.weaponLeft.name : player.weaponRight.name) + Draw.rect((player.weapon.name) + "-equip", x + s * 6 + i * 3*s, y + s*6 + 2*s, -8*s*i, 8*s); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java index b13ab160e0..bf81a5831c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java @@ -38,7 +38,6 @@ public abstract class Turret extends Block{ protected Effect shootEffect = Fx.none; protected Effect smokeEffect = Fx.none; protected Effect ammoUseEffect = Fx.none; - protected String shootsound = "shoot"; protected int ammoPerShot = 1; protected float ammoEjectBack = 1f; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/storage/CoreBlock.java index 38630c824f..9ae0bf025f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/storage/CoreBlock.java @@ -1,24 +1,43 @@ package io.anuke.mindustry.world.blocks.types.storage; +import com.badlogic.gdx.math.Rectangle; +import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.effect.ItemTransferEffect; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Lines; import static io.anuke.mindustry.Vars.state; public class CoreBlock extends StorageBlock { + private static Rectangle rect = new Rectangle(); + + protected int timerSupply = timers ++; + + protected float supplyRadius = 50f; + protected float supplyInterval = 5f; public CoreBlock(String name) { super(name); solid = true; - destructible = true; + update = true; unbreakable = true; size = 3; hasItems = true; itemCapacity = 2000; } + @Override + public void drawSelect(Tile tile){ + Draw.color("accent"); + Lines.dashCircle(tile.drawx(), tile.drawy(), supplyRadius); + Draw.color(); + } + + @Override public void onDestroyed(Tile tile){ //TODO more dramatic effects super.onDestroyed(tile); @@ -32,31 +51,26 @@ public class CoreBlock extends StorageBlock { public void handleItem(Item item, Tile tile, Tile source){ if(Net.server() || !Net.active()) super.handleItem(item, tile, source); } - /* @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return item.material && state.inventory.getAmount(item) < capacity; - } + public void update(Tile tile) { - @Override - public Item removeItem(Tile tile, Item item){ - for(int i = 0; i < state.inventory.getItems().length; i ++){ - if(state.inventory.getItems()[i] > 0 && (item == null || item.id == i)){ - if(Net.server() || !Net.active()) state.inventory.getItems()[i] --; - return Item.getByID(i); - } + if(tile.entity.timer.get(timerSupply, supplyInterval)){ + rect.setSize(supplyRadius*2).setCenter(tile.drawx(), tile.drawy()); + + Units.getNearby(tile.getTeam(), rect, unit -> { + if(unit.distanceTo(tile.drawx(), tile.drawy()) > supplyRadius) return; + + for(int i = 0; i < tile.entity.items.items.length; i ++){ + Item item = Item.getByID(i); + if(tile.entity.items.items[i] > 0 && unit.acceptsAmmo(item)){ + tile.entity.items.items[i] --; + unit.addAmmo(item); + new ItemTransferEffect(item, tile.drawx(), tile.drawy(), unit).add(); + return; + } + } + }); } - return null; } - - @Override - public boolean hasItem(Tile tile, Item item){ - for(int i = 0; i < state.inventory.getItems().length; i ++){ - if(state.inventory.getItems()[i] > 0 && (item == null || item.id == i)){ - return true; - } - } - return false; - }*/ } diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 6df1f27b81..0c84e44010 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -49,7 +49,7 @@ public class ServerControl extends Module { mode = ShuffleMode.valueOf(Settings.getString("shufflemode")); Effects.setScreenShakeProvider((a, b) -> {}); - Effects.setEffectProvider((a, b, c, d, e) -> {}); + Effects.setEffectProvider((a, b, c, d, e, f) -> {}); Sounds.setHeadless(true); //override default handling of chat packets