/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package transientlibs.maps.units;
import transientlibs.maps.tiles.Tile;
import transientlibs.maps.utils.pathfinding.PathFinder;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import java.util.ArrayList;
import transientlibs.slick2d.util.Log;
import transientlibs.bindedobjects.core.datasets.Action;
import transientlibs.bindedobjects.gamecontent.Creatures;
import transientlibs.maps.entities.DestroyableObject;
import transientlibs.maps.entities.MapObject;
import transientlibs.objects.creatures.items.Equipment;
import transientlibs.objects.misc.GenericTask;
import transientlibs.objects.creatures.items.Inventory;
import transientlibs.objects.creatures.items.Item;
import transientlibs.objects.creatures.ai.AbstractAIBrain;
import transientlibs.objects.cards.Deck;
import transientlibs.processors.misc.Detonator;
import transientlibs.preui.gdx.game.TransientInput;
import transientlibs.maps.implementation.TilelessMap;
import transientlibs.maps.utils.fov.FOVBoard;
import transientlibs.objects.primitives.Coords;
import transientlibs.objects.primitives.Int;
import transientlibs.objects.general.ModeSelector;
import transientlibs.objects.general.Node;
import transientlibs.objects.primitives.SmallPoints;
import transientlibs.preui.objects.gui.interfaces.IAnimation;
/**
*
* @author kibertoad
*/
public class Unit extends DestroyableObject implements GenericUnit {
public static Unit currentUnit;
public static Unit lastUnit;
public GenericTask assignedTask = null;
public IAnimation actionAnimation = null;
public IAnimation movingAnimation;
public Int verticalVelocity = new Int(0); //how many "go up steps" has the unit got left
public Int verticalDelta = new Int(-13); //how will velocity change on next iteration
public PathFinder pathfinder;
public Action currentAction = null;
public AbstractAIBrain AIBrain = null;
public Creatures creature;
public Unit target = null;
public ModeSelector modeSelector;
public Inventory inventory = new Inventory();
public Equipment equipment = new Equipment();
public Node actionTarget;
public int stepCount = 0;
public int direction = 6; // can be -1 if not moved
public int lastDirection = 6; //positioning
public Int maxActionPoints = new Int(0);
public Int actionPoints = new Int(0);
public Coords targettedCoords = new Coords();
public Coords aimedCoords = new Coords();
public Int sightRange = new Int(-1);
public boolean canSeePlayer = false;
public Deck deck = null;
private Vector2 movementVector = new Vector2();
public FOVBoard fov = null;
@Override
public void setDeck(Deck deck) {
this.deck = deck;
}
@Override
public Coords getAimedCoords() {
return aimedCoords;
}
@Override
public void setAimedCoords(Coords aimedCoords) {
this.aimedCoords = aimedCoords;
}
public Body body;
@Override
public Body getBody() {
return body;
}
@Override
public void setBody(Body body) {
this.body = body;
}
@Override
public void syncCoordsFromBody() {
mapCoords.x = body.getPosition().x * Detonator.BOX2D_TO_WORLD;
mapCoords.y = body.getPosition().y * Detonator.BOX2D_TO_WORLD;
}
public void syncCoordsToBody() {
//body.getPosition().x = mapCoords.x * Detonator.WORLD_TO_BOX2D * Terrain.tileWidth;
//body.getPosition().y = mapCoords.y * Detonator.WORLD_TO_BOX2D * Terrain.tileHeight;
}
public void adjustVector(int direction, float delta) {
if (direction == 7) {
movementVector.x = -delta;
movementVector.y = -delta;
}
if (direction == 8) {
movementVector.x = 0;
movementVector.y = -delta;
}
if (direction == 9) {
movementVector.x = delta;
movementVector.y = -delta;
}
if (direction == 4) {
movementVector.x = -delta;
movementVector.y = 0;
}
if (direction == 6) {
movementVector.x = delta;
movementVector.y = 0;
}
if (direction == 1) {
movementVector.x = -delta;
movementVector.y = delta;
}
if (direction == 2) {
movementVector.x = 0;
movementVector.y = delta;
}
if (direction == 3) {
movementVector.y = delta;
movementVector.x = delta;
}
if (direction == 5) {
movementVector.x = 0;
movementVector.y = 0;
}
}
public void floatBody(int direction, float delta) {
//Log.info("FLOAT");
adjustVector(direction, delta);
body.applyForceToCenter(movementVector, true);
//true - wake up the body
}
//public TransientImages transientImages = null;
public boolean movedThisTurn = false;
public static float step = 1f;
@Override
public void bindValues(String prefix) {
Detonator.INSTANCE.setBindedValue("actionpoints", actionPoints);
Detonator.INSTANCE.setBindedValue("hp", this.HP.now);
Detonator.INSTANCE.setBindedValue("maxhp", this.HP.max);
}
public Coords setVectorByDirection(float multiplier) {
Coords resultCoords = setVectorByDirection();
resultCoords.x = resultCoords.x * multiplier;
resultCoords.y = resultCoords.y * multiplier;
return resultCoords;
}
@Override
public Creatures getCreatures() {
return creature;
}
public void resetTarget() {
resetTargettedCoords();
target = null;
}
public void resetTargettedCoords() {
targettedCoords.x = mapCoords.x;
targettedCoords.y = mapCoords.y;
pathfinder.path = null;
}
public Coords setVectorByDirection() {
Coords resultCoords = new Coords();
if (direction == 7) {
resultCoords.x = -1;
resultCoords.y = -1;
}
if (direction == 8) {
resultCoords.x = 0;
resultCoords.y = -1;
}
if (direction == 9) {
resultCoords.x = 1;
resultCoords.y = -1;
}
if (direction == 4) {
resultCoords.x = -1;
resultCoords.y = 0;
}
if (direction == 6) {
resultCoords.x = 1;
resultCoords.y = 0;
}
if (direction == 1) {
resultCoords.x = -1;
resultCoords.y = 1;
}
if (direction == 2) {
resultCoords.x = 0;
resultCoords.y = 1;
}
if (direction == 3) {
resultCoords.y = 1;
resultCoords.x = 1;
}
if (direction == 5) {
resultCoords.x = 0;
resultCoords.y = 0;
}
return resultCoords;
}
public Coords setVectorByDirectionDefault() {
//Log.info("Direction: "+direction);
Coords resultCoords = new Coords();
if (direction == 7) {
resultCoords.x = -0.02f;
resultCoords.y = -0.02f;
}
if (direction == 8) {
resultCoords.x = 0;
resultCoords.y = -0.02f;
}
if (direction == 9) {
resultCoords.x = 0.02f;
resultCoords.y = -0.02f;
}
if (direction == 4) {
resultCoords.x = -0.02f;
resultCoords.y = 0;
}
if (direction == 6) {
resultCoords.x = 0.02f;
resultCoords.y = 0;
}
if (direction == 1) {
resultCoords.x = -0.02f;
resultCoords.y = 0.02f;
}
if (direction == 2) {
resultCoords.x = 0;
resultCoords.y = 0.02f;
}
if (direction == 3) {
resultCoords.y = 0.02f;
resultCoords.x = 0.02f;
}
if (direction == 5) {
resultCoords.x = 0;
resultCoords.y = 0;
}
return resultCoords;
}
@Override
public Coords multiplyVectorByDirection(float vector) {
Coords resultCoords = new Coords(vector, vector);
if (direction == 7) {
resultCoords.x = resultCoords.x * -1;
resultCoords.y = resultCoords.y * -1;
}
if (direction == 8) {
resultCoords.x = 0;
resultCoords.y = resultCoords.y * -1;
}
if (direction == 9) {
resultCoords.y = resultCoords.y * -1;
}
if (direction == 4) {
resultCoords.x = resultCoords.x * -1;
resultCoords.y = 0;
}
if (direction == 6) {
resultCoords.y = 0;
}
if (direction == 1) {
resultCoords.x = resultCoords.x * -1;
}
if (direction == 2) {
resultCoords.x = 0;
}
if (direction == 3) {
}
if (direction == 5) {
resultCoords.x = 0;
resultCoords.y = 0;
}
return resultCoords;
}
public void resetPath() {
pathfinder.goalX = mapCoords.getIntX();
pathfinder.goalY = mapCoords.getIntY();
}
public Unit(int onX, int onY, int setType, TilelessMap setMap) {
super(setMap, Creatures.creatures.get(setType).masterImage);
//if (Detonator.INSTANCE.useGDXImages == false) {
// originalImage = Images.getImagesByID(setType);
//}
originalImage = Detonator.INSTANCE.imageProvider.getImage(setType);
//Log.info("super finished");
creature = Creatures.creatures.get(setType);
for (Int i : creature.equippedItems) {
equipment.equipItem(new Item(i.value));
}
ofType = setType;
mapCoords.x = onX;
mapCoords.y = onY;
isDrawn = true;
HP.setup(creature.maxHP, creature.maxHP);
HP.min = -10000;
Log.info("now hp: " + HP.now.value);
pathfinder = new PathFinder(mapCoords, setMap);
maxActionPoints.value = creature.movementSpeed;
actionPoints.value = maxActionPoints.value;
pathfinder.currentMovementReach = actionPoints;
pathfinder.globalMovementReach.value = actionPoints.value;
movingAnimation = creature.walkAnimation;
noHoverOnTransparent = false;
}
public void targetUnit(Unit theUnit) {
target = theUnit;
}
public void targetTile(Coords toCoords) {
targetTile(toCoords.getIntX(), toCoords.getIntY());
}
public void targetTile(int setX, int setY) {
onMap.pathfindingGoalX = setX;
onMap.pathfindingGoalY = setY;
pathfinder.goalX = setX;
pathfinder.goalY = setY;
targettedCoords.x = setX;
targettedCoords.y = setY;
resetSteps();
pathfinder.updatePath();
}
@Override
public void becomeDestroyed() {
super.becomeDestroyed();
Log.info("destroy unit");
onMap.units.remove(this);
if (currentTile() != null) {
currentTile().units.remove(this);
}
}
@Override
public void getDamage(int damageAmount) {
super.getDamage(damageAmount);
if (HP.now.value <= 0) {
MapObject.killList.add(this);
}
//becomeDestroyed();
}
public void addToKillList() {
MapObject.killList.add(this);
isDead = true;
}
@Override
public void getDamage(int damageType, int damageAmount) {
super.getDamage(damageAmount);
if (HP.now.value <= 0) {
addToKillList();
}
//becomeDestroyed();
}
public void assignAction(String setAction) {
assignAction(Action.getActionByCode(setAction));
}
public void performAction(String setAction) {
assignAction(Action.getActionByCode(setAction));
processAction();
currentAction = null;
}
public void assignAction(Action setAction) {
//Log.info("assign action!");
currentAction = setAction;
if (setAction != null) {
if (setAction.unitAnimation != null) {
setAnimation(setAction.unitAnimation);
//Log.info("with animation");
if (currentAnimation == null) {
//Log.info("null animation!");
}
} else {
//Log.info("no animation set");
currentAnimation = null;
}
}
if (currentAnimation == null) {
//Log.info("null animation!");
}
}
public void processAction() {
if (currentAction != null) {
Detonator.INSTANCE.activeUnit = this;
if (currentAction.reqs.isFulfilled()) {
if (currentAction.eval != null) {
currentAction.eval.processSilently();
}
currentAction.acts.process();
}
}
if (currentAction != null) {
if ((currentAction.reqs != null)
&& (!currentAction.reqs.isFulfilled())) {
if (currentAction.stopAutomatically) {
//Log.info("STOPPED");
currentAction = null;
currentAnimation = null;
}
}
}
}
@Override
public void processTurn() {
resetSteps();
actionPoints.value = maxActionPoints.value;
}
@Override
public boolean isClickable() {
return true;
}
public void bindToMap() {
onMap.units.add(this);
}
public void bindToTile() {
//Log.info("Crd: "+mapCoords.getIntX()+"/"+mapCoords.getIntY());
//if (onMap == null) {Log.info("null map");}
//Log.info("terr: "+Maps.currentMap.tile[2][2].terrain.ID);
onMap.getTile(mapCoords.getIntX(), mapCoords.getIntY()).units.add(this);
calcImagePosition();
}
@Override
public MarkerType markerID() {
return MarkerType.UnitMarker;
}
@Override
public void processUnitCollision() {
collidedUnit.setIsDestroyed(true);
collidedUnit.setIsDrawn(false);
collidedUnit.setIsOnScreen(false);
}
@Override
public void performMove(int xDelta, int yDelta) {
performTeleport(mapCoords.getIntX() + xDelta, mapCoords.getIntY() + yDelta);
}
@Override
public void performMove(float xDelta, float yDelta) {
//Log.info("Delta: "+xDelta+"/"+yDelta);
if (!terrainCollision(xDelta, yDelta)) {
//Log.info("Didn't collide");
performTeleport(mapCoords.x + xDelta, mapCoords.y + yDelta);
}
}
@Override
public void performTeleport(int toX, int toY) {
//Log.info("Pre-move coords are: "+mapCoords.toString());
//onMap.getTile(mapCoords.getIntX(), mapCoords.getIntY()).units.remove(this);
onMap.removeUnitFromTile(mapCoords.getIntX(), mapCoords.getIntY(), this);
mapCoords.x = toX;
mapCoords.y = toY;
//onMap.getTile(mapCoords.getIntX(), mapCoords.getIntY()).units.add(this);
onMap.addUnitToTile(mapCoords.getIntX(), mapCoords.getIntY(), this);
calcImagePosition();
processEncounteredLandmarks();
//Log.info("after move coords are: "+mapCoords.toString());
}
@Override
public boolean move(int inDirection) {
if (inDirection != 5) {
currentTile().units.remove(this);
boolean result = super.move(inDirection);
currentTile().units.add(this);
return result;
} else {
return false;
}
}
@Override
public void performTeleport(float toX, float toY) {
//Log.info("Pre-move coords are: "+mapCoords.toString());
Tile oldTile = onMap.getTile(mapCoords.getIntX(), mapCoords.getIntY());
mapCoords.x = toX;
mapCoords.y = toY;
//Log.info("Now on "+mapCoords.getIntX()+"/"+mapCoords.getIntY());
Tile newTile = onMap.getTile(mapCoords.getIntX(), mapCoords.getIntY());
if (oldTile != newTile) {
oldTile.units.remove(this);
newTile.units.add(this);
processEncounteredLandmarks();
}
calcImagePosition();
//Log.info("after move coords are: "+mapCoords.toString());
}
public void processEncounteredLandmarks() {
/*
for (Landmark l : onMap.getTile(mapCoords.getIntX(), mapCoords.getIntY()).landmarks) {
if (l.landmark.onVisitTex != null) {
l.landmark.onVisitTex.processSilently(Detonator.INSTANCE.currentGame.getGenericTiledMapState().getMessageLog());
}
}*/
onMap.processUnitEncounterWithLandmark(this);
}
//used for setting up
public void setupNew(int onSide, int ofID, int setX, int setY, TilelessMap setMap) {
lastUnit = this;
lastUnit.side.value = onSide;
lastUnit.ID = ofID;
lastUnit.bindToMap();
lastUnit.bindToTile();
}
public void resetSteps() {
stepCount = 1;
}
public void takeAllSteps() {
if (pathfinder.path != null) {
while ((stepCount < pathfinder.path.getLength())
&& (actionPoints.value > 0)) {
Log.info("Take one step: " + stepCount);
takeOneStep();
}
} else {
Log.info("I'm already there.");
}
}
public void roundCoords() {
mapCoords.x = (float) Math.round(mapCoords.x * 100000) / 100000;
mapCoords.y = (float) Math.round(mapCoords.y * 100000) / 100000;
}
public void takeOneFractionalStep(float stepSize) {
Coords delta = setVectorByDirection(stepSize);
performMove(delta.x, delta.y);
}
public void takeOneFractionalStep() {
//Coords delta = setVectorByDirectionDefault();
//Coords delta = setVectorByDirection(0.015625f);
Coords delta = setVectorByDirection(0.03125f);
//Coords delta = setVectorByDirection(0.0625f);
//Log.info("D+ " + Terrain.tileStepVectorSize);
//Coords delta = setVectorByDirection(Terrain.tileStepVectorSize);
//Log.info(mapCoords.toString());
//Log.info("Delta+ " + delta.x + "/" + delta.y);
performMove(delta.x, delta.y);
//roundCoords();
//Log.info(mapCoords.toString());
//Log.info("X: "+mapCoords.getIntX()+" Y: "+ mapCoords.getIntY());
//Log.info("Coords after move: "+mapCoords.toString());
}
public void takeOneStep() {
if (pathfinder.path != null) {
//i (x < pathfinder.path.getLength()); x++) {
performTeleport(pathfinder.path.getX(stepCount), pathfinder.path.getY(stepCount));
stepCount++;
if (maxActionPoints.value > 0) {
//actionPoints.value = actionPoints.value - (currentTile().terrain.moveCost);
actionPoints.value = actionPoints.value - getCurrentTileMovementCost();
}
//}
}
}
@Override
public void draw(int onX, int onY) {
//Log.info("draw unit");
if (currentAnimation != null) {
//Log.info("draw animation");
currentAnimation.draw(onX, onY);
} else {
super.draw(onX, onY);
}
}
@Override
public void draw() {
//Log.info("unit draw");
if (currentAnimation != null) {
//Log.info("draw animation");
currentAnimation.draw(screenCoords.getIntX(), screenCoords.getIntY());
} else {
super.draw();
}
}
@Override
public void processTex(ArrayList<String> tokens) {
}
public boolean facesRight() {
return ((direction == 9) || (direction == 6) || (direction == 3));
}
public boolean facesLeft() {
return ((direction == 7) || (direction == 4) || (direction == 1));
}
public void targetUnitTile() {
targetTile(target.mapCoords);
}
@Override
public Coords getScreenCoords() {
return screenCoords;
}
public void processMovementInput(TransientInput input) {
movedThisTurn = false;
if (input.buttons[TransientInput.UP]) {
//if (input.isPressed(TransientInput.UP)) {
// mapCoords.y -= (step * delta);
direction = 8;
movedThisTurn = true;
//Log.info("UP");
}
if (input.buttons[TransientInput.DOWN]) {
//if (input.isPressed(TransientInput.DOWN)) {
//mapCoords.y += (step * delta);
direction = 2;
movedThisTurn = true;
//Log.info("DOWN");
}
if (input.buttons[TransientInput.LEFT]) {
//if (input.isPressed(TransientInput.LEFT)) {
//mapCoords.x -= (step * delta);
direction = 4;
movedThisTurn = true;
//Log.info("LEFT");
}
if (input.buttons[TransientInput.RIGHT]) {
//if (input.isPressed(TransientInput.RIGHT)) {
//mapCoords.x += (step * delta);
direction = 6;
movedThisTurn = true;
//Log.info("RIGHT");
}
}
public void moveUnit(TransientInput input, float delta) {
/*
if (input.buttons[TransientInput.UP]) {
this.mapCoords.y -= (1 * delta);
} else if (input.buttons[TransientInput.DOWN]) {
this.mapCoords.y += (1 * delta);
}
if (input.buttons[TransientInput.LEFT]) {
this.mapCoords.x -= (1 * delta);
} else if (input.buttons[TransientInput.RIGHT]) {
this.mapCoords.x += (1 * delta);
}
*/
processMovementInput(input);
if (movedThisTurn) {
this.floatBody(direction, step * delta);
//this.syncCoordsFromBody();
//this.calcImagePosition();
if ((direction == 4) || (direction == 6)
|| (direction == 8) || (direction == 2)) {
if ((getImage() != creature.visualInformation.getDirectionImages(direction))) {
if (getImage() != null) {
setImage(creature.visualInformation.getDirectionImages(direction));
}
}
}
}
// make sure the ship is inside the stage
//if( x < 0 ) x = 0;
//else if( x > stage.width() - width ) x = stage.width() - width;
//if( y < 0 ) y = 0;
//else if( y > stage.height() - height ) y = stage.height() - height;
}
@Override
public void processPhysicsMovement(TransientInput input, float delta) {
moveUnit(input, delta);
}
public void tick(TransientInput input) {
movedThisTurn = false;
//float delta = Gdx.graphics.getDeltaTime();
//float step = 50f * delta;
if (input.buttons[TransientInput.UP]) {
//mapCoords.y -= step;
direction = 8;
movedThisTurn = true;
}
if (input.buttons[TransientInput.DOWN]) {
//mapCoords.y += step;
direction = 2;
movedThisTurn = true;
}
if (input.buttons[TransientInput.LEFT]) {
//mapCoords.x -= step;
direction = 4;
movedThisTurn = true;
}
if (input.buttons[TransientInput.RIGHT]) {
// mapCoords.x += step;
direction = 6;
movedThisTurn = true;
}
if (movedThisTurn) {
this.floatBody(direction, step);
this.syncCoordsFromBody();
this.calcImagePosition();
if ((direction == 4) || (direction == 6)
|| (direction == 8) || (direction == 2)) {
if ((getImage() != creature.visualInformation.getDirectionImages(direction))) {
if (getImage() != null) {
setImage(creature.visualInformation.getDirectionImages(direction));
}
}
}
}
}
@Override
public Coords getMapCoords() {
return mapCoords;
}
@Override
public Int getSightRange() {
return sightRange;
}
@Override
public void processBrain() {
if (AIBrain != null) {
AIBrain.process();
}
}
@Override
public Int getSide() {
return side;
}
@Override
public Deck getDeck() {
return deck;
}
@Override
public AbstractAIBrain getBrain() {
return AIBrain;
}
@Override
public SmallPoints getHP() {
return HP;
}
@Override
public boolean isOnScreen() {
return onScreen;
}
@Override
public boolean isDrawn() {
return isDrawn;
}
@Override
public Inventory getInventory() {
return inventory;
}
@Override
public int getDirection() {
return direction;
}
@Override
public void setDirection(int toDirection) {
direction = toDirection;
}
@Override
public void getHealing(int ofType, int ofAmount) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Node getActionTarget() {
return actionTarget;
}
@Override
public Int getVerticalVelocity() {
return verticalVelocity;
}
@Override
public void processGenericMovement(TransientInput onInput) {
processMovementInput(onInput);
if (movedThisTurn) {
onInput.processedKeypress = true;
this.move(direction);
if ((direction == 4) || (direction == 6)
|| (direction == 8) || (direction == 2)) {
if ((getImage() != creature.visualInformation.getDirectionImages(direction))) {
if (creature.visualInformation.getDirectionImages(direction) != null) {
setImage(creature.visualInformation.getDirectionImages(direction));
}
}
}
}
}
@Override
public String getName (){
return this.creature.getName();
}
@Override
public Int getMaxActionPoints() {
return maxActionPoints;
}
public void setMaxActionPoints(Int maxActionPoints) {
this.maxActionPoints = maxActionPoints;
}
@Override
public Int getActionPoints() {
return actionPoints;
}
public void setActionPoints(Int actionPoints) {
this.actionPoints = actionPoints;
}
@Override
public PathFinder getPathfinder() {
return pathfinder;
}
public FOVBoard getFOV (){
return fov;
}
public void setFOV (FOVBoard setBoard){
fov = setBoard;
}
}