package de.nameless.gameEngine.gameObjects;
import static de.nameless.gameEngine.util.Logger.debug;
import java.util.Vector;
import de.nameless.gameEngine.system.NEplayer;
import de.nameless.graphicEngine.NEabstractGraphicObject;
import de.nameless.graphicEngine.animation.lib.NETransparencLable;
import de.nameless.graphicEngine.animation.lib.NEVisibleLable;
import de.nameless.graphicEngine.lib.NEQuad;
import de.nameless.graphicEngine.model.NEMesh;
public abstract class NEUnit extends NEGameObject{
private static final long serialVersionUID = 1L;
public static final short NORTH = 3;
public static final short EAST = 2;
public static final short SOUTH = 1;
public static final short WEST = 0;
private static long UnitCounter = 0 ;
/**
* Eine eindeutiger identifier f�r diese einheit
*/
private long unitId = UnitCounter++;
/**
* Spieler dem diese Einheit geh�rt
*/
private int ownerID = 0;
/**
* Der antrib den die einheit nutzt.
*/
protected NEUnitDrive drive = new NEUnitDrive();
/**
* Hilfsvariable um die f�r die einheit erreichbaren felder zu beschreiben.
*/
private Vector<NEField> reachableFields = null;
/**
* Hilfsvariable um die f�r die einheit erreichbaren felder zu beschreiben.
*/
private Vector<NEUnit> attackableUnits = null;
/**
* fl�g, ob die einheit selektiert ist
*/
protected NEVisibleLable selected;
protected NEVisibleLable attLable;
/**
* die selection box der einheit
*/
protected NEQuad selectionBox;
protected NEQuad attackableBox;
/**
* Ein lable ob die einheit bewegt wurde.
*/
protected NETransparencLable moved;
/**
* Das haupt graphikobject der einheit.
*/
protected NEabstractGraphicObject main;
/**
* Das mesh welches die einheit repr�sentiert.
*/
protected NEMesh mesh;
/**
* Das Landschaftsfeld auf dem sich die einheid gerade bewegt.
*/
protected NEField square;
/**
* Gibt die maximalen Health Points der Einheit an.
*/
protected float maxHP;
/**
* .gibt die momentanen Health Points der einheit ein. HP repr�sentieren den Aktuellen Zustand der Einheit.
* Sinken sie auf 0 ist die Einheit vernichtet.
*/
protected float HP;
/**
* gibt die momentanen schield points an.
*/
protected float SP;
protected Vector<NEWeapon> weapons;
/**
* der Standartkonstruktor. Da jede einheit eine besutzer hat muss dessen id angegeben werden.
* @param ownerID
*/
public NEUnit(int ownerID) {
this.ownerID = ownerID;
reachableFields = new Vector<NEField>();
attackableUnits = new Vector<NEUnit>();
weapons = new Vector<NEWeapon>();
}
/**
* liefert das feld auf dem sich sie einheit befindent.
* <b> hier ist nicht zwingend auch deren Grafik</b>
* @return
*/
public NEField getSquare() {
return square;
}
@Override
public void putGfxPos() {
selectionBox.x = square.getGLX();
selectionBox.y = square.getGLY();
attackableBox.x = square.getGLX();
attackableBox.y = square.getGLY();
}
@Override
public float getGLX() {
return square.getGLX();
}
@Override
public float getGLY() {
return square.getGLY();
}
/**
* platziert die Einheit auf dem feld. Da ein einheit immer nur auf einem feld ein kann,
* wird sie vom aktuelle feld entfernt falls vorhanden. Die Grafik wird nicht angetastet.
* @param square
*/
public void placeUnitOnSquare(NEField square) {
this.square = square;
if(selectionBox!=null){
this.selectionBox.x = square.getGLX();
this.selectionBox.y = square.getGLY();
}
}
/**
* Liefert die ID der Einheit.
* @return
*/
public long getUnitId() {
return unitId;
}
@Override
protected Vector<NEabstractGraphicObject> getOwnGfx() {
Vector<NEabstractGraphicObject> result = new Vector<NEabstractGraphicObject>();
selectionBox = new NEQuad();
selectionBox.setTexture("Selection.tga");
selectionBox.layer = 1;
selectionBox.colored =true;
selectionBox.colorRed = 1;
selected = new NEVisibleLable(selectionBox);
result.add(selectionBox);
attackableBox = new NEQuad();
attackableBox.setTexture("Selection.tga");
attackableBox.layer = 2;
attackableBox.colored =true;
attackableBox.colorRed = 0.5f;
attLable = new NEVisibleLable(attackableBox);
result.add(attackableBox);
moved = new NETransparencLable(main,0.6f,1);
return result;
}
/**
* Setzt die einheit auf das Zeilquadrat und f�gt ein Animation hinzu.
* @param square
*/
public abstract void moveTo(NEField square);
/**
* Setzt die einheit auf das Zeilquadrat und f�gt ein Animation hinzu,
* die dem angegebenen weg folgt.
* @param way
*/
public abstract void followPath(Vector<NEField> way);
/**
* Selectiert die einheit, setzt die erreichbaren felder.
*/
public void select(){
selected.set();
markReachableFields();
markAttackableEnemys();
}
/**
* Deselektiert die Einheit und gibt die erreichbaren felder wider frei.
*/
public void deSelect(){
selected.release();
unMarkReachableFields();
unMarkReachableEnemys();
}
public abstract void jumpTo(NEField square);
public void endMovements(){
if(main!=null){
main.endAllAnimation();
}
}
/**
* liefert die ID der Besitzers.
* @return
*/
public int getOwnerID() {
return ownerID;
}
/**
* Setzt die BesitzerDI
* @param ownerID
*/
public void setOwnerID(int ownerID) {
this.ownerID = ownerID;
}
public Vector<NEWeapon>getWeapons(){
return weapons;
}
/**
* L�sst die Einheit den angegebenen schaden nehmen. Er wird um SP reduziert.
* Sinken die PH auf 0 so wird destroy aufgerufen.
* @param damage der schaden den die einheit nehmen soll.
* @return ist die einheit zerst�rt?
*/
public boolean takeDamage(float damage){
damage -= SP;
HP -= damage;
debug(this.toString() , true);
if(HP <= 0){
this.destroy();
return true;
} else {
return false;
}
}
/**
* F�llt die HP der einheit um den angegebenen Wert auf. maxHP kann nicht �berschritten werden.
* @param HP auf zu f�llender betrag.
*/
public void refillHP(float HP){
if((HP + this.HP) > this.maxHP){
this.HP = this.maxHP;
} else{
this.HP += HP;
}
}
public void destroy(){
debug("ich sterbe " + this.toString(), true);
}
/**
* Setzt entsprechend der Owner ID die Farbe der einheit.
*/
protected void setColor(){
if(main != null){
switch (this.ownerID){
case NEplayer.RED:
main.setColor(1f, 0.2f, 0.2f, 1);
break;
case NEplayer.YELLOW:
main.setColor(1f, 1f, 0.2f, 1);
break;
case NEplayer.BLUE:
main.setColor(0.2f, 0.2f, 1f, 1);
break;
case NEplayer.GREEN:
main.colored = true;
main.colorRed = 0.2f;
main.colorGreen = 1;
main.colorBlue = 0.2f;
break;
case NEplayer.PURPUL:
main.colored = true;
main.colorRed = 1;
main.colorGreen = 0.2f;
main.colorBlue = 1;
break;
case NEplayer.ORANGE:
main.colored = true;
main.colorRed = 1;
main.colorGreen = 0.6f;
main.colorBlue = 0;
break;
case NEplayer.BLACK:
main.colored = true;
main.colorRed = 0.3f;
main.colorGreen = 0.3f;
main.colorBlue = 0.3f;
break;
case NEplayer.WHITE:
main.colored = true;
main.colorRed = 1;
main.colorGreen = 1;
main.colorBlue = 1;
break;
}
}
}
/**
* Markiert all erreichbaren felder mit dem entsprachendem lable.
*/
public void markReachableFields(){
this.unMarkReachableFields();
recReachField(this.square, drive.getMoveDistance()+drive.costsOf(this.square.typ), new Vector<NEField>());
}
public void markAttackableEnemys(){
this.unMarkReachableEnemys();
//this.unMarkReachableFields();
this.recEnemyReach( this.square,
weapons.firstElement().getMaxRange(),
weapons.firstElement().getMinRange(),
new Vector<NEField>());
}
private void recEnemyReach(NEField f, float maxWay, float minWay, Vector<NEField> way){
if(maxWay >= 0){
way.add(f);
if(minWay<=0 && f.containsUnit() && f.containtLUnit.getOwnerID()!=ownerID){
f.containtLUnit.setAttackableLable();
this.attackableUnits.add(f.containtLUnit);
}
f.restWayAttack = maxWay;
f.BestWayAttack = new Vector<NEField>(way);
NEField i;
i = f.getNorth();
if(i != null ) recEnemyReach(i, maxWay-1,--minWay,new Vector<NEField>(way));
i = f.getEast();
if(i != null ) recEnemyReach(i, maxWay-1,--minWay,new Vector<NEField>(way));
i = f.getSouth();
if(i != null ) recEnemyReach(i, maxWay-1,--minWay,new Vector<NEField>(way));
i = f.getWest();
if(i != null ) recEnemyReach(i, maxWay-1,--minWay,new Vector<NEField>(way));
}
}
/**
* ein algorythmus der dei erreichbaren felder setzt
* @param f
* @param restWay
* @param way
*/
private void recReachField(NEField f, float restWay, Vector<NEField> way){
if(restWay-drive.costsOf(f.typ) >= 0){
way.add(f);
reachableFields.add(f);
f.reachable.set();
f.restWay = restWay;
f.BestWay = new Vector<NEField>(way);
NEField i;
i = f.getNorth();
if(i != null && betterWay(i,restWay) && !containsEnemy(i) ) recReachField(i, restWay-drive.costsOf(f.typ),new Vector<NEField>(way));
i = f.getEast();
if(i != null && betterWay(i,restWay) && !containsEnemy(i) ) recReachField(i, restWay-drive.costsOf(f.typ),new Vector<NEField>(way));
i = f.getSouth();
if(i != null && betterWay(i,restWay) && !containsEnemy(i) ) recReachField(i, restWay-drive.costsOf(f.typ),new Vector<NEField>(way));
i = f.getWest();
if(i != null && betterWay(i,restWay) && !containsEnemy(i) ) recReachField(i, restWay-drive.costsOf(f.typ),new Vector<NEField>(way));
}
}
private boolean betterWay(NEField f, float restWay){
if(!f.reachable.isSet()){
return true;
} else {
return f.restWay < restWay;
}
}
private boolean containsEnemy(NEField f){
return (!(f.containtLUnit == null) && f.containtLUnit.getOwnerID() != this.getOwnerID());
}
public void unMarkReachableFields(){
if(reachableFields != null){
for(NEField f : reachableFields){
f.reachable.release();
f.restWay = 0;
f.BestWay = new Vector<NEField>();
}
reachableFields.removeAllElements();
}
}
public void unMarkReachableEnemys(){
if(attackableUnits != null){
for(NEUnit u : attackableUnits){
u.releaseAttackableLable();
u.getSquare().restWay = 0;
u.getSquare().BestWay = new Vector<NEField>();
}
attackableUnits.removeAllElements();
}
//this.unMarkReachableFields();
}
public Vector<NEField> getReachableFields() {
return reachableFields;
}
public boolean reachable(NEField f){
return reachableFields.contains(f);
}
public boolean isSelectionLableSet() {
if(selected!=null){
return selected.isSet();
} else {
return false;
}
}
public void releaseSelectionLable() {
if(selected!=null){
selected.release();
}
}
public void setSelectionLable() {
if(selected != null){
selected.set();
}
}
public boolean isMovedLableSet() {
if(moved!=null){
return moved.isSet();
} else {
return false;
}
}
public void releaseMovedLable() {
if(moved!=null){
moved.release();
}
}
public void setMovedLable() {
if(moved!=null){
moved.set();
}
}
public boolean isAttackableLableSet() {
return attLable.isSet();
}
public void releaseAttackableLable() {
attLable.release();
}
public void setAttackableLable() {
attLable.set();
}
}