private void renderTile(TileNode tileNode, Graphics2D g, float opacity) {

    // Do the actual Drawing here!
    Polygon tilePolygon = getHexTile(tileNode.pixelPoint);
    g.setColor(Color.BLACK);
    g.drawPolygon(
        tilePolygon); // This part kinda helps the tiles come together. Due to the math involved in
                      // rendering
    // The hex tiles, there are a few points where we have to cast to an int and lose precision.

    // Get the old clip (Should be the entire window).
    Shape oldClip = g.getClip();

    // Set the clip to just the hex tile
    g.setClip(tilePolygon);

    // Set the opacity.
    AlphaComposite acomp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
    g.setComposite(acomp);

    // Render the tile image.
    Image tileImage = tileNode.tile.getTileImage();
    int tileX = (int) (tileNode.pixelPoint.getX() - hexWidth / 2);
    int tileY = (int) (tileNode.pixelPoint.getY()) - hexHeight / 2;
    g.drawImage(tileImage, tileX, tileY, hexWidth, hexHeight, getDisplay());

    // Add this entity to list of entities and their locations to render its health later alligator
    if (tileNode.tile.getEntity() != null) {
      Entity entity = tileNode.tile.getEntity();
      Stats stats = entity.getStats();
      this.entityLocationTuples.add(
          new EntityLocationTuple(
              entity,
              new Point((int) tileNode.pixelPoint.getX(), (int) tileNode.pixelPoint.getY())));
      this.entityHealthMap.put(entity, stats.getStat(Stats.Type.HEALTH));
    }

    g.setClip(oldClip);
  }
  private void drawSkillRectAndBoxes(Graphics g) {

    // Draw outline
    g.setColor(goldTrim);

    // Fill
    g.drawRect(skillBoxStartX, skillBoxStartY, skillRectWidth, skillRectHeight);
    g.setColor(Color.darkGray);
    g.fillRect(skillBoxStartX, skillBoxStartY, skillRectWidth, skillRectHeight);

    // Values needed to draw
    int skillBoxX = skillBoxStartX;
    int skillBoxY = skillBoxStartY;
    int topAndSideMargin = skillBoxSize / 28;
    Color coolDownFontColor = Color.RED;
    Rectangle2D skillRect;
    Rectangle2D textRect;
    String skillText;
    String keyBind;
    Skill currentSkill;

    // Draw each box, loop thru each skill
    for (int i = 0; i < skillCount; i++) {
      currentSkill = skills.get(i);

      // Draw skill box
      g.setColor(goldTrim);
      g.drawRect(skillBoxX, skillBoxY, skillBoxSize, skillBoxSize);

      // TODO: Do draw image when have images. Not rly a large priority tbh
      // Draw item image
      Image skillImage = currentSkill.getSprite().getImage();
      g.drawImage(
          skillImage,
          skillBoxX + (skillBoxSize - imgSize) / 2,
          skillBoxY + (skillBoxSize - imgSize) / 2,
          imgSize,
          imgSize,
          null);

      // Draw skill image

      // Draw skill name
      g.setColor(Color.white);
      g.setFont(skillLabelFont);
      skillText = currentSkill.getName();
      fm = g.getFontMetrics(skillLabelFont);
      textRect = fm.getStringBounds(skillText, g);
      drawSkillName(g, skillText, textRect, skillBoxY, skillBoxX);

      // Draw Keybind in Upper Left Corner
      // Only active skils have keybinds
      if (currentSkill.isActive()) {
        // Set font
        g.setFont(keyBindFont);
        fm = g.getFontMetrics(keyBindFont);
        g.setColor(goldTrim);

        // Get keybind
        ActiveSkill currentActiveSkill = (ActiveSkill) currentSkill;
        int keyCode = currentActiveSkill.getKeyBind();
        keyBind = KeyEvent.getKeyText(keyCode);
        textRect = fm.getStringBounds(keyBind, g);
        g.drawString(
            keyBind,
            skillBoxX + (int) textRect.getWidth() / 2 + topAndSideMargin,
            skillBoxY + (int) textRect.getHeight() - 1);
      }

      // Set font
      g.setFont(skillLabelFont);
      fm = g.getFontMetrics(skillLabelFont);
      g.setColor(Color.WHITE);

      // Draw Skill level in Upper Right Corner
      String skillLvl = "Lvl " + Integer.toString(currentSkill.getLevel());
      textRect = fm.getStringBounds(skillLvl, g);
      g.drawString(
          skillLvl,
          skillBoxX + skillBoxSize - (int) textRect.getWidth() - topAndSideMargin,
          skillBoxY + (int) textRect.getHeight() + topAndSideMargin);

      // Draw cool down in center, if skill is coolin down
      if (currentSkill.isCooldown()) {
        double currentTime = currentSkill.getCooldownTimeRemaining();
        drawAndUpdateCoolDown(g, skillBoxX, skillBoxY, currentTime, currentSkill);
      }

      // Draw option to level up this skill if have skill points
      if (stats.getStat(Stats.Type.SKILL_POINTS) > 0) {
        drawSkillLevelUpBox(g, skillBoxX, skillBoxY);
      }

      // Increment x position
      skillBoxX += skillBoxSize;
    }
  }
 private void levelUpSkill(Skill skill) {
   skill.incrementLevel();
   stats.decrementSkillPoints();
 }
  private void drawEntityHealthBar(Graphics g, EntityLocationTuple entityLocationHealthTriple) {
    Point p = entityLocationHealthTriple.point;
    Entity entity = entityLocationHealthTriple.entity;

    int oldHealth = entityHealthMap.get(entity).intValue();

    int entityX = (int) p.getX() - hexWidth * 3 / 8;
    int entityY = (int) p.getY() - hexHeight * 3 / 8;

    Stats stats = entity.getStats();

    int entitysCurrentActualHealth = stats.getStat(Stats.Type.HEALTH);
    // Only render health on NPCs
    // Also only update health bar, if the entities current health is diff than its old health
    if (!(entity == avatar)) {

      if (!entityEffedUpHealthMap.containsKey(entity) || oldHealth != entitysCurrentActualHealth) {

        System.out.println("CHANGIN ENTITY HEALTH");

        Skill observation = avatar.getSpecificSkill(Skill.SkillDictionary.OBSERVATION);
        ObservationSkill observationSkill = (ObservationSkill) observation;
        observationSkill.onUpdate(entity);

        int effedUpHealth = observationSkill.getCombatError(entitysCurrentActualHealth);

        entityEffedUpHealthMap.put(entity, effedUpHealth);
        entityHealthMap.put(entity, entitysCurrentActualHealth);
      }

      //            int health = entityEffedUpHealthMap.get(entity);
      int health = entitysCurrentActualHealth + entityEffedUpHealthMap.get(entity);

      int maxHealth = stats.getStat(Stats.Type.MAX_HEALTH);

      health = health > maxHealth ? maxHealth : health;
      health = health < 0 ? 0 : health;

      // Sizes
      int healthBarWidth = getScreenWidth() / 12;
      int healthBarHeight = getScreenHeight() / 53;

      // Set the font
      Font f = new Font("Courier New", 1, 14);
      g.setFont(f);

      // Set the location and size of the health bar.
      int healthBarX = entityX - healthBarWidth / 3;
      int healthBarY = entityY - healthBarHeight;

      // Draw the outline of the health bar.
      g.setColor(Color.RED);
      g.fillRect(healthBarX, healthBarY, healthBarWidth, healthBarHeight);

      // Determine what fraction of the healthbar should be shown.
      double healthFraction = (double) health / (double) maxHealth;
      int healthFillWidth = (int) (healthFraction * healthBarWidth);

      // Fill the healthbar
      g.setColor(Color.GREEN);
      g.fillRect(healthBarX, healthBarY, healthFillWidth, healthBarHeight);

      // Display the fraction of health
      g.setColor(Color.WHITE);
      String healthFractionString = "(" + health + "/" + maxHealth + ")";
      FontMetrics fm = g.getFontMetrics(f);

      // Place the font at the right of the bar
      Rectangle2D healthFractionRect = fm.getStringBounds(healthFractionString, g);

      int healthFractionX = healthBarX + (healthBarWidth - (int) healthFractionRect.getWidth()) / 2;
      int healthFractionY = healthBarY + healthBarHeight - 4;

      g.drawString(healthFractionString, healthFractionX, healthFractionY);
    }
  }