package net.mostlyoriginal.ns2d.system.active; import com.artemis.Aspect; import com.artemis.ComponentMapper; import com.artemis.Entity; import com.artemis.annotations.Wire; import com.artemis.managers.GroupManager; import com.artemis.managers.TagManager; import com.artemis.systems.EntityProcessingSystem; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import net.mostlyoriginal.ns2d.component.*; import net.mostlyoriginal.ns2d.system.passive.AssetSystem; import net.mostlyoriginal.ns2d.system.render.DialogRenderSystem; import net.mostlyoriginal.ns2d.util.EntityFactory; /** * @author Daan van Yperen */ @Wire public class WeaponSystem extends EntityProcessingSystem { private ComponentMapper<Weapon> wm; private ComponentMapper<Pos> pm; private ComponentMapper<Bounds> om; private ComponentMapper<Attached> atm; private ComponentMapper<Anim> am; private ComponentMapper<Physics> ym; private ComponentMapper<Gravity> gm; private ComponentMapper<Buildable> bm; private GroupManager groupManager; private PhysicsSystem physicsSystems; private AfterPhysicsSystem afterPhysicsSystem; private AttachmentSystem attachmentSystem; private ParticleSystem particleSystem; private TagManager tagManager; public Entity player; private AssetSystem assetSystem; private DialogRenderSystem dialogRenderSystem; public WeaponSystem() { super(Aspect.getAspectForAll(Weapon.class, Pos.class, Bounds.class, Anim.class)); } private Vector2 vTmp = new Vector2(); @Override protected void begin() { player = tagManager.getEntity("player"); } @Override protected void process(Entity gun) { final Weapon weapon = wm.get(gun); // avoid cooldown on unbuilt structures. if ( bm.has(gun) && !bm.get(gun).built ) return; if (weapon.firing || !weapon.cooldownWhileNotFiring) { weapon.cooldown -= world.delta; } weapon.sfxCooldown -= world.delta; if (weapon.firing) { weapon.firing = false; if (weapon.cooldown <= 0) { weapon.cooldown = weapon.fireCooldown; final Pos pos = pm.get(gun); final Bounds bounds = om.get(gun); final Anim anim = am.get(gun); float aimRotation = anim.rotation + weapon.aimRotation; if ( weapon.muzzleFlare ) { // determine muzzle location. vTmp.set(28,0).rotate(aimRotation).add(pos.x-8, pos.y+2).add(bounds.cx(), bounds.cy()); particleSystem.setRotation(aimRotation); particleSystem.spawnParticle((int)vTmp.x, (int)vTmp.y, "muzzle-flare"); particleSystem.setRotation(0); } if ( weapon.shellParticle != null ) { vTmp.set(18,0).rotate(aimRotation).add(pos.x-8, pos.y+2).add(bounds.cx(), bounds.cy()); particleSystem.spawnParticle((int)vTmp.x, (int)vTmp.y, weapon.shellParticle); } if ( weapon.fireSfxId != null ) { if ( weapon.sfxCooldown <= 0 ) { weapon.sfxCooldown = 1/30f; assetSystem.playSfx(weapon.fireSfxId,gun); } } // repeated bullets. for (int c = 0, s = MathUtils.random(weapon.minBullets, weapon.maxBullets); c < s; c++) { Entity bullet = EntityFactory.createBullet(world, pos.x + bounds.cx(), pos.y + bounds.cy()); // rotate bullet to player rotation float rotation = aimRotation + MathUtils.random(-weapon.spread, weapon.spread); Anim bulletAnim = am.get(bullet); bulletAnim.rotation = rotation; bulletAnim.id = weapon.bulletAnimId; // push back the user. if (atm.has(gun)) { Attached attachedTo = atm.get(gun); if (attachedTo.parent != null && attachedTo.parent.isActive()) { physicsSystems.push(attachedTo.parent, rotation - 180, weapon.recoil); } } if ( weapon.bulletPayload.type == Payload.DamageType.RESOURCE ) { Homing homing = new Homing(player); homing.maxDistance = 100; homing.maxVelocity = 500; homing.speedFactor = 2; bullet.edit().add(homing); } Physics physics = ym.get(bullet); physics.friction = weapon.bulletFriction; physics.bounce = weapon.bulletBounce; Payload payload = weapon.bulletPayload.clone(); payload.triggerGroup = weapon.enemyGroup; bullet.edit().add(payload); Gravity gravity = gm.get(bullet); gravity.y *= weapon.bulletGravityFactor; gravity.x *= weapon.bulletGravityFactor; attachmentSystem.push(gun, rotation - 180, weapon.recoil / s); physicsSystems.push(bullet, rotation, weapon.bulletSpeed); } if ( weapon.bulletPayload.type == Payload.DamageType.WEAPON_PICKUP ) { cycleWeaponPickup(weapon); } } } } private void cycleWeaponPickup(Weapon weapon) { dialogRenderSystem.randomSay(DialogRenderSystem.WEAPON_READY_MESSAGES); switch (weapon.bulletAnimId) { case "rifle": weapon.bulletAnimId="shotgun"; break; case "shotgun": weapon.bulletAnimId="grenadelauncher"; break; case "grenadelauncher": weapon.bulletAnimId="flamethrower"; break; case "flamethrower": weapon.bulletAnimId="rifle"; break; } } }