/*******************************************************************************
* Copyright 2015 Maximilian Stark | Dakror <mail@dakror.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package de.dakror.arise.game.building;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.sql.Connection;
import org.json.JSONException;
import org.json.JSONObject;
import de.dakror.arise.game.Game;
import de.dakror.arise.layer.CityHUDLayer;
import de.dakror.arise.net.User;
import de.dakror.arise.settings.Const;
import de.dakror.arise.settings.Resources;
import de.dakror.arise.settings.Resources.Resource;
import de.dakror.arise.ui.BuildButton;
import de.dakror.arise.util.Assistant;
import de.dakror.gamesetup.ui.ClickEvent;
import de.dakror.gamesetup.ui.ClickableComponent;
import de.dakror.gamesetup.ui.Container;
import de.dakror.gamesetup.util.Helper;
/**
* @author Dakror
*/
public abstract class Building extends ClickableComponent {
public static int GRID = 32;
protected int tx, ty, tw, th, id, typeId, level, maxLevel, levelFac, minCityLevel;
public int bx, by, bw, bh;
/**
* -1 = marked for deletion<br>
* 0 = construction<br>
* 1 = built<br>
* 2 = deconstruction<br>
* 3 = upgrading<br>
*/
protected int stage;
protected int stageChangeDuration;
protected int stageChangeSecondsLeft;
protected String name, desc;
protected String metadata;
protected Resources buildingCosts, products, scale;
protected Container guiContainer;
public Building(int x, int y, int width, int height, int level) {
super(x * GRID, y * GRID, width * GRID, height * GRID);
this.level = level;
buildingCosts = new Resources();
products = new Resources();
scale = new Resources();
bx = by = 0;
bw = width;
bh = height;
metadata = "";
guiContainer = new Container.DefaultContainer();
addClickEvent(new ClickEvent() {
@Override
public void trigger() {
CityHUDLayer.selectedBuilding = Building.this;
float duration = stageChangeDuration * Const.DECONSTRUCT_FACTOR / Game.world.getSpeed();
CityHUDLayer.upgrade.setUpgradeMode("Ausbau", "Die Stufe des Gebäudes wird erhöht. \nDauer: " + Assistant.formatSeconds((long) duration), getUpgradeCosts(), 0);
CityHUDLayer.upgrade.setProducts(products);
CityHUDLayer.upgrade.setScale(scale);
CityHUDLayer.upgrade.setLevel(Building.this.level);
CityHUDLayer.upgrade.setMaxLevel(maxLevel);
CityHUDLayer.deconstruct.setUpgradeMode("Abriss", "Das Gebäudes wird abgerissen. Es werden keine Resourcen zurückgegeben.", new Resources(), 0);
}
});
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void init() {
try {
if (Game.config.getJSONObject("buildings").has("" + typeId)) {
JSONObject o = Game.config.getJSONObject("buildings").getJSONObject(typeId + "");
buildingCosts = new Resources(o.getJSONObject("costs"));
products = new Resources(o.getJSONObject("products"));
scale = new Resources(o.getJSONObject("scale"));
stageChangeDuration = o.getInt("stage");
minCityLevel = o.has("mincitylevel") ? o.getInt("mincitylevel") : 0;
maxLevel = o.has("maxlevel") ? o.getInt("maxlevel") : Const.BUILDING_MAX_LEVEL;
levelFac = o.has("levelfac") ? o.getInt("levelfac") : Const.BUILDING_MAX_LEVEL;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void draw(Graphics2D g) {
if (Game.world == null) return;
if (state != 0 || (CityHUDLayer.selectedBuilding != null && CityHUDLayer.selectedBuilding.equals(this))) {
Color c = g.getColor();
g.setColor(Color.black);
g.drawRect(x + bx * GRID - 1, y + by * GRID - 1, bw * GRID + 2, bh * GRID + 2);
g.setColor(c);
}
if (stage > 0) drawStage1(g);
if (stageChangeSecondsLeft > 0) {
int tx = x + bx * GRID, ty = y + by * GRID, width = 128;
if (stage == 0) Assistant.drawBuildingStage(tx, ty, this, g);
Color c = g.getColor();
g.setColor(Color.white);
Helper.drawHorizontallyCenteredString(Assistant.formatSeconds(stageChangeSecondsLeft), tx + (bw * GRID - width) / 2, width, ty + (bh * GRID) / 2 + 6, g, 30);
g.setColor(c);
}
}
protected void drawStage1(Graphics2D g) {
Helper.setRenderingHints(g, false);
Helper.drawImage2(Game.getImage("world/structs.png"), x, y, width, height, tx * 32, ty * 32, tw * 32, th * 32, g);
Helper.setRenderingHints(g, true);
}
@Override
public void drawTooltip(int x, int y, Graphics2D g) {
if (Game.currentGame.getActiveLayer() instanceof CityHUDLayer) {
String string = getTooltipText();
int width = g.getFontMetrics(g.getFont().deriveFont(30f)).stringWidth(string) + 30;
int height = 64;
int x1 = x;
int y1 = y;
if (x1 + width > Game.getWidth()) x1 -= (x1 + width) - Game.getWidth();
if (y1 + height > Game.getHeight()) y1 -= (y1 + height) - Game.getHeight();
Helper.drawShadow(x1, y1, width, height, g);
Helper.drawString(string, x1 + 15, y1 + 40, g, 30);
}
}
@Override
public void update(int tick) {
if (stageChangeSecondsLeft > 0 && tick % Game.currentGame.getUPS() == 0) stageChangeSecondsLeft--;
}
public String getTooltipText() {
return "Lvl. " + (level + 1) + " " + name + (stage == 2 ? " (Abriss)" : (stage == 3 ? " (Ausbau)" : (stage == 0 ? " (Bau)" : "")));
}
public int getTypeId() {
return typeId;
}
public int getLevel() {
return level;
}
public int getStage() {
return stage;
}
public void setStage(int s) {
stage = s;
}
public int getStageChangeSeconds() {
return stageChangeDuration;
}
public long getStageChangeSecondsLeft() {
return stageChangeSecondsLeft;
}
/**
* @param s - time in seconds
*/
public void setStageChangeSecondsLeft(int s) {
stageChangeSecondsLeft = s;
}
protected float getStageChangeDuration() {
return Math.round(stageChangeDuration * (stage == 0 ? 1f : Const.DECONSTRUCT_FACTOR) / Game.world.getSpeed());
}
public String getName() {
return name;
}
public String getDescription() {
return desc;
}
public String getData() {
return typeId + ":" + level + ":" + ((x - 96) / GRID) + ":" + ((y - 96) / GRID) + ":" + stage + ":" + stageChangeSecondsLeft + (metadata.length() > 0 ? ":" + metadata : "");
}
public Resources getBuildingCosts() {
return buildingCosts;
}
public Resources getUpgradeCosts() {
Resources res = new Resources();
res.add(buildingCosts);
for (Resource r : res.getFilled())
res.set(r, (int) Math.round((Const.BUILDING_MAX_LEVEL / (float) levelFac) * res.get(r) * Math.pow(Const.UPGRADE_FACTOR, level + 1)));
return res;
}
public Resources getProducts() {
return products;
}
public int getMinCityLevel() {
return minCityLevel;
}
public Resources getScalingProducts() {
Resources p = new Resources();
p.add(products);
if (level > 0) p.add(Resources.mul(scale, level));
return p;
}
public Resources getScale() {
return scale;
}
public Container getGuiContainer() {
return guiContainer;
}
public int getMaxLevel() {
return maxLevel;
}
public void setMetadata(String s) {
if (s == null) s = "";
metadata = s;
}
protected void addGuiButton(int x, int y, Image icon, String tooltip, String desc, Resources buildingCosts, int minCityLevel, ClickEvent action) {
BuildButton b = new BuildButton(x * 56 + Game.getWidth() - 270, y * 56 + Game.getHeight() - 170, 32, 32, icon);
b.addClickEvent(action);
b.mode1 = true;
b.setUpgradeMode(tooltip, desc, buildingCosts, minCityLevel);
guiContainer.components.add(b);
}
protected void addGuiButton(int x, int y, Point icon, String tooltip, String desc, Resources buildingCosts, int minCityLevel, ClickEvent action) {
addGuiButton(x, y, Game.getImage("system/icons.png").getSubimage(icon.x * 24, icon.y * 24, 24, 24), tooltip, desc, buildingCosts, minCityLevel, action);
}
/** Server-side only */
public void onSpecificChange(int cityId, User owner, Connection connection) {}
@Override
public boolean contains(int x, int y) {
return new Rectangle(this.x + bx * GRID, this.y + by * GRID, bw * GRID, bh * GRID).contains(x, y);
}
public void setLevel(int newLevel) {
level = newLevel;
}
public void updateGuiButtons() {}
public static Building getBuildingByTypeId(int x, int y, int level, int typeId) {
switch (typeId) {
case 1:
return new Center(x, y, level);
case 2:
return new Lumberjack(x, y, level);
case 3:
return new Mine(x, y, level);
case 4:
return new Quarry(x, y, level);
case 5:
return new Barracks(x, y, level);
case 6:
return new Barn(x, y, level);
default:
return null;
}
}
}