/*
Copyright 2013-2015 Rohit Nirmal
This file is part of Clonepoint.
Clonepoint is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clonepoint is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clonepoint. If not, see .
*/
#ifndef ENTITY_H
#define ENTITY_H
#include //for AudioManager::playSound
#include "vec.h"
#include "global.h"
#include "sprite.h"
#include "locator.h"
#define ENEMY_FOV_RADIUS_SNIPER 1024
#define ENEMY_FOV_RADIUS_LIT 512
#define ENEMY_FOV_RADIUS_DARK 64
#define ENEMY_FOV_HALFANGLE 45
#define ENEMY_FOV_HALFANGLE_SEEN 80
#define GRAVITY 0.025
enum StairTraversal
{
NotMoving = 0,
MovingUp,
MovingDown
};
enum GuardState
{
IDLE = 0,
IDLE_CAUTION, //just ended investigation - wait a few seconds to switch to patrolling.
PATROLLING, //normal speed.
INVESTIGATING, //running toward point of interest - either noise or player's last position
AIMING,
USING_SWITCH,
PINNED,
FALLING,
KNOCKED_OUT
};
enum AttachType
{
NotAttached = 0,
LeftSide,
RightSide,
Ceiling
};
enum AlertType
{
ALERT_NONE = 0,
ALERT_LOOK,
ALERT_WALK,
ALERT_RUN
};
enum TargetType
{
TARGET_NONE = 0,
TARGET_NOISE,
TARGET_PLAYER,
TARGET_LIGHTSWITCH,
TARGET_ALARM
};
enum FOVType
{
FOV_LIGHT = 0,
FOV_CAMERA
};
enum DoorType
{
Door_Normal = 0,
Door_Trap,
Door_Vault
};
enum EnemyType
{
Enemy_Guard = 0,
Enemy_Enforcer,
Enemy_Professional,
Enemy_Sniper
};
struct Acceleration
{
bool accelerating;
float target;
float accel;
};
enum GunShotTraceType
{
Shot_None = 0, //used only for EnemyShotResolve.
Shot_FromPlayer,
Shot_FromEnemyVoluntary,
Shot_FromEnemyInvoluntary
};
struct EnemyShotResolve
{
int timeSinceShot;
GunShotTraceType shotType;
};
void setAccel(Acceleration* accel, bool accelerating, float start, float target);
class LightFixture;
class FieldOfView
{
public:
FieldOfView(float x, float y, float radius, int direction, int halfSize, bool active, FOVType type);
~FieldOfView();
vec2f getPosition();
float getRadius();
int getDirection();
int getSize();
void addVertex(float x, float y);
void changeVertex(unsigned int i, float x, float y); //for calculating light when door opens or closes.
float* getVertData();
int getNumberOfVerts();
void moveTo(float x, float y);
void clearVerts();
void getColors(float* r, float* g, float* b);
Rect getCollisionRect();
FOVType getType();
float _red;
float _green;
float _blue;
bool _active;
LightFixture* _fixture;
private:
vec2f _position;
float _radius;
int _direction;
int _halfSize;
std::vector _verts;
FOVType _type;
};
struct LightAndAngles
{
FieldOfView* fov;
int angle1;
int angle2;
};
class Entity
{
public:
Entity(float x, float y);
Entity(float x, float y, unsigned int sprite);
virtual ~Entity();
vec2f getPosition();
vec2f getVelocity();
float getRotation();
void setPosition(float x, float y);
void setCollisionRectPosition(float x, float y);
void setCollisionRectDims(float w, float h, int entDim);
void setCollisionRectDimsAndPosition(float x, float y, float w, float h, int entDim);
void setPosX(float x);
void setPosY(float y);
void setPosition(vec2f newPos);
void setVelocity(float x, float y);
void setVelX(float x);
void setVelY(float y);
virtual void update(unsigned int dT);
Rect getCollisionRect();
vec2f getCollisionRectPosition();
vec2f getCollisionRectCenterPosition();
void updateCollisionRectPosition();
unsigned int getCurrentSprite();
void changeToStaticSprite(unsigned int sprite);
void changeAnimationSequence(AnimationSequence* sequence);
void changeAnimationSequenceForce(AnimationSequence* sequence);
bool _highlighted;
protected:
vec2f _position;
vec2f _offset;
vec2f _velocity;
float _rotation;
Rect _collisionRect;
unsigned int _sprite;
AnimationSequence* _activeSequence; //what animation is this entity currently running?
float _animDT;
unsigned int _currentSequenceIndex;
bool _currentAnimFinished;
};
class Particle : public Entity //probably used only for glass shards.
{
public:
Particle(float x, float y, unsigned int sprite);
void update(unsigned int dT);
bool _alive;
};
class TutorialMark : public Entity
{
public:
TutorialMark(float x, float y, StringMessage ts);
StringMessage _ts;
};
class Stairwell;
class Stairs : public Entity
{
public:
Stairs(float x, float y);
void registerStairwell(Stairwell* well);
Stairs* getUpstairs();
Stairs* getDownstairs();
void setUpstairs(Stairs* target);
void setDownstairs(Stairs* target);
private:
Stairs* _upstairs;
Stairs* _downstairs;
Stairwell* _well;
};
class Stairwell
{
public:
Stairwell(int x);
~Stairwell();
void addStairs(Stairs* stairs);
int getX();
void setDirections(unsigned int yMax);
private:
std::vector _stairs;
int _x;
};
class ElevatorShaft;
class ElevatorSwitch;
class ElevatorDoor : public Entity
{
public:
ElevatorDoor(float x, float y);
bool isOpen();
void open(bool animate);
void close( bool animate);
void update(unsigned int dT);
bool isOpening();
bool isClosing();
ElevatorShaft* _shaft;
ElevatorSwitch* _switch;
private:
bool _open;
};
class ElevatorShaft
{
public:
ElevatorShaft(int x);
~ElevatorShaft();
void addDoor(ElevatorDoor* ed);
void update();
int containsDoor(ElevatorDoor* door);
void setOpenDoor(ElevatorDoor* door, bool animate);
void setOpenDoorFirst();
void setTarget(ElevatorDoor* target);
vec2f getElevatorPosition();
Rect getRect();
ElevatorDoor* getOpenDoor();
ElevatorDoor* getTarget();
void calculateDoorOrders(int yMax);
ElevatorDoor* getDoorAbove(ElevatorDoor* door);
ElevatorDoor* getDoorBelow(ElevatorDoor* door);
int getDoorIndexOrdered(int index);
float _yVel;
bool _moving;
int _x;
private:
std::vector _doors;
std::vector _order;
Rect _rect;
vec2f _elevatorPosition; //where bounding box is drawn.
ElevatorDoor* _target;
ElevatorDoor* _openDoor;
bool _waitingForClose;
Acceleration _acceleration;
};
class MainComputer : public Entity
{
public:
MainComputer(float x, float y, bool active);
bool isActive();
void setActive(bool b);
private:
bool _active;
};
class CircuitBox : public Entity
{
public:
CircuitBox(float x, float y, Circuit circuit);
bool isHacked();
void setHacked(bool hacked, bool playSound);
Circuit getCircuit();
private:
Circuit _circuit;
bool _hacked;
};
class LivingEntity : public Entity
{
public:
LivingEntity(float x, float y, Direction startingDir);
void update(unsigned int dT);
void setAlive(bool b);
bool isAlive();
virtual void landOnGround();
void setStairMovement(StairTraversal st);
StairTraversal getStairTraversal();
virtual void arriveAtStairs(Stairs* st);
Direction getDirection();
void reverseDirection();
bool isMovingThroughStairs();
int getStairTimer();
void setDirection(Direction dir);
Stairs* getStairsEntered();
virtual bool isAnimatingThroughStairs() = 0;
Acceleration* getAccelerationStruct();
bool isPositionBehind(float x);
bool _onGround;
Stairs* _overlappingStairs;
protected:
bool _alive;
bool _fixDirection;
bool _affectedByGravity;
Direction _dir;
int _stairTimer;
StairTraversal _traversal;
Stairs* _stairsEntered;
Acceleration _acceleration;
private:
};
class LinkableEntity : public Entity
{
public:
LinkableEntity(float x, float y, Circuit c);
Circuit getCircuitType();
LinkableEntity* getTarget();
void link(LinkableEntity* target, bool playSound);
virtual void unlink();
virtual void activate(LinkableEntity* activator);
bool hasCycle();
protected:
Circuit _circuit;
LinkableEntity* _other;
private:
};
class LightSwitch : public LinkableEntity
{
public:
LightSwitch(float x, float y, Circuit c, bool hs); //hs = isHandScanner
void activate(LinkableEntity* activator);
bool isHandScanner();
private:
bool _isHandScanner;
};
class ElevatorSwitch : public LinkableEntity
{
public:
ElevatorSwitch(float x, float y, Circuit c);
void activate(LinkableEntity* activator);
void activateTarget();
void changeSprite(unsigned int sprite);
ElevatorDoor* _door;
};
class Door : public LinkableEntity
{
public:
Door(float x, float y, Circuit c, bool open, DoorType type);
CollisionVolume* getCollisionVolume();
CollisionVolume* getCollisionVolume2();
void update(unsigned int dT);
void updateCollisionVolume();
void activate(LinkableEntity* activator);
bool isOpened();
void open(Direction opendir);
void close(Direction opendir);
void openSound(Direction opendir);
void closeSound(Direction opendir);
void addOverlappingLight(FieldOfView* fov, int angle1, int angle2);
size_t getNumberOfOverlappingLights();
void setOpenDirection(Direction opendir);
Direction getOpenDirection();
FieldOfView* getLightAndAnglesAt(int i, int* angle1, int* angle2);
DoorType getType();
int getTimeToClose(); //for save games.
bool dirty;
private:
DoorType _type;
int _timeToClose; //for trap and vault doors only.
bool _opened;
CollisionVolume* _cvol;
CollisionVolume* _cvol2;
std::vector _overlappingLights; //all lights here update when opened or closed.
Direction _opendir;
};
class MotionScanner : public LinkableEntity
{
public:
MotionScanner(float x, float y, Circuit c);
Entity* getTrespasser();
void setTrespasser(Entity* ent);
void resetTrespasser();
bool _trespassed; //set to true when an entity (probably living) has overlapped collisionRect. Do not activate() while true, to prevent multiple activations.
private:
Entity* _trespasser;
};
class SecurityCamera : public LinkableEntity
{
public:
SecurityCamera(float x, float y, Circuit c, Direction dir, FieldOfView* fov);
void activate(LinkableEntity* activator);
FieldOfView* getFOV();
bool _trespassed; //set to true when an entity (probably living) has overlapped collisionRect. Do not activate() while true, to prevent multiple activations.
private:
Direction _direction;
FieldOfView* _fov;
};
class LightFixture : public LinkableEntity
{
public:
LightFixture(float x, float y, Circuit c, bool switchedOn);
~LightFixture();
void activate(LinkableEntity* activator);
void toggleAllFOVs();
void setSwitchedOn(bool sw);
bool isSwitchedOn();
void addFOV(FieldOfView* fov);
private:
bool _switchedOn;
std::vector _lights;
};
class PowerSocket : public LinkableEntity
{
public:
PowerSocket(float x, float y, Circuit c);
void activate(LinkableEntity* activator);
void deactivate();
bool isLive();
private:
bool _live;
};
class SoundDetector : public LinkableEntity
{
public:
SoundDetector(float x, float y, Circuit c);
void unlink();
void activate(LinkableEntity* activator);
private:
bool _soundedAlarm;
};
class Alarm : public LinkableEntity
{
public:
Alarm(float x, float y, Circuit c);
void activate(LinkableEntity* activator);
void deactivate();
void setAnimating(bool b);
bool isActivated();
bool _sounded;
};
class Enemy;
class EnemyGun : public LinkableEntity
{
public:
EnemyGun(float x, float y, Circuit c);
void activate(LinkableEntity* activator);
void fire(GunShotTraceType gstt);
void update(unsigned int dT);
Enemy* _enemy;
};
class Enemy : public LivingEntity
{
public:
Enemy(float x, float y, Direction startingDir, bool startPatrol, EnemyType type);
void update(unsigned int dT);
void setPosition(float x, float y);
void landOnGround();
void seePlayer(float x, float y);
void alertToPosition(float x, float y, AlertType aType, TargetType tType);
bool hasSeenPlayer();
void loseSightOfPlayer(bool wentInElevator, vec2f newTarget);
bool canSeePlayer();
void changeState(GuardState state);
GuardState getState();
AlertType getAlertType();
vec2f getTarget();
void setDesiredStairsAndDirection(Stairs* sw, StairTraversal st);
bool goingForStairs();
void setSecondaryTarget(Entity* ent);
Entity* getSecondaryTarget();
unsigned int getNumSwitchAttempts();
void resetSwitchAttempts();
void setStrongestLight(FieldOfView* fov);
void setLightToActivate(FieldOfView* toActivate); //used for loading saved games only.
void loseStrongestLight(); //called only when strongestLight is suddenly set to inactive.
FieldOfView* getStrongestLight();
FieldOfView* getLightToActivate();
TargetType getTargetType();
void forgetTarget();
void setLinkableTarget(LinkableEntity* ls);
LinkableEntity* getTargetSwitch();
bool ignoringFall();
void setIgnoreFall(bool b);
void setReadyToShoot(bool b);
void resetReactionTime();
void setReactionTime(int time);
int getReactionTime();
EnemyType getType();
void setHeldAtGunpoint(bool b);
bool isHeldAtGunpoint();
void setResolve(int timeToReact, GunShotTraceType gstt);
void setSprite();
void arriveAtStairs(Stairs* st);
bool isAnimatingThroughStairs();
void setStairMovement(StairTraversal st);
//save game related only.
bool isWaitingForAlert();
void setWaitingForAlert(bool b);
void setCanSeePlayer(bool b);
bool _scene_trace_bullet;
vec2f _shootTarget; //usually set to _target, unless gun is activated by something else...
void _fireWeapon(GunShotTraceType gstt); //ugh.
EnemyShotResolve getResolve();
EnemyGun* _gun;
private:
int _reactionTime; //time between seeing player and shooting.
int _timeToResetReactionTime;
EnemyShotResolve _resolve;
bool _playerInSight;
bool _hasSeenPlayer; //used to detect how many guards in a level has seen the player for statistical purposes.
vec2f _target; //try to move here when INVESTIGATING.
GuardState _state;
bool _fullyPunched; //used to play punch sound once in punching animation.
StairTraversal _desiredStairDirection;
int _timeToPatrol;
int _timeToTurn1;
int _timeToTurn2;
int _timeToHitSwitch;
int _timeToAlert;
bool _waitingForAlert;
LinkableEntity* _targetSwitch;
Entity* _secondaryTarget; //a handscanner or stairs.
unsigned int _numSwitchAttempts;
FieldOfView* _lightToActivate; //former strongest light that was just turned off. Try to "activate" again.
FieldOfView* _strongestLight;
TargetType _targetType;
AlertType _alertType;
bool _ignoreFall;
bool _readyToShoot;
bool _heldAtGunpoint;
EnemyType _type;
};
class Player : public LivingEntity
{
public:
Player(float x, float y, Direction startingDir);
~Player();
void update(unsigned int dT);
void setVelX(float x);
void setVelY(float y);
void die();
void landOnGround();
void jump(float x, float y);
bool isJumping();
bool isPinning();
bool isHacking();
bool isAttachingDown();
bool isGoingUpRoof();
void pinEnemy(Enemy* enemy);
void hackTerminal(MainComputer* computer);
void punchPinnedEnemy();
unsigned int getNumPunches();
void releasePin();
Enemy* getPinnedEnemy();
AttachType getAttachType();
AttachType getLastAttachType();
void attachToVolume(CollisionVolume* volume, AttachType at);
void detach();
CollisionVolume* getAttachedVolume();
bool isInElevator();
void enterElevator(ElevatorDoor* door);
void switchElevator(ElevatorDoor* door);
void leaveElevator();
ElevatorDoor* getElevatorDoor();
void setStairMovement(StairTraversal st);
void arriveAtStairs(Stairs* st);
bool isAnimatingThroughStairs();
int getArmRotation();
void setArmRotation(int rotation);
void setAimingGun(bool b);
bool isAimingGun();
unsigned int _lightVisibility; //between 0 and 100.
unsigned int _numHackedTerminals;
int _armRotation;
private:
bool _jumping;
bool _pinning;
unsigned int _numPunches;
bool _inElevator;
AttachType _attach;
AttachType _lastAttach;
ElevatorDoor* _door;
Enemy* _pinnedEnemy;
MainComputer* _hackedTerminal;
CollisionVolume* _attachedVolume; //The Collision Volume the player is attached to.
bool _aimingGun;
//deleted by AnimationManager.
AnimationSequence* _runningSequence;
AnimationSequence* _climbingUpSequence;
AnimationSequence* _ceilingSequence;
AnimationSequence* _hackingSequence;
AnimationSequence* _attachDownSequence;
AnimationSequence* _reachRoofSequence;
AnimationSequence* _attachToCeiling;
AnimationSequence* _attachFromCeiling;
AnimationSequence* _enterStairs;
AnimationSequence* _exitStairs;
AnimationSequence* _walkingSequence;
};
#endif