package net.mostlyoriginal.ns2d.system.collide;
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.artemis.utils.ImmutableBag;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import net.mostlyoriginal.ns2d.component.*;
import net.mostlyoriginal.ns2d.system.active.CameraShakeSystem;
import net.mostlyoriginal.ns2d.system.active.CombatSystem;
import net.mostlyoriginal.ns2d.system.active.EntitySpawnerSystem;
import net.mostlyoriginal.ns2d.system.active.ParticleSystem;
import net.mostlyoriginal.ns2d.system.passive.AssetSystem;
import net.mostlyoriginal.ns2d.system.passive.CollisionSystem;
import net.mostlyoriginal.ns2d.util.EntityUtil;
/**
* @author Daan van Yperen
*/
@Wire
public class BulletCollisionSystem extends EntityProcessingSystem {
private CameraShakeSystem cameraShakeSystem;
private ComponentMapper<Payload> pm;
private ComponentMapper<Pos> om;
private ComponentMapper<Wallet> wm;
private ComponentMapper<Inventory> im;
private GroupManager groupManager;
private CollisionSystem collisionSystem;
private CombatSystem combatSystem;
private ParticleSystem particleSystem;
private TagManager tagManager;
private EntitySpawnerSystem entitySpawnerSystem;
private ComponentMapper<Anim> am;
private AssetSystem assetSystem;
public BulletCollisionSystem() {
super(Aspect.getAspectForAll(Payload.class));
}
@Override
protected void process(Entity bullet) {
final Payload payload = pm.get(bullet);
payload.age += world.delta;
if (payload.age >= payload.maxLifetime - 0.25f) {
if ( am.has(bullet) )
{
// fade out bullets.
am.get(bullet).color.a = (payload.maxLifetime - payload.age) *4f;
}
}
if (payload.age >= payload.maxLifetime) {
if (payload.radius > 0) {
damageArea(bullet, payload.triggerGroup, payload.radius, MathUtils.random(payload.minDamage, payload.maxDamage), payload.type);
}
bullet.deleteFromWorld();
return;
}
final ImmutableBag<Entity> targets = groupManager.getEntities(payload.triggerGroup);
for (int i = 0, s = targets.size(); s > i; i++) {
final Entity victim = targets.get(i);
if (victim != null && collisionSystem.overlaps(bullet, victim)) {
triggerPayload(victim, bullet);
bullet.deleteFromWorld();
return;
}
}
}
private void triggerPayload(Entity victim, Entity bullet) {
final Payload payload = pm.get(bullet);
int damage = MathUtils.random(payload.minDamage, payload.maxDamage);
float radius = payload.radius;
if (payload.explodeSfxId != null) {
assetSystem.playSfx(payload.explodeSfxId, bullet);
}
switch (payload.type) {
case WEAPON_PICKUP: {
final Entity player = tagManager.getEntity("player");
entitySpawnerSystem.giveWeapon(player, am.get(bullet).id);
assetSystem.playSfx("ns2d_sfx_pickup",bullet);
break;
}
case RESOURCE: {
final Entity player = tagManager.getEntity("player");
if (wm.has(player))
{
wm.get(player).resources += damage;
assetSystem.playSfx("ns2d_sfx_pickup",bullet);
}
break;
}
case EXPLOSIVE:
if (radius == 0) {
//cameraShakeSystem.shake(1);
combatSystem.damage(victim, damage);
} else {
damageArea(bullet, payload.triggerGroup, radius, damage, payload.type);
}
break;
}
}
Vector2 vTmp = new Vector2();
private void damageArea(Entity bullet, String groupId, float radius, int damage, Payload.DamageType type) {
Payload payload = pm.get(bullet);
Pos pos = om.get(bullet);
switch (type) {
case BILE:
for (int i = 0, s = MathUtils.random(5, 10); i < s; i++) {
vTmp.set(MathUtils.random(0, radius), 0).rotate(MathUtils.random(0, 360)).add(pos.x, pos.y);
particleSystem.spawnParticle(
(int) vTmp.x, (int) vTmp.y, "bile");
}
break;
default:
cameraShakeSystem.shake(1 + radius / 20);
particleSystem.spawnParticle((int) pos.x, (int) pos.y, "explosion");
for (int i = 0, s = MathUtils.random(3, 5); i < s; i++) {
vTmp.set(MathUtils.random(0, radius), 0).rotate(MathUtils.random(0, 360)).add(pos.x, pos.y);
particleSystem.spawnParticle(
(int) vTmp.x, (int) vTmp.y, "tiny-explosion");
}
}
final ImmutableBag<Entity> targets = groupManager.getEntities(groupId);
for (int i = 0, s = targets.size(); s > i; i++) {
final Entity victim = targets.get(i);
if (victim != null && EntityUtil.distance2(bullet, victim) <= radius * radius) {
combatSystem.damage(victim, damage);
}
}
}
}