/**
* THIS IS CREATED BY tom_mai78101. PLEASE GIVE CREDIT FOR WORKING ON A CLONE.
*
* ALL WORKS COPYRIGHTED TO The Pokémon Company and Nintendo. I REPEAT, THIS IS A CLONE.
*
* YOU MAY NOT SELL COMMERCIALLY, OR YOU WILL BE PROSECUTED BY The Pokémon Company AND Nintendo.
*
* THE CREATOR IS NOT LIABLE FOR ANY DAMAGES DONE. FOLLOW LOCAL LAWS, BE RESPECTFUL, AND HAVE A GOOD DAY!
* */
package level;
import item.ItemText;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import main.Game;
import obstacle.Obstacle;
import screen.BaseScreen;
import submenu.Inventory;
import abstracts.Item;
import abstracts.Tile;
import abstracts.World;
import dialogue.NewDialogue;
import entity.Player;
public class OverWorld extends World {
// Overworld properties.
private boolean invertBitmapColors;
private int currentAreaSectorID;
private NewDialogue[] newDialogues;
private int newDialoguesIterator;
/**
* Initializes the overworld in the game.
*
* All game entities are to be loaded through this method.
*
* @param Player
* Takes a Player object. The overworld then loads all related properties in respect to the Player object.
* */
public OverWorld(Player player, Game game) {
// There should be a maximum number of areas available for the OverWorld.
// All areas defined must be placed in WorldConstants.
// Player and Game.
super(player, game);
this.worldID = WorldConstants.OVERWORLD;
if (!this.areas.isEmpty())
this.areas.clear();
WorldConstants.getAllNewScripts();
this.areas = WorldConstants.getAllNewAreas();
// Overworld properties
this.invertBitmapColors = false;
// Going to set this area as test default only. This will need to change in the future.
this.currentArea = this.areas.get(0);
this.setCurrentArea(this.areas.get(0));
this.currentArea.setPlayer(player);
this.currentArea.setDebugDefaultPosition();
this.setCurrentAreaSector(0);
// TODO: Add a method that executes according to the sector ID. Basically,
// it needs to tell the player that they entered a new sector.
// Needs a marker in the area that points to where the area connects together.
// Dialogue
this.newDialogues = null;
this.newDialoguesIterator = 0;
}
// Will add this in the future. Currently, the only entity is Player.
// public void addEntity(Entity e) {
// //e.initialize(this);
// //this.tiles.add(e);
// }
// Worlds no longer need to calculate total width and height.
// public int getTotalWidth() {
// int result = 0;
// for (Area a : areas) {
// if (a != null)
// result += a.getWidth();
// }
// return result;
// }
//
// public int getTotalHeight() {
// int result = 0;
// for (Area a : areas) {
// if (a != null)
// result += a.getHeight();
// }
// return result;
// }
// Not sure if these width and height values are useful...
public int getCurrentAreaWidth() {
return this.currentArea.getWidth();
}
public int getCurrentAreaHeight() {
return this.currentArea.getHeight();
}
@Override
public void tick() {
if (!this.invertBitmapColors)
this.player.tick();
if (this.currentArea == null)
this.currentArea = this.areas.get(0);
this.currentArea.tick();
if (this.currentArea.playerIsInWarpZone() || (this.currentArea.isDisplayingExitArrow() && this.player.isColliding())) {
this.handleWarpPointEvent();
}
if (!this.player.isLockedWalking()) {
if (this.currentArea != null) {
if (this.currentArea.getSectorID() != this.currentAreaSectorID) {
this.currentAreaSectorID = this.currentArea.getSectorID();
// This is where you get the latest sector id at.
System.out.println("Area: " + this.currentArea.getAreaID() + " Sector: " + currentArea.getSectorID());
}
}
}
this.handlePlayerInteractions();
this.handleDialogues();
}
/**
* <p>Handles player interactions with objects in the world. When the player is interacting, it passes the interacted object's interaction ID number
* to the OverWorld, where it handles the interaction ID accordingly.
* </p>
*
* */
private void handlePlayerInteractions() {
// TODO: Fix the awkward interaction caused by so many states not working properly.
int interactionID = player.getInteractionID();
if (this.player.isInteracting() && interactionID != 0 && !this.currentArea.isBeingTriggered()) {
int alpha = (interactionID >> 24) & 0xFF;
int red = (interactionID >> 16) & 0xFF;
switch (alpha) {
case 0x03: {// Obstacles
switch (red) {
case 0x05: {// Signs
int dialogueID = (interactionID & 0xFFFF);
SIGN_LOOP: for (Map.Entry<NewDialogue, Integer> entry : WorldConstants.signTexts) {
if (entry.getValue() == dialogueID) {
this.newDialogues = new NewDialogue[] { entry.getKey() };
break SIGN_LOOP;
}
}
break;
}
default: // Other obstacles
ArrayList<Obstacle> list = this.currentArea.getObstaclesList();
OBSTACLE_LOOP: for (int i = 0; i < list.size(); i++) {
Obstacle obstacle = list.get(i);
if (obstacle.getID() != red)
continue;
this.newDialogues = obstacle.getDialogues();
break OBSTACLE_LOOP;
}
break;
}
break;
}
case 0x0A: {// Item
ItemText text = null;
for (Entry<ItemText, Item> entry : WorldConstants.items) {
if (entry.getKey().id == red) {
text = entry.getKey();
break;
}
}
if (this.newDialogues == null) {
this.newDialogues = new NewDialogue[] { NewDialogue.createText(text.itemName + " has been found.", NewDialogue.MAX_STRING_LENGTH, NewDialogue.DIALOGUE_ALERT, true) };
new Thread(new Runnable() {
@Override
public void run() {
PixelData data = currentArea.getCurrentPixelData();
switch (player.getFacing()) {
case Player.UP:
currentArea.setPixelData(data, player.getXInArea(), player.getYInArea() - 1);
break;
case Player.DOWN:
currentArea.setPixelData(data, player.getXInArea(), player.getYInArea() + 1);
break;
case Player.LEFT:
currentArea.setPixelData(data, player.getXInArea() - 1, player.getYInArea());
break;
case Player.RIGHT:
currentArea.setPixelData(data, player.getXInArea() + 1, player.getYInArea());
break;
}
}
}).start();
Inventory inventory = this.game.getStartMenu().getInventory();
inventory.addItem(text);
}
break;
}
}
}
else {
if (this.currentArea != null && !this.currentArea.isBeingTriggered()) {
if (Player.isMovementsLocked())
Player.unlockMovements();
}
}
}
private void handleDialogues() {
if (this.newDialogues != null) {
// The order is IMPORTANT!!
if (this.newDialogues.length == 1) {
if (this.newDialogues[this.newDialoguesIterator].isDialogueCompleted() && this.newDialogues[this.newDialoguesIterator].isScrolling()) {
Player.unlockMovements();
this.newDialogues[this.newDialoguesIterator].resetDialogue();
this.newDialogues = null;
this.newDialoguesIterator = 0;
this.player.stopInteraction();
}
else if (this.newDialogues[this.newDialoguesIterator].isDialogueCompleted() && !this.newDialogues[this.newDialoguesIterator].isScrolling()) {
this.newDialogues[this.newDialoguesIterator].tick();
}
else if (this.newDialogues[this.newDialoguesIterator].isDialogueTextSet() && !(this.newDialogues[this.newDialoguesIterator].isDialogueCompleted() && this.newDialogues[this.newDialoguesIterator].isShowingDialog())) {
Player.lockMovements();
this.newDialogues[this.newDialoguesIterator].tick();
}
}
else {
switch (this.newDialogues[this.newDialoguesIterator].getDialogueType()) {
case NewDialogue.DIALOGUE_SPEECH:
if (this.newDialogues[this.newDialoguesIterator].isDialogueCompleted() && this.newDialogues[this.newDialoguesIterator].isScrolling()) {
Player.unlockMovements();
this.newDialogues[this.newDialoguesIterator].resetDialogue();
if (this.newDialoguesIterator < this.newDialogues.length - 1) {
this.newDialoguesIterator++;
this.handleDialogues();
}
else {
this.newDialogues = null;
this.newDialoguesIterator = 0;
this.player.stopInteraction();
}
}
else if (this.newDialogues[this.newDialoguesIterator].isDialogueCompleted() && !this.newDialogues[this.newDialoguesIterator].isScrolling()) {
if (!this.newDialogues[this.newDialoguesIterator].isShowingDialog()) {
Player.unlockMovements();
this.newDialogues[this.newDialoguesIterator].resetDialogue();
if (this.newDialoguesIterator < this.newDialogues.length - 1) {
this.newDialoguesIterator++;
this.handleDialogues();
}
else {
this.newDialogues = null;
this.newDialoguesIterator = 0;
this.player.stopInteraction();
}
}
else
this.newDialogues[this.newDialoguesIterator].tick();
}
else if (this.newDialogues[this.newDialoguesIterator].isDialogueTextSet() && !(this.newDialogues[this.newDialoguesIterator].isDialogueCompleted() && this.newDialogues[this.newDialoguesIterator].isShowingDialog())) {
Player.lockMovements();
this.newDialogues[this.newDialoguesIterator].tick();
}
break;
case NewDialogue.DIALOGUE_QUESTION:
if (!this.newDialogues[this.newDialoguesIterator].yesNoQuestionHasBeenAnswered()) {
this.newDialogues[this.newDialoguesIterator].tick();
if (!Player.isMovementsLocked())
Player.lockMovements();
}
if (this.newDialogues[this.newDialoguesIterator].getAnswerToSimpleQuestion() == Boolean.TRUE) {
this.newDialogues[this.newDialoguesIterator].resetDialogue();
if (this.newDialoguesIterator < this.newDialogues.length - 1) {
this.newDialoguesIterator++;
this.handleDialogues();
}
else {
this.newDialogues[this.newDialoguesIterator].resetDialogue();
this.newDialogues = null;
this.newDialoguesIterator = 0;
this.player.stopInteraction();
Player.unlockMovements();
}
}
else if (this.newDialogues[this.newDialoguesIterator].getAnswerToSimpleQuestion() == Boolean.FALSE) {
this.newDialogues[this.newDialoguesIterator].resetDialogue();
this.newDialogues = null;
this.newDialoguesIterator = 0;
this.player.stopInteraction();
Player.unlockMovements();
}
break;
}
}
}
}
private void handleWarpPointEvent() {
boolean currentAreaFound = false;
int currentAreaID = 0;
if (WorldConstants.isModsEnabled.booleanValue() && this.currentArea.getAreaID() < 1000)
currentAreaID = this.currentArea.getAreaID() + 1000;
else
currentAreaID = this.currentArea.getAreaID();
// boolean doorIsLocked = false;
for (int i = 0; i < this.areas.size(); i++) {
if (this.areas.get(i) == null) {
// Door needs to be blocking if there is no area to walk to.
// doorIsLocked = true;
continue;
}
if (this.areas.get(i).getAreaID() == currentAreaID) {
this.areas.set(i, this.currentArea);
currentAreaFound = true;
break;
}
}
if (currentAreaFound) {
PixelData data = this.currentArea.getCurrentPixelData();
int targetAreaID = 0;
if (WorldConstants.isModsEnabled.booleanValue() && this.currentArea.getAreaID() < 1000)
targetAreaID = data.getTargetAreaID() + 1000;
else
targetAreaID = data.getTargetAreaID();
this.currentArea = WorldConstants.convertToArea(areas, targetAreaID);
if (currentArea == null)
return;
this.currentArea.setPlayer(this.player);
this.currentArea.setDefaultPosition(data);
this.invertBitmapColors = true;
switch ((data.getColor() >> 24) & 0xFF) {
case 0x04: // Warp point
this.player.forceLockWalking();
break;
case 0x09: // Door
this.player.tick();
break;
case 0x0B: // Carpet (Indoors)
case 0x0C: // Carpet (Outdoors)
this.player.forceLockWalking();
this.player.tick();
break;
}
this.currentArea.playerWentPastWarpZone();
}
// else if (doorIsLocked) {
// PixelData data = this.currentArea.getCurrentPixelData();
// //Pixel data color, alpha value is 0x09 = House door
// if (((data.getColor() >> 24) & 0xFF) == 0x09){
//
// }
// // int targetAreaID = 0;
// // if (WorldConstants.isModsEnabled.booleanValue() && this.currentArea.getAreaID() < 1000)
// // targetAreaID = data.getTargetAreaID() + 1000;
// // else
// // targetAreaID = data.getTargetAreaID();
// }
}
protected void renderTiles(BaseScreen screen, int x0, int y0, int x1, int y1) {
for (int y = y0; y < y1; y++) {
for (int x = x0; x < x1; x++) {
this.currentArea.renderTiles(screen, x, y);
}
}
}
@Override
public void render(BaseScreen screen, int xPlayerPos, int yPlayerPos) {
// OverWorld offsets are not set.
// Setting area offsets with player positions
screen.setOffset(screen.getWidth() / 2 - Tile.WIDTH, (screen.getHeight() - Tile.HEIGHT) / 2);
if (this.currentArea != null)
this.currentArea.renderTiles(screen, xPlayerPos, yPlayerPos);
screen.setOffset(0, 0);
if (this.invertBitmapColors) {
if (screen.getRenderingEffectTick() == (byte) 0x7) {
screen.setRenderingEffectTick((byte) 0x0);
}
this.invertBitmapColors = screen.invert();
}
if (screen.getRenderingEffectTick() < (byte) 0x4 || screen.getRenderingEffectTick() >= (byte) 0x7)
player.render(screen, 0, 0);
if (this.newDialogues != null && this.newDialogues.length > 0) {
NewDialogue.renderDialogBox(screen, 0, 6, 9, 2);
this.newDialogues[this.newDialoguesIterator].render(screen, screen.getBufferedImage().createGraphics());
}
}
// private void renderTiles(BaseScreen screen, Area area, int xPosition, int yPosition, int xOff, int yOff) {
// //Unsure at the moment.
// // area.setPosition(xPosition, yPosition);
// // area.renderTiles(screen, -xOff, -yOff);
// }
public Tile getTile(int x, int y) {
/*
* if (pixels[y * this.width + x] != 0xFF00FF00) return new Tree();
*/
return null;
}
public void addTile(Tile t) {
// this.tiles.add(t);
}
// ---------------------------------------------------------------------------------------
// Private methods
private void setCurrentAreaSector(int i) {
this.currentAreaSectorID = i;
}
}