package com.weem.epicinventor.placeable;
import com.weem.epicinventor.*;
import com.weem.epicinventor.actor.*;
import com.weem.epicinventor.actor.monster.*;
import com.weem.epicinventor.inventory.*;
import com.weem.epicinventor.network.*;
import com.weem.epicinventor.utility.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.AffineTransform;
import java.io.*;
import java.util.*;
public abstract class Placeable implements Serializable {
private static final long serialVersionUID = 10000L;
protected transient boolean shouldRender = true;
protected String id = "";
transient protected Registry registry;
protected PlaceableManager placeableManager;
protected int mapX, mapY;
protected int width, height;
protected String standardImage;
protected String animationImage;
protected State currentState;
protected int numAnimationFrames;
protected int currentAnimationFrame;
protected int animationFrameDuration;
protected long animationFrameUpdateTime = 0;
protected final static double DEFAULT_ANIMATION_DURATION = 0.20;
protected boolean isAnimating;
protected boolean isActive;
private boolean isBuilding;
private long buildingTime;
protected int totalBuildTime;
transient protected BufferedImage buildingImage;
transient protected BufferedImage canPlaceImage;
transient protected BufferedImage cantPlaceImage;
protected boolean isDirty;
private boolean isDestroying;
protected int totalHitPoints = 400;
protected int hitPoints;
private boolean isPowered = true;
private boolean noPowerShow;
private float noPowerTotalTime;
private final static float NO_POWER_MAX_TIME = 1.0f;
private final static int NO_POWER_WIDTH = 32;
private final static int NO_POWER_HEIGHT = 32;
protected int powerRequired;
protected int powerGenerated;
protected int fearGenerated;
protected int fearDistance;
protected long fearDuration;
protected int touchDamage;
private long destroyingTime;
private final static int DESTROY_TIME = 10;
protected String type = "";
protected boolean facingRight = true;
protected Rectangle spriteRect;
private long lastDamage = 0;
transient private Player destroyingPlayer;
public enum State {
New,
Placed,
NotPlaced
}
public Placeable(PlaceableManager pm, Registry rg, String sm, String am, int x, int y, Placeable.State cs) {
placeableManager = pm;
registry = rg;
mapX = x;
mapY = y;
hitPoints = totalHitPoints;
isAnimating = false;
isActive = true;
currentState = cs;
animationImage = am;
setImage(sm);
BufferedImage im;
buildingImage = registry.getImageLoader().getImage(standardImage);
buildingImage = ImageLoader.changeToGrayscale(buildingImage);
canPlaceImage = registry.getImageLoader().getImage(standardImage);
canPlaceImage = ImageLoader.changeTransperancy(canPlaceImage, 0.7f);
canPlaceImage = ImageLoader.changeColor(canPlaceImage, (short) 0, (short) 100, (short) 0);
cantPlaceImage = registry.getImageLoader().getImage(standardImage);
cantPlaceImage = ImageLoader.changeTransperancy(cantPlaceImage, 0.7f);
cantPlaceImage = ImageLoader.changeColor(cantPlaceImage, (short) 100, (short) 0, (short) 0);
id = UUID.randomUUID().toString();
}
public void setTransient(Registry rg) {
registry = rg;
placeableManager = rg.getPlaceableManager();
buildingImage = registry.getImageLoader().getImage(standardImage);
buildingImage = ImageLoader.changeToGrayscale(buildingImage);
canPlaceImage = registry.getImageLoader().getImage(standardImage);
canPlaceImage = ImageLoader.changeTransperancy(canPlaceImage, 0.7f);
canPlaceImage = ImageLoader.changeColor(canPlaceImage, (short) 0, (short) 100, (short) 0);
cantPlaceImage = registry.getImageLoader().getImage(standardImage);
cantPlaceImage = ImageLoader.changeTransperancy(cantPlaceImage, 0.7f);
cantPlaceImage = ImageLoader.changeColor(cantPlaceImage, (short) 100, (short) 0, (short) 0);
if (id == null) {
id = UUID.randomUUID().toString();
}
}
public void animateStart() {
if (!animationImage.equals("")) {
loopImage(animationImage);
}
}
public void animateStop() {
setImage(standardImage);
}
public String getId() {
return id;
}
public Point getCenterPoint() {
return new Point(mapX + (width / 2), mapY + (height / 2));
}
public void toggled() {
}
public boolean setDestroying(Player p, boolean destroying) {
destroyingTime = 0;
isDestroying = destroying;
destroyingPlayer = p;
return true;
}
public int applyDamage(Monster source, int damage) {
if (damage > 0) {
if (damage > 80) {
damage = 80;
}
if (!getItemName().equals("ItemContainer")) {
registry.showMessage("Error", "One of your towns is under attack!");
hitPoints -= damage;
lastDamage = registry.currentTime;
registry.getIndicatorManager().createIndicator(mapX + (width / 2), mapY + 50, "-" + Integer.toString(damage));
if (source != null) {
SoundClip cl = new SoundClip(registry, "Monster/Chew" + source.getName() + Rand.getRange(1, 2), getCenterPoint());
} else {
SoundClip cl = new SoundClip(registry, "Monster/Chew", getCenterPoint());
}
if (registry.getGameController().multiplayerMode == registry.getGameController().multiplayerMode.SERVER && registry.getNetworkThread() != null) {
if (registry.getNetworkThread().readyForUpdates()) {
UpdatePlaceable up = new UpdatePlaceable(this.getId());
up.source = source;
up.dataInt = damage;
up.action = "ApplyDamage";
registry.getNetworkThread().sendData(up);
}
}
}
}
return damage;
}
public int attackDamage(Monster source, Rectangle attackRect, int damage) {
int damageTaken = 0;
if (registry.getGameController().multiplayerMode != registry.getGameController().multiplayerMode.CLIENT) {
if (canDestroy() && spriteRect.intersects(attackRect) && hitPoints > 0) {
damageTaken = applyDamage(source, damage);
}
}
return damageTaken;
}
public boolean canDestroy() {
if (currentState == State.Placed && !isBuilding) {
return true;
} else {
return false;
}
}
public Player getDestroyingPlayer() {
return destroyingPlayer;
}
public boolean isDirty() {
return isDirty;
}
public void destroy() {
isDirty = true;
if (registry.getGameController().multiplayerMode != registry.getGameController().multiplayerMode.NONE && registry.getNetworkThread() != null) {
if (registry.getNetworkThread().readyForUpdates()) {
UpdatePlaceable up = new UpdatePlaceable(this.getId());
up.action = "IsDirty";
registry.getNetworkThread().sendData(up);
}
}
}
public String getItemName() {
String parts[];
String itemName = "";
if (standardImage != null) {
parts = standardImage.split("/");
itemName = parts[parts.length - 1];
}
return itemName;
}
public int getHitPoints() {
return hitPoints;
}
public int getTotalHitPoints() {
return totalHitPoints;
}
protected void setImage(String name) {
BufferedImage im = registry.getImageLoader().getImage(name);
if (im != null) {
standardImage = name;
width = im.getWidth();
height = im.getHeight();
spriteRect = new Rectangle(mapX, mapY, width, height);
isAnimating = false;
}
}
public void setHitPoints(int h, int t) {
hitPoints = h;
totalHitPoints = t;
}
public void setInventory(Inventory i) {
}
protected void setState(Placeable.State state) {
if (currentState == State.NotPlaced && state == State.Placed) {
isBuilding = true;
placeableManager.playerDeleteInventory(registry.getPlayerPlacingSlot(registry.getPlayerManager().getCurrentPlayer()), 1);
}
currentState = state;
}
public Placeable.State getState() {
return currentState;
}
protected void setIsPowered(boolean p) {
isPowered = p;
if (isPowered) {
noPowerShow = false;
noPowerTotalTime = 0;
}
}
public void setIsBuilding(boolean b) {
isBuilding = b;
}
protected void loopImage(String name) {
if (registry.getImageLoader().numImages(name) > 1) {
standardImage = name;
BufferedImage im = registry.getImageLoader().getImage(name);
numAnimationFrames = registry.getImageLoader().numImages(name);
width = im.getWidth();
height = im.getHeight();
spriteRect = new Rectangle(mapX, mapY, width, height);
currentAnimationFrame = 0;
animationFrameDuration = (int) (1000 * DEFAULT_ANIMATION_DURATION);
isAnimating = true;
} else {
setImage(name);
}
}
public void stopLooping() {
isAnimating = false;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getPowerGenerated() {
return powerGenerated;
}
public int getPowerRequired() {
return powerRequired;
}
public int getFearGenerated() {
return fearGenerated;
}
public int getFearDistance() {
return fearDistance;
}
public long getFearDuration() {
return fearDuration;
}
public boolean getIsDirty() {
return isDirty;
}
public void setIsDirty(boolean d) {
isDirty = d;
}
public int getTouchDamage() {
return touchDamage;
}
public String getType() {
return type;
}
public boolean handleRightClick(Point clickPoint) {
return false;
}
protected boolean isInside(Point p) {
if (p.x >= mapX
&& p.x <= (mapX + width)
&& p.y >= mapY
&& p.y <= (mapY + height)) {
return true;
}
return false;
}
public boolean isActive() {
return isActive;
}
public boolean isActivated() {
if (canDestroy() && isPowered) {
return true;
} else {
return false;
}
}
public void setActive(boolean a) {
isActive = a;
}
public void setPosition(int x, int y) {
mapX = x;
mapY = y;
}
public int getMapX() {
return mapX;
}
public int getMapY() {
return mapY;
}
public Rectangle getPerimeter() {
return new Rectangle(mapX, mapY, width, height);
}
public boolean checkCanPlace() {
boolean canPlace = true;
if (placeableManager.isOverOther()) {
canPlace = false;
}
if (currentState == Placeable.State.New) {
canPlace = false;
}
return canPlace;
}
public void update() {
if (isActive && isAnimating) {
if (animationFrameUpdateTime <= registry.currentTime) {
currentAnimationFrame++;
if (currentAnimationFrame >= numAnimationFrames) {
currentAnimationFrame = 0;
}
animationFrameUpdateTime = registry.currentTime + animationFrameDuration;
}
}
if (registry.getGameController().multiplayerMode != registry.getGameController().multiplayerMode.CLIENT) {
if (isBuilding) {
buildingTime += registry.getImageLoader().getPeriod();
if ((buildingTime / 1000) >= totalBuildTime) {
buildingTime = 0;
isBuilding = false;
animateStart();
if (!type.isEmpty()) {
registry.showMessage("Success", type + " has finished building!");
}
}
}
if (isDestroying) {
destroyingTime += registry.getImageLoader().getPeriod();
if ((destroyingTime / 1000) >= DESTROY_TIME) {
destroyingTime = 0;
isDestroying = false;
placeableManager.placeableDoneDestroying(this);
}
}
}
//check status of no power
if (!isPowered) {
long p = registry.getImageLoader().getPeriod();
noPowerTotalTime = (noPowerTotalTime
+ registry.getImageLoader().getPeriod())
% (long) (1000 * NO_POWER_MAX_TIME * 2);
if ((noPowerTotalTime / (NO_POWER_MAX_TIME * 1000)) > 1) {
noPowerShow = !noPowerShow;
noPowerTotalTime = 0;
}
}
if (registry.getGameController().multiplayerMode != registry.getGameController().multiplayerMode.CLIENT) {
if (hitPoints <= 0) {
if (!type.isEmpty()) {
registry.showMessage("Error", type + " has been destroyed!");
}
SoundClip cl = new SoundClip(registry, "Placeable/Destroy", getCenterPoint());
BufferedImage im = null;
if (isAnimating) {
im = registry.getImageLoader().getImage(standardImage, currentAnimationFrame);
} else {
im = registry.getImageLoader().getImage(standardImage);
}
registry.getPixelizeManager().pixelize(im, mapX, mapY);
isDirty = true;
}
}
if (getPerimeter().intersects(placeableManager.getPanelRect())) {
shouldRender = true;
} else {
shouldRender = false;
}
}
public void updateLong() {
if (registry.currentTime - lastDamage > 5000 || lastDamage == 0) {
if (hitPoints < totalHitPoints) {
hitPoints++;
} else {
hitPoints = totalHitPoints;
}
}
}
public int getHPRegenerationBonus(Point p) {
//to be overridden
return 0;
}
public float getAttackBonus(Point p) {
//to be overridden
return 0;
}
public void render(Graphics g) {
if (shouldRender) {
if (currentState != Placeable.State.New) {
BufferedImage im;
BufferedImage imLeft;
AffineTransform tx;
AffineTransformOp op;
int xPos = placeableManager.mapToPanelX(mapX);
int yPos = placeableManager.mapToPanelY(mapY);
//flip the yPos since drawing happens top down versus bottom up
yPos = placeableManager.getPHeight() - yPos;
//subtract the height since points are bottom left and drawing starts from top left
yPos -= height;
if (isBuilding) {
if (buildingImage != null) {
g.drawImage(buildingImage, xPos, yPos, null);
}
float timeSpent;
float timeLeft;
float percentage;
int hours = 0;
int minutes = 0;
int seconds = 0;
int x = mapX + (width / 2);
int y = mapY + height;
timeSpent = (float) (buildingTime / 1000f);
timeLeft = (float) totalBuildTime - timeSpent;
if (timeLeft < 0) {
timeLeft = 0;
}
if (timeLeft >= 3600) {
hours = (int) timeLeft / 3600;
timeLeft -= (hours * 3600);
}
if (timeLeft >= 60) {
minutes = (int) timeLeft / 60;
timeLeft -= (minutes * 60);
}
seconds = (int) timeLeft + 1;
percentage = ((float) timeSpent / (float) totalBuildTime) * 100;
placeableManager.displayProgress(g,
x,
y,
(int) percentage,
hours + ":"
+ String.format("%02d", minutes) + ":"
+ String.format("%02d", seconds));
} else if (!isPowered) {
if (buildingImage != null) {
g.drawImage(buildingImage, xPos, yPos, null);
if (noPowerShow) {
Point centerPoint = getCenterPoint();
centerPoint.x -= NO_POWER_WIDTH / 2;
centerPoint.y -= NO_POWER_HEIGHT / 2;
xPos = placeableManager.mapToPanelX(centerPoint.x);
yPos = placeableManager.mapToPanelY(centerPoint.y);
//flip the yPos since drawing happens top down versus bottom up
yPos = placeableManager.getPHeight() - yPos;
//subtract the height since points are bottom left and drawing starts from top left
yPos -= NO_POWER_HEIGHT;
g.drawImage(registry.getImageLoader().getImage("Misc/NoPower"), xPos, yPos, null);
}
/*
* BufferedImage im;
*
* int xPos = placeableManager.mapToPanelX(mapX); int
* yPos = placeableManager.mapToPanelY(mapY);
*
* //flip the yPos since drawing happens top down
* versus bottom up yPos = placeableManager.getPHeight()
* - yPos;
*
* //subtract the height since points are bottom left
* and drawing starts from top left yPos -= height;
*/
}
} else {
if (isAnimating) {
im = registry.getImageLoader().getImage(standardImage, currentAnimationFrame);
} else {
im = registry.getImageLoader().getImage(standardImage);
if (currentState == State.NotPlaced) {
if (placeableManager.isOverOther() || placeableManager.doesRectContainBlocks(mapX + 1, mapY + 1, width - 2, height - 2)) {
im = cantPlaceImage;
} else {
im = canPlaceImage;
}
}
}
if (im != null) {
if (facingRight) {
g.drawImage(im, xPos, yPos, null);
} else {
tx = AffineTransform.getScaleInstance(1, -1);
tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-width, 0);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
imLeft = op.filter(im, null);
if (imLeft != null) {
g.drawImage(imLeft, xPos, yPos, null);
}
}
}
}
if (isDestroying) {
float timeSpent;
float timeLeft;
float percentage;
int hours = 0;
int minutes = 0;
int seconds = 0;
int x = mapX + (width / 2);
int y = mapY + height;
timeSpent = (float) (destroyingTime / 1000f);
timeLeft = (float) DESTROY_TIME - timeSpent;
if (timeLeft < 0) {
timeLeft = 0;
}
if (timeLeft >= 3600) {
hours = (int) timeLeft / 3600;
timeLeft -= (hours * 3600);
}
if (timeLeft >= 60) {
minutes = (int) timeLeft / 60;
timeLeft -= (minutes * 60);
}
seconds = (int) timeLeft + 1;
percentage = ((float) timeSpent / (float) DESTROY_TIME) * 100;
placeableManager.displayProgress(g,
x,
y,
(int) percentage,
hours + ":"
+ String.format("%02d", minutes) + ":"
+ String.format("%02d", seconds));
}
if (hitPoints < totalHitPoints) {
float percentage;
int x = mapX + (width / 2);
int y = mapY + height;
percentage = ((float) hitPoints / (float) totalHitPoints) * 100;
placeableManager.displayHP(g,
x,
y,
(int) percentage);
}
/*
* if (spriteRect != null) { xPos =
* placeableManager.mapToPanelX(spriteRect.x); yPos =
* placeableManager.mapToPanelY(spriteRect.y);
*
* //flip the yPos since drawing happens top down versus bottom
* up yPos = placeableManager.getPHeight() - yPos;
*
* //subtract the height since points are bottom left and
* drawing starts from top left yPos -= height;
*
*
* g.setColor(Color.blue); g.drawRect(xPos, yPos,
* spriteRect.width, spriteRect.height); }
*/
}
}
}
public UDPPlaceable createUpdate() {
UDPPlaceable udpUpdate = new UDPPlaceable(id);
udpUpdate.isActive = isActive;
udpUpdate.isBuilding = isBuilding;
udpUpdate.buildingTime = buildingTime;
udpUpdate.totalBuildTime = totalBuildTime;
udpUpdate.isDirty = isDirty;
udpUpdate.isDestroying = isDestroying;
udpUpdate.totalHitPoints = totalHitPoints;
udpUpdate.hitPoints = hitPoints;
udpUpdate.destroyingTime = destroyingTime;
return udpUpdate;
}
public void processUpdate(UDPPlaceable udpUpdate) {
isActive = udpUpdate.isActive;
isBuilding = udpUpdate.isBuilding;
buildingTime = udpUpdate.buildingTime;
totalBuildTime = udpUpdate.totalBuildTime;
isDirty = udpUpdate.isDirty;
isDestroying = udpUpdate.isDestroying;
totalHitPoints = udpUpdate.totalHitPoints;
hitPoints = udpUpdate.hitPoints;
destroyingTime = udpUpdate.destroyingTime;
}
private void readObject(ObjectInputStream aInputStream) throws Exception {
aInputStream.defaultReadObject();
}
private void writeObject(ObjectOutputStream aOutputStream) throws Exception {
aOutputStream.defaultWriteObject();
}
}