public class AbilityPanel extends TilePanel { private final GlyphLayout layout = new GlyphLayout(); private BitmapFont font; private TextureRegion white; private TextureRegion passiveTileBorder; public AbilityPanel(Skin skin, Stage stage) { super( skin, stage, AssetManager.loadSprite("GUI/TileBackground"), AssetManager.loadSprite("GUI/TileBorder"), 1, Global.NUM_ABILITY_SLOTS, 48, false); drawHorizontalBackground = false; font = skin.getFont("default"); padding = 10; this.white = AssetManager.loadTextureRegion("Sprites/white.png"); passiveTileBorder = AssetManager.loadTextureRegion("Sprites/GUI/PassiveTileBorder.png"); } @Override public void populateTileData() { tileData.clear(); for (AbilityTree a : Global.CurrentLevel.player.slottedAbilities) { if (a != null) { tileData.add(a); } else { tileData.add(tileData.size); } } while (tileData.size < Global.NUM_ABILITY_SLOTS) { tileData.add(tileData.size); } } @Override public Sprite getSpriteForData(Object data) { if (data == null || data instanceof Integer) { return null; } return ((AbilityTree) data).current.current.getIcon(); } @Override public void handleDataClicked(final Object data, InputEvent event, float x, float y) { { if (GameScreen.Instance.abilityToEquip != null) { int index = 0; if (data instanceof Integer) { index = (Integer) data; } else { index = Global.CurrentLevel.player.slottedAbilities.indexOf((AbilityTree) data, true); } while (Global.CurrentLevel.player.slottedAbilities.size <= index) { Global.CurrentLevel.player.slottedAbilities.add(null); } Global.CurrentLevel.player.slottedAbilities.removeIndex(index); Global.CurrentLevel.player.slottedAbilities.insert( index, GameScreen.Instance.abilityToEquip); GameScreen.Instance.abilityToEquip = null; if (data instanceof AbilityTree) { Item item = new Item(); item.ability = (AbilityTree) data; Global.CurrentLevel.player.tile[0][0].items.add(item); } GameScreen.Instance.lockContextMenu = false; GameScreen.Instance.clearContextMenu(); } else { if (data instanceof AbilityTree && ((AbilityTree) data).current.current instanceof ActiveAbility) { ActiveAbility aa = (ActiveAbility) ((AbilityTree) data).current.current; if (GameScreen.Instance.preparedAbility == aa) { GameScreen.Instance.prepareAbility(null); } else if (aa.isAvailable()) { GameScreen.Instance.prepareAbility(aa); } } } } } @Override public Table getToolTipForData(Object data) { if (data == null || data instanceof Integer) { return null; } return ((AbilityTree) data).current.current.createTable(skin, Global.CurrentLevel.player); } @Override public Color getColourForData(Object data) { if (data == null || data instanceof Integer) { return Color.DARK_GRAY; } if (((AbilityTree) data).current.current == GameScreen.Instance.preparedAbility) { return Color.CYAN; } return null; } @Override public void onDrawItemBackground(Object data, Batch batch, int x, int y, int width, int height) { if (GameScreen.Instance.abilityToEquip != null) { batch.setColor(Color.GOLD); tileBackground.render(batch, x, y, width, height); } } @Override public void onDrawItem(Object data, Batch batch, int x, int y, int width, int height) { if (data instanceof AbilityTree && ((AbilityTree) data).current.current instanceof ActiveAbility) { ActiveAbility aa = (ActiveAbility) ((AbilityTree) data).current.current; if (!aa.isAvailable()) { batch.setColor(0.1f, 0.1f, 0.1f, 0.75f); batch.draw(white, x, y, width, height); batch.setColor(Color.WHITE); int cooldown = (int) Math.ceil(aa.cooldownAccumulator); if (cooldown > 0) { String text = aa.cooldownType.text + "\n" + cooldown; layout.setText(font, text, Color.WHITE, 0, Align.center, false); font.draw(batch, layout, x + width / 2, y + height / 2 + layout.height / 2); } } } } @Override public void onDrawItemForeground(Object data, Batch batch, int x, int y, int width, int height) { if (data instanceof AbilityTree) { AbilityTree tree = (AbilityTree) data; if (((AbilityTree) data).current.current instanceof PassiveAbility) { batch.draw(passiveTileBorder, x, y, width, height); } if (tree.current.needsLevelAnim) { Sprite sprite = AssetManager.loadSprite("EffectSprites/Heal/Heal", 0.1f); GameScreen.Instance.addSpriteAction(sprite, x + width / 2, y + height / 2, width, height); Global.CurrentLevel.player.pendingMessages.add( new Message( tree.current.current.getName() + " levelled up! (Level " + tree.current.current.getLevel() + ")", Color.GOLD)); levelUpSound.play(Global.CurrentLevel.player.tile[0][0]); tree.current.needsLevelAnim = false; } } } public static final SoundInstance levelUpSound = SoundInstance.getSound("LevelUp"); }
private void doAttack(Array<GameTile> hitTiles, final GameEntity entity, Item weapon) { final GameTile source = entity.tile[0][0]; // Get all the attacked tiles Array<GameTile> attackedTiles = new Array<GameTile>(); if (weapon == null || weapon.wepDef == null || weapon.wepDef.hitType == Item.WeaponDefinition.HitType.ALL) { attackedTiles.addAll(hitTiles); } else if (weapon.wepDef.hitType == Item.WeaponDefinition.HitType.CLOSEST) { int num = weapon.wepDef.hitData != null ? Integer.parseInt(weapon.wepDef.hitData) : 1; Array<GameTile> validEntityTiles = new Array<GameTile>(); Array<GameTile> validEnvironmentTiles = new Array<GameTile>(); // Get tiles valid to hit for (GameTile tile : hitTiles) { if (tile.entity != null && !tile.entity.isAllies(entity)) { validEntityTiles.add(tile); } else if (tile.environmentEntity != null && tile.environmentEntity.canTakeDamage) { validEnvironmentTiles.add(tile); } } Comparator<GameTile> comp = new Comparator<GameTile>() { @Override public int compare(GameTile o1, GameTile o2) { int dist1 = Math.abs(o1.x - source.x) + Math.abs(o1.y - source.y); int dist2 = Math.abs(o2.x - source.x) + Math.abs(o2.y - source.y); return dist1 - dist2; } }; // sort by distance validEntityTiles.sort(comp); validEnvironmentTiles.sort(comp); for (int i = 0; i < num && i < validEntityTiles.size; i++) { attackedTiles.add(validEntityTiles.get(i)); } for (int i = 0; i < num - validEntityTiles.size && i < validEnvironmentTiles.size; i++) { attackedTiles.add(validEnvironmentTiles.get(i)); } } else if (weapon.wepDef.hitType == Item.WeaponDefinition.HitType.RANDOM) { int num = weapon.wepDef.hitData != null ? Integer.parseInt(weapon.wepDef.hitData) : 1; Array<GameTile> validEntityTiles = new Array<GameTile>(); Array<GameTile> validEnvironmentTiles = new Array<GameTile>(); // Get tiles valid to hit for (GameTile tile : hitTiles) { if (tile.entity != null && !tile.entity.isAllies(entity)) { validEntityTiles.add(tile); } else if (tile.environmentEntity != null && tile.environmentEntity.canTakeDamage) { validEnvironmentTiles.add(tile); } } if (validEntityTiles.size > 0) { for (int i = 0; i < num; i++) { attackedTiles.add(validEntityTiles.random()); } } else if (validEnvironmentTiles.size > 0) { for (int i = 0; i < num; i++) { attackedTiles.add(validEnvironmentTiles.random()); } } } Sprite hitEffect = null; if (weapon == null) { hitEffect = entity.defaultHitEffect; } else { hitEffect = weapon.getWeaponHitEffect(); } Point minPoint = Global.PointPool.obtain().set(Integer.MAX_VALUE, Integer.MAX_VALUE); Point maxPoint = Global.PointPool.obtain().set(0, 0); int hitCount = weapon != null && weapon.wepDef != null ? weapon.wepDef.hitCount : 1; float animdelay = 0; for (int i = 0; i < hitCount; i++) { // Do the attack for (GameTile tile : attackedTiles) { // do misses int hitPercent = weapon != null && weapon.wepDef != null ? weapon.wepDef.hitPercent : 100; if (hitPercent < 100) { if (MathUtils.random(100) > hitPercent) { // Argh! a miss! Hit a random surrounding tile Direction dir = Direction.values()[MathUtils.random(Direction.values().length - 1)]; GameTile newTile = tile.level.getGameTile(tile.x + dir.getX(), tile.y + dir.getY()); if (newTile != null) { tile = newTile; } } } if (weapon == null || weapon.wepDef == null || weapon.wepDef.hitType != Item.WeaponDefinition.HitType.ALL) { int[] diff = tile.getPosDiff(source); Sprite sprite = hitEffect.copy(); if (sprite.spriteAnimation != null) { int distMoved = (Math.abs(diff[0]) + Math.abs(diff[1])) / Global.TileSize; sprite.spriteAnimation.set(0.05f * distMoved, diff); } Vector2 vec = new Vector2(diff[0] * -1, diff[1] * -1); vec.nor(); float x = vec.x; float y = vec.y; double dot = 0 * x + 1 * y; // dot product double det = 0 * y - 1 * x; // determinant float angle = (float) Math.atan2(det, dot) * MathUtils.radiansToDegrees; sprite.rotation = angle; sprite.renderDelay = animdelay; animdelay += 0.1f; boolean isMoving = sprite.spriteAnimation != null && sprite.spriteAnimation instanceof MoveAnimation; final SoundInstance sound = hitEffect.sound; final GameTile hitTile = tile; final GameEntity hitEntity = hitTile.entity; final EnvironmentEntity hitEnvEntity = hitTile.environmentEntity; sprite.spriteAction = new SpriteAction( isMoving ? SpriteAction.FirePoint.End : SpriteAction.FirePoint.Start) { @Override public void evaluate() { // do on hit for (GameEventHandler handler : entity.getAllHandlers()) { handler.onHit(entity, hitTile); } if (hitEntity != null && !hitEntity.isAllies(entity)) { entity.attack(hitEntity, dir); } else if (hitEnvEntity != null && !hitEnvEntity.passableBy.intersect(entity.getTravelType())) { entity.attack(hitEnvEntity, dir); } if (sound != null) { sound.play(hitTile); } } }; SpriteEffect effect = new SpriteEffect( sprite, Direction.CENTER, weapon != null && weapon.light != null ? weapon.light.copyNoFlag() : null); tile.spriteEffects.add(effect); } else { // do on hit for (GameEventHandler handler : entity.getAllHandlers()) { handler.onHit(entity, tile); } if (tile.entity != null && !tile.entity.isAllies(entity)) { entity.attack(tile.entity, dir); } else if (tile.environmentEntity != null && !tile.environmentEntity.passableBy.intersect(entity.getTravelType())) { entity.attack(tile.environmentEntity, dir); } if (tile.x < minPoint.x) { minPoint.x = tile.x; } if (tile.x > maxPoint.x) { maxPoint.x = tile.x; } if (tile.y < minPoint.y) { minPoint.y = tile.y; } if (tile.y > maxPoint.y) { maxPoint.y = tile.y; } } } } if (weapon != null && weapon.wepDef != null && weapon.wepDef.hitType == Item.WeaponDefinition.HitType.ALL) { // Use a joined sprite Sprite sprite = hitEffect.copy(); sprite.rotation = dir.getAngle(); sprite.baseScale[0] = (maxPoint.x - minPoint.x) + 1; sprite.baseScale[1] = (maxPoint.y - minPoint.y) + 1; if (dir == Direction.WEST || dir == Direction.EAST) { float temp = sprite.baseScale[0]; sprite.baseScale[0] = sprite.baseScale[1]; sprite.baseScale[1] = temp; } SpriteEffect effect = new SpriteEffect( sprite, Direction.CENTER, weapon != null && weapon.light != null ? weapon.light.copyNoFlag() : null); int px = minPoint.x; int py = minPoint.y; float dx = (maxPoint.x - minPoint.x) / 2.0f; float dy = (maxPoint.y - minPoint.y) / 2.0f; px += dir.getX() < 0 ? Math.ceil(dx) : Math.floor(dx); py += dir.getY() < 0 ? Math.ceil(dy) : Math.floor(dy); GameTile tile = attackedTiles.first().level.getGameTile(px, py); tile.spriteEffects.add(effect); SoundInstance sound = hitEffect.sound; if (sound != null) { sound.play(tile); } } }