package net.mostlyoriginal.game.system.ship; /** * @author Daan van Yperen */ import com.artemis.Aspect; import com.artemis.ComponentMapper; import com.artemis.Entity; import com.artemis.EntitySystem; import com.artemis.annotations.Wire; import com.artemis.utils.EntityBuilder; import com.artemis.utils.ImmutableBag; import com.badlogic.gdx.math.MathUtils; import net.mostlyoriginal.api.component.basic.Bounds; import net.mostlyoriginal.api.component.basic.Pos; import net.mostlyoriginal.api.component.graphics.Anim; import net.mostlyoriginal.api.component.graphics.Color; import net.mostlyoriginal.api.component.graphics.Renderable; import net.mostlyoriginal.api.utils.GdxUtil; import net.mostlyoriginal.api.utils.reference.SafeEntityReference; import net.mostlyoriginal.game.G; import net.mostlyoriginal.game.NameRolodex; import net.mostlyoriginal.game.component.ship.CrewMember; import net.mostlyoriginal.game.component.ui.Button; import net.mostlyoriginal.game.component.ui.ButtonListener; import net.mostlyoriginal.game.component.ui.Clickable; import net.mostlyoriginal.game.component.ui.Label; import net.mostlyoriginal.game.manager.EntityFactorySystem; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Render and progress animations. * * @author Daan van Yperen * @see net.mostlyoriginal.api.component.graphics.Anim */ @Wire public class CrewSystem extends EntitySystem { public static final int MARGIN_BOTTOM = 40; public static final int MARGIN_LEFT = 2; private ComponentMapper<CrewMember> mCrew; protected InventorySystem inventorySystem; protected LifesupportSimulationSystem lifesupportSimulationSystem; protected ComponentMapper<CrewMember> mCrewMember; protected ComponentMapper<Pos> mPos; protected ComponentMapper<Anim> mAnim; protected ComponentMapper<Label> mLabel; protected ComponentMapper<Color> mColor; protected EntityFactorySystem efs; protected float labelCooldown = 4; protected boolean showStatusLabel = false; protected int crewIndex = 0; public static final Color NEUTRAL = GdxUtil.asColor("2C4142"); private final List<Entity> sortedEntities = new ArrayList<Entity>(); public boolean sortedDirty = false; public Comparator<Entity> layerSortComperator = new Comparator<Entity>() { @Override public int compare(Entity e1, Entity e2) { return mCrew.get(e1).name.compareTo(mCrew.get(e2).name); } }; private int ROW_HEIGHT = 9; public CrewSystem() { super(Aspect.getAspectForAll(CrewMember.class)); } @Override protected void initialize() { super.initialize(); createCrew("The Captain", "crew-0", CrewMember.Effect.HEALTHY); } @Override protected void processEntities(ImmutableBag<Entity> entities) { if (sortedDirty) { sortedDirty = false; Collections.sort(sortedEntities, layerSortComperator); } for (Entity entity : sortedEntities) { process(entity); crewIndex++; } } @Override protected void begin() { super.begin(); crewIndex=0; // slowly toggle between labels. labelCooldown -= world.delta; if ( labelCooldown <= 0 ) { labelCooldown = 2; showStatusLabel = !showStatusLabel; } } protected void process(Entity e) { final CrewMember crewMember = mCrewMember.get(e); populateTransients(crewMember, e); int offsetX = G.SCREEN_WIDTH - 8 - MARGIN_LEFT; int offsetY = MARGIN_BOTTOM + crewIndex * ROW_HEIGHT; if ( crewMember.icon.isActive() ) { Entity e2 = crewMember.icon.get(); if ( mPos.has(e2)) { Pos pos = mPos.get(e2); pos.x = offsetX; pos.y = offsetY; offsetX -= 8; } if ( mAnim.has(e2)) { Anim anim = mAnim.get(e2); anim.id2=crewMember.effect.animStatusId; } } if ( crewMember.biogelButton.isActive() ) { if ( inventorySystem.get(InventorySystem.Resource.BIOGEL) > 0 && crewMember.effect.can(CrewMember.Ability.BIOGELLABLE) ) { Entity e2 = crewMember.biogelButton.get(); if (mPos.has(e2)) { Pos pos = mPos.get(e2); pos.x = offsetX; pos.y = offsetY - 1; offsetX -= 6; } } } // fonts are typically offset in the wrong dir. offsetY += 6; offsetX += 5; // move label to right location. if ( crewMember.labelName.isActive() ) { // show name when applicable, or when healthy. updateLabel(offsetX, offsetY, crewMember.labelName.get(), !showStatusLabel || crewMember.effect == CrewMember.Effect.HEALTHY ? crewMember.name : null, NEUTRAL); } // move label to right location. if ( crewMember.labelStatus.isActive() ) { // show effect only when not healthy. updateLabel(offsetX, offsetY, crewMember.labelStatus.get(), showStatusLabel && crewMember.effect != CrewMember.Effect.HEALTHY ? crewMember.effect.label : null, crewMember.effect.color); } } private void updateLabel(int offsetX, int offsetY, Entity e2, String label, Color color) { if ( mPos.has(e2)) { Pos pos = mPos.get(e2); pos.x = offsetX; pos.y = offsetY; } if ( mLabel.has(e2) ) { Label l = mLabel.get(e2); l.text = label; mColor.get(e2).set(color); } } /** return random crewmember with ability, or null if none. */ public Entity randomWith(CrewMember.Ability ability) { Entity[] entities = getAllWith(ability); return entities.length == 0 ? null : entities[MathUtils.random(0,entities.length-1)]; } /** return all crewmembers with given agbility. */ public Entity[] getAllWith(CrewMember.Ability ability) { final ArrayList<Entity> list = new ArrayList<>(); for (Entity e : sortedEntities) { final CrewMember crewMember = mCrewMember.get(e); if ( crewMember != null ) { if ( crewMember.effect.can( ability ) ) { list.add(e); } } } return list.toArray(new Entity[list.size()]); } public int countNotOf(CrewMember.Ability ability) { int count=0; for (Entity e : sortedEntities) { final CrewMember crewMember = mCrewMember.get(e); if ( crewMember != null ) { if ( !crewMember.effect.can( ability ) ) { count++; } } } return count; } /** return count of crew with given ability. */ public int countOf(CrewMember.Ability ability) { int count=0; for (Entity e : sortedEntities) { final CrewMember crewMember = mCrewMember.get(e); if ( crewMember != null ) { if ( crewMember.effect.can( ability ) ) { count++; } } } return count; } private void populateTransients(CrewMember crewMember, Entity e) { if ( crewMember.icon == null ) { crewMember.icon = new SafeEntityReference(new EntityBuilder(world).with(new Pos(), new Renderable(), new Anim(crewMember.animId)).build()); } if ( crewMember.biogelButton == null ) { Button btn = new Button("btn-heal", new HealButton(crewMember, e), "Heal the crewmember."); crewMember.biogelButton = new SafeEntityReference(new EntityBuilder(world).with(new Pos(), new Bounds(-2,-2,10, 8), new Clickable(), new Renderable(), new Anim(), btn).build()); btn.hideIfDisabled=true; } if ( crewMember.labelName == null ) { Label label = new Label(crewMember.name); label.align = Label.Align.RIGHT; crewMember.labelName = new SafeEntityReference(new EntityBuilder(world).with(new Pos(), label, new Renderable(), new Color(NEUTRAL)).build()); } if ( crewMember.labelStatus == null ) { Label label = new Label(crewMember.effect.label); label.align = Label.Align.RIGHT; crewMember.labelStatus = new SafeEntityReference(new EntityBuilder(world).with(new Pos(), label, new Renderable(), new Color(NEUTRAL)).build()); } } @Override protected boolean checkProcessing() { return true; } @Override protected void inserted(Entity e) { sortedEntities.add(e); sortedDirty = true; } @Override protected void removed(Entity e) { removeTransientProperties(e); sortedEntities.remove(e); } /** cleanup label and icon for crewmember. */ private void removeTransientProperties(Entity e) { final CrewMember crewMember = mCrewMember.get(e); if ( crewMember != null ) { if (crewMember.icon != null && !crewMember.icon.isActive()) { crewMember.icon.get().deleteFromWorld(); } if (crewMember.labelName != null && !crewMember.labelName.isActive()) { crewMember.labelName.get().deleteFromWorld(); } if (crewMember.labelStatus != null && !crewMember.labelStatus.isActive()) { crewMember.labelStatus.get().deleteFromWorld(); } if (crewMember.biogelButton != null && !crewMember.biogelButton.isActive()) { crewMember.biogelButton.get().deleteFromWorld(); } } } public void createRandomCrewmember() { createCrew(getRandomName(), "crew-" + MathUtils.random(0,2), CrewMember.Effect.HEALTHY); } public void createCrew(String name, String animId, CrewMember.Effect effect) { new EntityBuilder(world).with(new CrewMember(name, animId, effect)).build(); } public String getRandomName() { return NameRolodex.randomName(); } public CrewMember randomWithAsCrew(CrewMember.Ability ability) { Entity entity = randomWith(ability); return entity != null ? mCrewMember.get(entity) : null; } private class HealButton extends ButtonListener { private final CrewMember crewMember; public Entity e; public HealButton(CrewMember crewMember, Entity e) { this.crewMember = crewMember; this.e=e; } @Override public void run() { super.run(); lifesupportSimulationSystem.changeState(e, CrewMember.Effect.HEALTHY); inventorySystem.alter(InventorySystem.Resource.BIOGEL,-1); } @Override public boolean enabled() { return inventorySystem.get(InventorySystem.Resource.BIOGEL) > 0 && crewMember.effect.can(CrewMember.Ability.BIOGELLABLE); } } }