package vooga.rts.gamedesign.state;
import vooga.rts.util.DelayedTask;
/**
* This class represents the state of the entity in the game. For example, this
* class will keep track of whether or not a unit can attack or can currently
* move.
*
* @author Ryan Fishel
* @author Kevin Oh
* @author Francesco Agosti
* @author Wenshun Liu
*
*/
public class EntityState {
private AttackingState myAttackingState;
private OccupyState myOccupyState;
private ProducingState myProducingState;
private MovementState myMovementState;
private DetectableState myDetectableState;
private UnitState myUnitState;
private double myAttackingCooldown;
private DelayedTask myAttackingDelay;
private static final double DEFAULT_ATTACKING_INTERVAL = .25;
/**
* Creates a new state for the entity with that is set to not attacking, not
* occupying, not producing, and stationary. The interval for attacking
* after moving is also set to the default attacking interval
*/
public EntityState () {
myAttackingState = AttackingState.NOT_ATTACKING;
myOccupyState = OccupyState.NOT_OCCUPYING;
myProducingState = ProducingState.NOT_PRODUCING;
myMovementState = MovementState.STATIONARY;
myDetectableState = DetectableState.DETECTABLE;
myAttackingCooldown = DEFAULT_ATTACKING_INTERVAL;
myUnitState = UnitState.NO_STATE;
}
/**
* Returns the attacking state of the game entity.
*
* @return the attacking state of the entity
*/
public AttackingState getAttackingState () {
return myAttackingState;
}
/**
* This method is used to set the attacking state (either attacking or not
* attacking) for the game entity.
*
* @param attackingState
* is the attacking state that the game entity will be set to
*
*/
public void setAttackingState (AttackingState attackingState) {
myAttackingState = attackingState;
}
/**
* This method is used to set the occupying state (either occupying or not
* occupying) for the game entity.
*
* @param occupyState
* is the occupying state that the game entity will be set to
*/
public void setOccupyState (OccupyState occupyState) {
myOccupyState = occupyState;
}
public OccupyState getOccupyState () {
return myOccupyState;
}
/**
* This method is used to set the producing state (either producing or not
* producing) for the game entity.
*
* @param producingState
* is the producing state that the game entity will be set to
*/
public void setProducingState (ProducingState producingState) {
myProducingState = producingState;
}
/**
* This method is used to set the movement state (either moving or
* stationary) for the game entity.
*
* @param movementState
* is the movement state that the game entity will be set to
*/
public void setMovementState (MovementState movementState) {
myMovementState = movementState;
}
/**
* This method returns the movement state (either moving or stationary) of
* the game entity.
*
* @return the movement state of the game entity
*/
public MovementState getMovementState () {
return myMovementState;
}
/**
* returns the unit's state.
*
* @return the state of the unit
*/
public UnitState getUnitState () {
return myUnitState;
}
/**
* Sets the state of the unit.
*
* @param unitState
* is the state of the unit
*/
public void setUnitState (UnitState unitState) {
myUnitState = unitState;
}
/**
* Returns whether or not a unit is in occupy mode.
*
* @return true if a unit is set to occupy (a friendly building was
* clicked on) and false if it cannot occupy
*/
public boolean canUnitOccupy () {
return myUnitState == UnitState.OCCUPY;
}
/**
* Returns whether the entity is currently in the move state.
*
* @return true if the unit can move and false if the unit is stationary
*/
public boolean canMove () {
return myMovementState == MovementState.MOVING;
}
/**
* Returns whether or not the entity can be selected.
*
* @return true if the entity can be selected and false if it can not be
* selected
*/
public boolean canSelect () {
return myOccupyState == OccupyState.NOT_OCCUPYING;
}
/**
* Sets the state of an entity to producing. When an entity produces, it
* does not move attack, move, or occupy.
*/
public void produce () {
myProducingState = ProducingState.PRODUCING;
myMovementState = MovementState.STATIONARY;
myAttackingState = AttackingState.NOT_ATTACKING;
myOccupyState = OccupyState.NOT_OCCUPYING;
myUnitState = UnitState.PRODUCE;
}
/**
* Returns whether or not an entity can produce other entities
*
* @return true if the entity can produce other entities and false if it
* cannot produce other entities
*/
public boolean canProduce () {
return myProducingState == ProducingState.PRODUCING
&& myUnitState == UnitState.PRODUCE;
}
/**
* Returns whether the entity can attack. In order to attack, the entity
* must be in the attacking state.
*
* @return true if the entity can attack (in the attacking state and false
* if the entity cannot attack
*/
public boolean canAttack () {
return myAttackingState == AttackingState.ATTACKING;
}
/**
* Checks to see whether an entity has an attacking state other than not
* attacking.
*
* @return true if the entity state is either attacking or waiting and false
* if the entity is not attacking
*/
public boolean isAttacking () {
return myAttackingState != AttackingState.NOT_ATTACKING;
}
/**
* Checks to see if an entity has been set to be in attack mode.
*
* @return true if the unit state of the entity is set to attack and false
* if the unit state of the entity is set to anything else
*/
public boolean inAttackMode () {
return myUnitState == UnitState.ATTACK;
}
/**
* Stops the movement of the entity. This means that the entity's movement
* state is set to stationary.
*/
public void stop () {
myMovementState = MovementState.STATIONARY;
}
/**
* Holds the entity. This means that the entity is set to not attack and not
* move (it is set to stationary).
*/
public void hold () {
myAttackingState = AttackingState.NOT_ATTACKING;
myMovementState = MovementState.STATIONARY;
}
/**
* This method sets the entity to the attacking state.
*/
public void attack () {
myAttackingState = AttackingState.WAITING;
// myUnitState = UnitState.ATTACK;
myAttackingDelay = new DelayedTask(myAttackingCooldown, new Runnable() {
@Override
public void run () {
myAttackingState = AttackingState.ATTACKING;
}
});
}
/**
* This method is used to update the cooldown of the attacking delayed task.
* This delayed task is used to make the entity delay attacking after moving
* so that the entity does not look "buggy" as it moves and shoots. If the
* entity is moving, its cooldown is reset to the max cooldown. If the
* entity is not moving the cooldown gets decremented.
*/
public void update (double elapsedTime) {
if (myAttackingDelay != null) {
if (myMovementState == MovementState.MOVING) {
myAttackingDelay.cancel();
myAttackingState = AttackingState.NOT_ATTACKING;
}
else {
// System.out.println("Not Moving!");
myAttackingDelay.update(elapsedTime);
}
}
}
}