Show IEntity.cpp syntax highlighted
/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG *
*Copyright (C) 2006, Tony Sparks *
* *
*This library is free software; you can redistribute it and/or *
*modify it under the terms of the GNU Lesser General Public *
*License as published by the Free Software Foundation; either *
*version 2.1 of the License, or (at your option) any later version. *
* *
*This library 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 *
*Lesser General Public License for more details. *
* *
*You should have received a copy of the GNU Lesser General Public *
*License along with this library; if not, write to the Free Software *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
**************************************************************************************
*/
#include "stdafx.h"
#include "IEntity.h"
#include "IWeapon.h"
#include <math.h>
#include "../kernel.h"
extern Kernel* g_kernel;
#define TIME g_kernel->GetTime()
#define RUN_SCRIPT( str ) (g_kernel->GetScriptEngine()->RunFile( #str ))
IEntity::IEntity()
{
m_active = true;
m_remove = false;
m_name = "Entity";
m_bounds.y = m_bounds.x = 0;
m_bounds.width = 0;
m_bounds.height = 0;
m_actions = 0;
m_health = 0;
m_flags = 0;
m_id = 0;
m_nextUpdate = 0.0f;
m_moveTime = 0.0f;
m_heightAboveGround = 0.0f;
m_gravity = 0.0f;
m_face = SOUTH;
m_oldFace = SOUTH;
m_dest.Set( 0, 0 );
m_throwVel.ZeroOut();
m_forward.ZeroOut();
m_world.Set( 0, 0 );
m_velocity.Set(0,0);
m_baseVelocity.Set( 0,0 );
m_position.Set( 0,0 );
m_carriedent = NULL;
m_carrier = NULL;
m_entCtrl.SetEntity( this );
m_FSM.SetOwner( this );
}
IEntity::IEntity(const IEntity &ent)
{
m_active = ent.m_active;
m_remove = ent.m_remove;;
m_name = ent.m_name;
m_bounds = ent.m_bounds;
m_health = ent.m_health;
m_flags = ent.m_flags;
m_face = ent.m_face;
m_oldFace = ent.m_oldFace;
m_dest .Set( ent.m_dest );
m_throwVel .Set( ent.m_throwVel );
m_forward .Set ( ent.m_forward );
m_world .Set( ent.m_world );
m_velocity .Set( ent.m_velocity );
m_baseVelocity .Set( ent.m_baseVelocity );
m_position .Set( ent.m_position );
m_actions = 0;
m_id = 0;
m_nextUpdate = 0.0f;
m_moveTime = 0.0f;
m_heightAboveGround = 0.0f;
m_gravity = 0.0f;
m_carriedent = NULL;
m_carrier = NULL;
// TODO - copy the dictionary
m_entCtrl.SetEntity( this );
m_FSM.SetOwner( this );
}
// TODO - delete states
IEntity:: ~IEntity()
{
g_kernel->GetConsole()->Print( "***Entity Memory Report: %d bytes", sizeof( *this ) );
// Delete all the states
type_States::iterator it = m_states.begin();
for( ; it != m_states.end(); it++ )
{
if ( it->second )
delete it->second;
}
}
/** Apply Common Dictionary Attributes */
void IEntity::Apply()
{
m_world = m_attributes.GetVector2f("location");
m_baseVelocity = m_attributes.GetVector2f("base_velocity");
m_bounds.width = m_attributes.GetInt("width");
m_bounds.height = m_attributes.GetInt("height");
m_health = m_attributes.GetInt("health");
m_position.Set( m_world.x, m_world.y );
SetBounds( m_world.x /*+ m_bounds.width/2*/, m_world.y + m_bounds.height, m_bounds.width,m_bounds.height);
}
/** Update the Position Coordinates */
void IEntity::UpdateScreenCoord( const Vector2f &screenCoords )
{
// update the screen coords
m_position.Set( screenCoords );
}
/** Update bounds */
void IEntity::UpdateCollisionBounds( int x, int y )
{
//if ( GetName() == "pot1" )
//std::cout << "***Updating bounds\n";
SetBounds( x/*+(GetBounds().width/2)*/ , y + GetBounds().height, GetBounds().width, GetBounds().height );
}
/*-------------------------------
TEMP - Test out moving an entity
-------------------------------*/
/** Update the entity */
void IEntity::Update( long dt)
{
m_nextUpdate = TIME + 10;
m_FSM.Update();
// we are in the possession of
// someone else or being thrown
if ( GetState() == ENT_STATES[ THROWN ] || CarriedBy() )
return;
CheckFace(m_actions); // check the direction of the entity
// The entity is attempting to attack
if ( m_actions & BUTTON_ATTACK1 )
{
if ( CarryingEntity() )
{
Throw();
}
else
{
// TODO - attack based off of weapon
m_nextUpdate = TIME + 450; // TEMP
SetState( ENT_STATES[ATTACKING1] );
}
return;
}
// The entity is attempting to 'use'
if ( m_actions & BUTTON_USE )
{
if ( CarryingEntity() )
{
Throw();
}
else
{
// search for an entity in a region -- TODO THIS IS HORRIBLY SLOW!!!
IEntity* ent = EntityManager::GetInstance()->FindInRegion( GetReachRectangle(), this );
if ( ent && ent != this )
{
if ( ent->m_attributes.Has( "dialog" ) )
{
ent->SetFace( (GetFace() + 2) % 4);
ent->SetState( ENT_STATES[TALKING] );
}
else if ( ent->m_attributes.Has( "liftable" ) )
{
if ( !CarryingEntity() )
{
Carry( ent );
}
}
}
}
return;
}
// Check for movement
if ( m_velocity.Length() )
{
// switch the state to walking
if ( CarryingEntity() )
{
SetState( ENT_STATES[CARRYING_WALKING] );
}
else
{
SetState( ENT_STATES[WALKING] );
}
}
else
{
// switch the state to idle
if ( CarryingEntity() )
{
SetState( ENT_STATES[CARRYING] );
}
else
{
SetState( ENT_STATES[IDLE] );
}
}
}
/** Damage this entity */
int IEntity::Damage( int hit )
{
// Make sure this entity is destructable
if ( !m_attributes.Has("health") )
return 0;
SetState( ENT_STATES[HIT] ); // set to the hit state
m_nextUpdate = TIME + 450; // let the hit animation time run
int old = m_health; // save old health
m_health += hit; // damage the health
// if we are holding something, throw it
if ( CarryingEntity() )
{
Throw();
}
// set the dead state
if ( m_health <= 0 )
{
// TODO - SET DEAD STATE
SetState(ENT_STATES[DEAD]);
}
return old;
}
/** Throws the entity */
void IEntity::Throw()
{
if ( m_carriedent )
{
SetState( ENT_STATES[THROWING] );
m_carriedent->SetState( ENT_STATES[THROWN] );
Vector2f thrownTo;
const float dest = 2.0f;
thrownTo = m_forward * dest;
m_carriedent->m_heightAboveGround = 16;
m_carriedent->MoveToOverTime( thrownTo, TIME + 500 );
m_carriedent->m_carrier = NULL;
m_carriedent = NULL;
//m_nextUpdate = TIME + 600;
}
}
/** Pick Up an Item */
void IEntity::PickUpItem(IEntity* ent)
{
ent->m_flags &= ~EF_WP_ONGROUND; // turn off the on ground flag
ent->m_flags |= EF_NOTONSCREEN; // don't draw it either
EntityManager::GetInstance()->RemoveWithoutDeleting( ent );
// run a picked up script if needed
if ( ent->m_attributes.Has( "pickedup" ) )
RUN_SCRIPT( ent->m_attributes.GetStr( "pickedup" ) );
switch( ent->GetType() )
{
case TYPE_BASE:
m_itemInventory.Add( ent );
break;
case TYPE_WEAPON:
IWeapon* weapon = static_cast<IWeapon*>(ent);
weapon->SetOwner( this );
m_weaponInventory.Add( weapon );
break;
}
}
/** Arrived to location */
bool IEntity::ArrivedToLocation()
{
return TIME > m_moveTime;
}
/** Get the Reach rectangle - creates a rect infront of entity */
Rect IEntity::GetReachRectangle()
{
// distance to move
int destw = GetBounds().width;
int desth = GetBounds().height;
int w = GetBounds().width;
int h = GetBounds().height;
Vector2f spot;
spot.Set( m_world );
switch( GetFace() )
{
case NORTH:
break;
case EAST: spot.y += desth; spot.x += destw;
break;
case SOUTH: spot.y += (desth*2);
break;
case WEST: spot.y += desth; spot.x -= destw;
break;
}
Rect reach( spot.x, spot.y, w, h );
return reach;
}
/** Check the face Direction of the player */
void IEntity::CheckFace(int action)
{
m_velocity.ZeroOut();
int lastFace = GetFace();
// vertical movement
if( action & BUTTON_UP ) {
m_velocity.y = -1;
if( lastFace == SOUTH || !(action & (BUTTON_LEFT|BUTTON_RIGHT)) ) {
SetFace(NORTH);
}
} else if ( action & BUTTON_DOWN ) {
m_velocity.y = 1;
if( lastFace == NORTH || !(action & (BUTTON_LEFT|BUTTON_RIGHT)) ) {
SetFace(SOUTH);
}
}
// horizontal movement
if( action & BUTTON_LEFT ) {
m_velocity.x = -1;
if( lastFace == EAST || !(action & (BUTTON_UP|BUTTON_DOWN)) ) {
SetFace(WEST);
}
} else if ( action & BUTTON_RIGHT ) {
m_velocity.x = 1;
if( lastFace == WEST || !(action & (BUTTON_UP|BUTTON_DOWN)) ) {
SetFace(EAST);
}
}
}
/** Set the direction */
void IEntity::SetFace( int f)
{
m_oldFace = m_face;
m_face = f;
m_forward.ZeroOut();
// make the correct forward vec
switch( m_face )
{
case NORTH: m_forward.Set( 0, -1 );
break;
case SOUTH: m_forward.Set( 0, 1 );
break;
case EAST: m_forward.Set( 1, 0 );
break;
case WEST: m_forward.Set( -1, 0 );
break;
default: m_forward.Set( 1, 1 );
break;
};
}
See more files for this project here