Package org.pokenet.server.battle.impl

Source Code of org.pokenet.server.battle.impl.NpcBattleField

package org.pokenet.server.battle.impl;

import org.pokenet.server.backend.entity.NonPlayerChar;
import org.pokenet.server.backend.entity.PlayerChar;
import org.pokenet.server.battle.BattleField;
import org.pokenet.server.battle.BattleTurn;
import org.pokenet.server.battle.Pokemon;
import org.pokenet.server.battle.mechanics.BattleMechanics;
import org.pokenet.server.battle.mechanics.MoveQueueException;
import org.pokenet.server.battle.mechanics.statuses.StatusEffect;
import org.pokenet.server.battle.mechanics.statuses.field.FieldEffect;
import org.pokenet.server.battle.mechanics.statuses.field.HailEffect;
import org.pokenet.server.battle.mechanics.statuses.field.RainEffect;
import org.pokenet.server.battle.mechanics.statuses.field.SandstormEffect;
import org.pokenet.server.feature.TimeService;
import org.pokenet.server.network.TcpProtocolHandler;
import org.pokenet.server.network.message.battle.BattleEndMessage;
import org.pokenet.server.network.message.battle.BattleInitMessage;
import org.pokenet.server.network.message.battle.BattleMessage;
import org.pokenet.server.network.message.battle.BattleMoveMessage;
import org.pokenet.server.network.message.battle.BattleMoveRequest;
import org.pokenet.server.network.message.battle.BattleRewardMessage;
import org.pokenet.server.network.message.battle.EnemyDataMessage;
import org.pokenet.server.network.message.battle.FaintMessage;
import org.pokenet.server.network.message.battle.HealthChangeMessage;
import org.pokenet.server.network.message.battle.NoPPMessage;
import org.pokenet.server.network.message.battle.StatusChangeMessage;
import org.pokenet.server.network.message.battle.SwitchMessage;
import org.pokenet.server.network.message.battle.SwitchRequest;
import org.pokenet.server.network.message.battle.BattleEndMessage.BattleEnd;
import org.pokenet.server.network.message.battle.BattleRewardMessage.BattleRewardType;

/**
* A battlefield for NPC battles
* @author shadowkanji
*
*/
public class NpcBattleField extends BattleField {
  private PlayerChar m_player;
  private NonPlayerChar m_npc;
  private BattleTurn[] m_turn = new BattleTurn[2];
  private boolean m_finished = false;

  /**
   * Constructor
   * @param mech
   * @param p
   * @param n
   */
  public NpcBattleField(BattleMechanics mech, PlayerChar p, NonPlayerChar n) {
    super(mech, new Pokemon[][] { p.getParty(), n.getParty(p) });
    /* Store the player and npc */
    m_player = p;
    m_npc = n;

    /* Start the battle */
    TcpProtocolHandler.writeMessage(p.getTcpSession(),
        new BattleInitMessage(false, getAliveCount(1)));
    /* Send enemy's Pokemon data */
    sendPokemonData(p);
    /* Set the player's battle id */
    m_player.setBattleId(0);
    /* Send enemy name */
    m_player.getTcpSession().write("bn" + m_npc.getName());
    /* Apply weather and request moves */
    applyWeather();
    requestMoves();
  }
 
  /**
   * Sends pokemon data to the client
   * @param receiver
   */
  private void sendPokemonData(PlayerChar receiver) {
    for (int i = 0; i < this.getParty(1).length; i++) {
      if (this.getParty(1)[i] != null) {
        TcpProtocolHandler.writeMessage(receiver.getTcpSession(),
            new EnemyDataMessage(i, getParty(1)[i]));
      }
    }
  }

  @Override
  public void applyWeather() {
    if (m_player.getMap().isWeatherForced()) {
      switch (m_player.getMap().getWeather()) {
      case NORMAL:
        return;
      case RAIN:
        this.applyEffect(new RainEffect());
        return;
      case HAIL:
        this.applyEffect(new HailEffect());
        return;
      case SANDSTORM:
        this.applyEffect(new SandstormEffect());
        return;
      default:
        return;
      }
    } else {
      FieldEffect f = TimeService.getWeatherEffect();
      if (f != null) {
        this.applyEffect(f);
      }
    }
  }

  @Override
  public void clearQueue() {
    m_turn[0] = null;
    m_turn[1] = null;
  }

  @Override
  public BattleTurn[] getQueuedTurns() {
    return m_turn;
  }

  @Override
  public String getTrainerName(int idx) {
    if(idx == 0)
      return m_player.getName();
    else
      return m_npc.getName();
  }

  @Override
  public void informPokemonFainted(int trainer, int idx) {
    if (m_player != null)
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new FaintMessage(getParty(trainer)[idx].getSpeciesName()));
  }

  @Override
  public void informPokemonHealthChanged(Pokemon poke, int change) {
    if (m_player != null) {
      if (getActivePokemon()[0] == poke) {
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new HealthChangeMessage(0 , change));
      } else if(getActivePokemon()[1] == poke) {
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new HealthChangeMessage(1 , change));
      } else {
        int index = getPokemonPartyIndex(0, poke);
        if(index > -1) {
          m_player.getTcpSession().write("Ph" + String.valueOf(index) + poke.getHealth());
          return;
        }
        //TODO: Add support for NPC pokemon healing for pokemon in pokeballs
      }
    }
  }

  @Override
  public void informStatusApplied(Pokemon poke, StatusEffect eff) {
    if(m_finished)
      return;
    if (m_player != null) {
      if (getActivePokemon()[0].compareTo(poke) == 0)
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new StatusChangeMessage(0,
                poke.getSpeciesName(),
                eff.getName(), false));
      else if(poke.compareTo(getActivePokemon()[1]) == 0)
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new StatusChangeMessage(1,
                poke.getSpeciesName(),
                eff.getName(), false));
    }
  }

  @Override
  public void informStatusRemoved(Pokemon poke, StatusEffect eff) {
    if(m_finished)
      return;
    if (m_player != null) {
      if (getActivePokemon()[0].compareTo(poke) == 0 &&
          !getActivePokemon()[0].isFainted())
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new StatusChangeMessage(0,
                poke.getSpeciesName(),
                eff.getName(), true));
      else if(poke.compareTo(getActivePokemon()[1]) == 0 &&
          !getActivePokemon()[1].isFainted())
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new StatusChangeMessage(1,
                poke.getSpeciesName(),
                eff.getName(), true));
    }
  }

  @Override
  public void informSwitchInPokemon(int trainer, Pokemon poke) {
    if(m_player != null) {
      if (trainer == 0) {
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new SwitchMessage(m_player.getName(),
                poke.getSpeciesName(),
                trainer,
                getPokemonPartyIndex(trainer, poke)));
      } else {
        TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
            new SwitchMessage(m_npc.getName(),
                poke.getSpeciesName(),
                trainer,
                getPokemonPartyIndex(trainer, poke)));
      }
    }
  }

  @Override
  public void informUseMove(Pokemon poke, String name) {
    if (m_player != null)
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new BattleMoveMessage(poke.getSpeciesName(), name));
  }

  @Override
  public void informVictory(int winner) {
    m_finished = true;
    int money = getParty(1)[0].getLevel() * (getMechanics().getRandom().nextInt(4) + 1);
    if (winner == 0) {
      /* Reward the player */

      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new BattleRewardMessage(BattleRewardType.MONEY,
          money));
      m_player.setMoney(m_player.getMoney() + money);
      /* End the battle */
      m_player.removeTempStatusEffects();
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new BattleEndMessage(BattleEnd.WON));
      /* Now add Trainer EXP */
      int trainerExp = 0;
      for(int i = 0; i < getParty(1).length; i++) {
        if(getParty(1)[i] != null)
          trainerExp += getParty(1)[i].getLevel() / 2;
      }
      /* If the player got a badge, triple the EXP gained */
      if(m_npc.isGymLeader() && !m_player.hasBadge(m_npc.getBadge()))
        trainerExp *= 2;
      if(trainerExp > 0)
        m_player.addTrainingExp(trainerExp);
      /* Give the player the badge if it's a gym leader */
      if(m_npc.isGymLeader()) {
        m_player.addBadge(m_npc.getBadge());
      }
    } else {
      if(m_player.getMoney() - money >= 0) {
        m_player.setMoney(m_player.getMoney() - money);
      } else {
        m_player.setMoney(0);
      }
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new BattleEndMessage(BattleEnd.LOST));
      m_player.lostBattle();
    }
    m_player.updateClientMoney();
    m_player.setBattling(false);
    m_player.setTalking(false);
    dispose();
    if (m_dispatch != null) {
      /*
       * This very bad programming but shoddy does it and forces us to do
       * it
       */
      /*Thread t = m_dispatch;
      m_dispatch = null;
      t.stop(); let the thread manually return.*/
    }
  }

  @Override
  public void queueMove(int trainer, BattleTurn move)
      throws MoveQueueException {
    /* Check if move exists */
    if(move.isMoveTurn() && move.getId() != -1 &&
        getActivePokemon()[trainer].getMove(move.getId()) == null) {
      requestMove(trainer);
      return;
    }
    /* Handle forced switches */
    if(m_isWaiting && m_replace != null && m_replace[trainer]) {
      if(!move.isMoveTurn()) {
        if(getActivePokemon()[trainer].compareTo(this.getParty(trainer)[move.getId()]) != 0) {
          this.switchInPokemon(trainer, move.getId());
          m_replace[trainer] = false;
          m_isWaiting = false;
          return;
        }
      }
      requestPokemonReplacement(trainer);
      return;
    }
    /* Queue the move */
    if(m_turn[trainer] == null) {
      /* Handle Pokemon being unhappy and ignoring you */
      if(trainer == 0 && !getActivePokemon()[0].isFainted()) {
        if(getActivePokemon()[0].getHappiness() <= 40) {
          /* Pokemon is unhappy, they'll do what they feel like */
          showMessage(getActivePokemon()[0].getSpeciesName() + " is unhappy!");
          int moveID = getMechanics().getRandom().nextInt(4);
          while (getActivePokemon()[0].getMove(moveID) == null)
            moveID = getMechanics().getRandom().nextInt(4);
          move = BattleTurn.getMoveTurn(moveID);
        } else if(getActivePokemon()[0].getHappiness() < 70) {
          /* Pokemon is partially unhappy, 50% chance they'll listen to you */
          if(getMechanics().getRandom().nextInt(2) == 1) {
            showMessage(getActivePokemon()[0].getSpeciesName() + " is unhappy!");
            int moveID = getMechanics().getRandom().nextInt(4);
            while (getActivePokemon()[0].getMove(moveID) == null)
              moveID = getMechanics().getRandom().nextInt(4);
            move = BattleTurn.getMoveTurn(moveID);
          }
        }
      }
      if (move.getId() == -1) {
        if (m_dispatch == null
            && ((trainer == 0 && m_turn[1] != null) ||
                (trainer == 1 && m_turn[0] != null))) {
          m_dispatch = new Thread(new Runnable() {
            public void run() {
              executeTurn(m_turn);
              m_dispatch = null;
            }
          });
          m_dispatch.start();
          return;
        }
      } else {
        // Handle a fainted pokemon
        if (this.getActivePokemon()[trainer].isFainted()) {
          if (!move.isMoveTurn() && this.getParty(trainer)[move.getId()] != null
              && this.getParty(trainer)[move.getId()].getHealth() > 0) {
            switchInPokemon(trainer, move.getId());
            requestMoves();
            return;
          } else {
            // The player still has pokemon left
            if (getAliveCount(trainer) > 0) {
              requestPokemonReplacement(trainer);
              return;
            } else {
              // the player has no pokemon left. Announce winner
              if (trainer == 0)
                this.informVictory(1);
              else
                this.informVictory(0);
              return;
            }
          }
        } else {
          // The turn was used to attack!
          if (move.isMoveTurn()) {
            // Handles Struggle
            if (getActivePokemon()[trainer].mustStruggle())
              m_turn[trainer] = BattleTurn.getMoveTurn(-1);
            else {
              // The move has no more PP
              if (this.getActivePokemon()[trainer].getPp(move
                  .getId()) <= 0) {
                if (trainer == 0) {
                  TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
                      new NoPPMessage(this.getActivePokemon()[trainer]
                        .getMoveName(move.getId())));
                  requestMove(0);
                } else {
                  /* Get another move from the npc */
                  requestMove(1);
                }
                return;
              } else {
                // Assign the move to the turn
                m_turn[trainer] = move;
              }
            }
          } else {
            if (this.getActivePokemon()[trainer].isActive() &&
                this.getParty(trainer)[move.getId()] != null &&
                this.getParty(trainer)[move.getId()].getHealth() > 0) {
              m_turn[trainer] = move;
            } else {
              requestMove(trainer);
              return;
            }
          }
        }
      }
    }
    /* Ensures the npc selected a move */
    if(trainer == 0 && m_turn[0] != null && m_turn[1] == null) {
      requestMove(1);
      return;
    }
    if (m_dispatch != null)
      return;
    // Both turns are ready to be performed
    if (m_turn[0] != null && m_turn[1] != null) {
      m_dispatch = new Thread(new Runnable() {
        public void run() {
          executeTurn(m_turn);
          for (int i = 0; i < m_participants; ++i) {
            m_turn[i] = null;
          }
          m_dispatch = null;
        }
      });
      m_dispatch.start();
    }
  }

  @Override
  public void refreshActivePokemon() {
    m_player.getTcpSession().write(
        "bh0" + this.getActivePokemon()[0].getHealth());
    m_player.getTcpSession().write(
        "bh1" + this.getActivePokemon()[1].getHealth());
  }

  @Override
  public void requestAndWaitForSwitch(int party) {
    requestPokemonReplacement(party);
    if (party == 0) {
      /* Request a switch from the player */
      if (!m_replace[party]) {
        return;
      }
      m_isWaiting = true;
      do {
        synchronized (m_dispatch) {
          try {
            m_dispatch.wait(1000);
          } catch (InterruptedException e) {

          }
        }
      } while ((m_replace != null) && m_replace[party]);
    }
  }

  @Override
  protected void requestMove(int trainer) {
    if(trainer == 0) {
      /* Request move from player */
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new BattleMoveRequest());
    } else {
      /* Request move from npc */
      try {
        if(getActivePokemon()[1].hasTypeWeakness(getActivePokemon()[0])
            && this.getAliveCount(1) >= 3) {
          /* The npc should switch out a different Pokemon */
          /* 50:50 chance they will switch */
          if(this.getMechanics().getRandom().nextInt(3) == 0) {
            int index = 0;
            while(this.getParty(1)[index] == null ||
                this.getParty(1)[index].isFainted() ||
                this.getParty(1)[index].compareTo(getActivePokemon()[1]) == 0) {
              try {
                Thread.sleep(100);
              } catch (Exception e) {}
              index = getMechanics().getRandom().nextInt(6);
            }
            this.queueMove(1, BattleTurn.getSwitchTurn(index));
            return;
          }
        }
        /* If they did not switch, select a move */
        int moveID = getMechanics().getRandom().nextInt(4);
        while (getActivePokemon()[1].getMove(moveID) == null)
          moveID = getMechanics().getRandom().nextInt(4);
        queueMove(1, BattleTurn.getMoveTurn(moveID));
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  @Override
  protected void requestMoves() {
    clearQueue();
    requestMove(1);
    requestMove(0);
  }

  @Override
  protected void requestPokemonReplacement(int i) {
    if(i == 0) {
      /* Request Pokemon replacement from player */
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
          new SwitchRequest());
    } else {
      /* Request Pokemon replacement from npc */
      if(getAliveCount(1) == 0) {
        informVictory(0);
      } else {
        try {
          int index = 0;

          while(this.getParty(1)[index] == null ||
              this.getParty(1)[index].isFainted()) {
            try {
              Thread.sleep(100);
            } catch (Exception e) {}
            index = getMechanics().getRandom().nextInt(6);
          }
          this.switchInPokemon(1, BattleTurn.getSwitchTurn(index).getId());
                  requestMoves();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }

  @Override
  public void showMessage(String message) {
    if(m_finished)
      return;
    if(m_player != null)
      TcpProtocolHandler.writeMessage(m_player.getTcpSession(),
        new BattleMessage(message));
  }

  @Override
  public void forceExecuteTurn() {
    if(m_turn[0] == null) {
      m_turn[0] = BattleTurn.getMoveTurn(-1);
    }
    if(m_turn[1] == null) {
      m_turn[1] = BattleTurn.getMoveTurn(-1);
    }
    executeTurn(m_turn);
  }

}
TOP

Related Classes of org.pokenet.server.battle.impl.NpcBattleField

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.