#Bar borders and angle penalty
-Changes to notifications. They take different parameters now-see template_entity_script.js. You can choose to destroy the notifiers yourself in the script (useful for idle) -Added "idle" event with registerIdle and registerDamage to assist with the angle penalty. -Bar border stuff -Angle penalty is set up but untested-it just needs to use this.getAttackDirections() to find the number of directions the entity is being attacked from. The penalty is specified in template_unit There is a problem when the game exits-it attempts to destroy the notifiers in entity.cpp's constructor, where it calls DestroyAllNotifiers(). The problem is that the notifiers don't exist any longer because they've been destroyed. I would fix it but I'm leaving for vacation (Jason told me it was OK to comitt). Hope it isn't too much of a problem. This was SVN commit r3732.
This commit is contained in:
parent
b6d46bb918
commit
f2e867e239
@ -352,12 +352,18 @@ void Render()
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
g_Selection.renderRanks();
|
||||
g_Mouseover.renderRanks();
|
||||
g_Mouseover.renderBarBorders();
|
||||
g_Selection.renderBarBorders();
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
g_Mouseover.renderHealthBars();
|
||||
g_Selection.renderHealthBars();
|
||||
g_Mouseover.renderStaminaBars();
|
||||
g_Selection.renderStaminaBars();
|
||||
g_Selection.renderRanks();
|
||||
g_Mouseover.renderRanks();
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
@ -502,6 +508,8 @@ static void InitScripting()
|
||||
|
||||
g_ScriptingHost.DefineConstant( "FORMATION_ENTER", CFormationEvent::FORMATION_ENTER );
|
||||
g_ScriptingHost.DefineConstant( "FORMATION_LEAVE", CFormationEvent::FORMATION_LEAVE );
|
||||
g_ScriptingHost.DefineConstant( "FORMATION_DAMAGE", CFormationEvent::FORMATION_DAMAGE );
|
||||
g_ScriptingHost.DefineConstant( "FORMATION_ATTACK", CFormationEvent::FORMATION_ATTACK );
|
||||
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_NONE", CEntityListener::NOTIFY_NONE );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_GOTO", CEntityListener::NOTIFY_GOTO );
|
||||
@ -513,6 +521,8 @@ static void InitScripting()
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_ESCORT", CEntityListener::NOTIFY_ESCORT );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_HEAL", CEntityListener::NOTIFY_HEAL );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_GATHER", CEntityListener::NOTIFY_GATHER );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_IDLE", CEntityListener::NOTIFY_IDLE );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_ALL", CEntityListener::NOTIFY_ALL );
|
||||
|
||||
g_ScriptingHost.DefineConstant( "ORDER_NONE", -1 );
|
||||
g_ScriptingHost.DefineConstant( "ORDER_GOTO", CEntityOrder::ORDER_GOTO );
|
||||
|
@ -118,6 +118,25 @@ void CSelectedEntities::renderStaminaBars()
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
}
|
||||
void CSelectedEntities::renderBarBorders()
|
||||
{
|
||||
std::vector<HEntity>::iterator it;
|
||||
for( it = m_selected.begin(); it < m_selected.end(); it++ )
|
||||
(*it)->renderBarBorders();
|
||||
|
||||
if( m_group_highlight != -1 )
|
||||
{
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glEnable( GL_BLEND );
|
||||
|
||||
std::vector<HEntity>::iterator it;
|
||||
for( it = m_groups[m_group_highlight].begin(); it < m_groups[m_group_highlight].end(); it++ )
|
||||
(*it)->renderBarBorders();
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
}
|
||||
|
||||
void CSelectedEntities::renderRanks()
|
||||
{
|
||||
std::vector<HEntity>::iterator it;
|
||||
@ -828,34 +847,48 @@ void CMouseoverEntities::renderRanks()
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
|
||||
|
||||
int CSelectedEntities::loadRankTextures()
|
||||
void CMouseoverEntities::renderBarBorders()
|
||||
{
|
||||
VFSUtil::FileList ranklist;
|
||||
VFSUtil::FindFiles( "art/textures/ui/session/icons", 0, ranklist );
|
||||
for ( std::vector<CStr>::iterator it = ranklist.begin(); it != ranklist.end(); it++ )
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glEnable( GL_BLEND );
|
||||
|
||||
std::vector<SMouseoverFader>::iterator it;
|
||||
for( it = m_mouseover.begin(); it < m_mouseover.end(); it++ )
|
||||
it->entity->renderBarBorders();
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
static void LoadUnitUIThunk( const char* path, const DirEnt* UNUSED(ent), void* context )
|
||||
{
|
||||
std::map<CStr, Handle>* textures = (std::map<CStr, Handle>*) context;
|
||||
CStr name(path);
|
||||
|
||||
if ( !tex_is_known_extension(path) )
|
||||
{
|
||||
const char* filename = it->c_str();
|
||||
if ( !tex_is_known_extension(filename) )
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "Unknown rank texture extension (%s)", filename);
|
||||
continue;
|
||||
}
|
||||
Handle ht = ogl_tex_load(filename);
|
||||
if (ht <= 0)
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "loadRankTextures failed on \"%s\"", filename);
|
||||
return ht;
|
||||
}
|
||||
m_rankTextures[it->AfterLast("/")] = ht;
|
||||
RETURN_ERR(ogl_tex_upload(ht));
|
||||
if ( name.BeforeLast(".") == name ) //this is a directory (contains no ".")
|
||||
return;
|
||||
LOG(ERROR, "Unknown rank texture extension (%s)", path);
|
||||
return;
|
||||
}
|
||||
Handle tmp = ogl_tex_load(path);
|
||||
if (tmp <= 0)
|
||||
{
|
||||
LOG(ERROR, "Rank Textures", "loadRankTextures failed on \"%s\"", path);
|
||||
return;
|
||||
}
|
||||
name.Remove("art/textures/ui/session/icons/"); //Names are relative to this directory
|
||||
(*textures)[name] = tmp;
|
||||
ogl_tex_upload(tmp);
|
||||
}
|
||||
int CSelectedEntities::loadUnitUITextures()
|
||||
{
|
||||
THROW_ERR( VFSUtil::EnumDirEnts( "art/textures/ui/session/icons/", VFSUtil::RECURSIVE,
|
||||
NULL, LoadUnitUIThunk, &m_unitUITextures ) );
|
||||
return 0;
|
||||
}
|
||||
void CSelectedEntities::destroyRankTextures()
|
||||
void CSelectedEntities::destroyUnitUITextures()
|
||||
{
|
||||
for ( std::map<CStr, Handle>::iterator it=m_rankTextures.begin(); it != m_rankTextures.end(); it++ )
|
||||
for ( std::map<CStr, Handle>::iterator it=m_unitUITextures.begin(); it != m_unitUITextures.end(); it++ )
|
||||
{
|
||||
ogl_tex_free(it->second);
|
||||
it->second = 0;
|
||||
|
@ -37,11 +37,11 @@ struct CSelectedEntities : public Singleton<CSelectedEntities>
|
||||
m_selectionChanged = true;
|
||||
m_mouseOverMM = false;
|
||||
|
||||
loadRankTextures();
|
||||
loadUnitUITextures();
|
||||
}
|
||||
~CSelectedEntities()
|
||||
{
|
||||
destroyRankTextures();
|
||||
destroyUnitUITextures();
|
||||
}
|
||||
std::vector<HEntity> m_selected;
|
||||
std::vector<HEntity> m_groups[MAX_GROUPS];
|
||||
@ -78,10 +78,11 @@ struct CSelectedEntities : public Singleton<CSelectedEntities>
|
||||
void renderHealthBars();
|
||||
void renderStaminaBars();
|
||||
void renderRanks();
|
||||
void renderBarBorders();
|
||||
|
||||
void destroyRankTextures();
|
||||
int loadRankTextures();
|
||||
std::map<CStr, Handle> m_rankTextures;
|
||||
void destroyUnitUITextures();
|
||||
int loadUnitUITextures();
|
||||
std::map<CStr, Handle> m_unitUITextures;
|
||||
};
|
||||
|
||||
// CMouseoverEntities: the singleton containing entities the mouse is currently hovering over or bandboxing
|
||||
@ -133,6 +134,7 @@ struct CMouseoverEntities : public Singleton<CMouseoverEntities>
|
||||
void renderHealthBars();
|
||||
void renderStaminaBars();
|
||||
void renderRanks();
|
||||
void renderBarBorders();
|
||||
|
||||
bool isBandbox() { return( m_bandbox ); }
|
||||
void startBandbox( u16 x, u16 y );
|
||||
|
@ -22,6 +22,7 @@ enum EEventType
|
||||
EVENT_ORDER_TRANSITION,
|
||||
EVENT_NOTIFICATION,
|
||||
EVENT_FORMATION,
|
||||
EVENT_IDLE,
|
||||
EVENT_LAST,
|
||||
|
||||
// Projectile events
|
||||
@ -49,7 +50,8 @@ static const wchar_t* const EventNames[EVENT_LAST] =
|
||||
/* EVENT_PREPARE_ORDER */ L"onPrepareOrder", /* To check if a unit can execute a given order */
|
||||
/* EVENT_ORDER_TRANSITION */ L"onOrderTransition", /* When we change orders (sometimes...) */
|
||||
/* EVENT_NOTIFICATION */ L"onNotification", /*When we receive a notification */
|
||||
/* EVENT_FORMATION */ L"onFormation" /* When this unit does something with a formation */
|
||||
/* EVENT_FORMATION */ L"onFormation", /* When this unit does something with a formation */
|
||||
/* EVENT_IDLE */ L"onIdle" /* When this unit becomes idle, do something */
|
||||
};
|
||||
|
||||
#endif // #ifndef EVENTTYPES_H__
|
||||
|
@ -231,12 +231,11 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
|
||||
else
|
||||
entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0]));
|
||||
|
||||
//Destroy old listeners if we're explicitly being reassigned
|
||||
//Destroy old notifiers if we're explicitly being reassigned
|
||||
for ( size_t i=0; i < entities.size(); i++)
|
||||
{
|
||||
if ( entities[i]->m_currentListener )
|
||||
entities[i]->DestroyListeners( entities[i]->m_currentListener );
|
||||
entities[i]->m_currentListener = NULL;
|
||||
if ( entities[i]->m_destroyNotifiers )
|
||||
entities[i]->DestroyAllNotifiers();
|
||||
}
|
||||
std::vector<CNetMessage*> messages;
|
||||
CNetMessage* msg = CNetMessage::CommandFromJSArgs(entities, cx, argc-1, argv+1);
|
||||
@ -273,6 +272,48 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
//Formation stuff
|
||||
JSBool createEntityFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
REQUIRE_MIN_PARAMS(2, createEntityFormation);
|
||||
|
||||
CEntityList entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0]));
|
||||
CStrW name = ToPrimitive<CStrW>( argv[1] );
|
||||
g_FormationManager.CreateFormation( entities, name );
|
||||
*rval = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
|
||||
}
|
||||
JSBool removeFromFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
REQUIRE_MIN_PARAMS(1, removeFromFormation);
|
||||
|
||||
CEntityList entities;
|
||||
if (JS_GetClass(JSVAL_TO_OBJECT(argv[0])) == &CEntity::JSI_class)
|
||||
entities.push_back( (ToNative<CEntity>(argv[0])) ->me);
|
||||
else
|
||||
entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0]));
|
||||
|
||||
*rval = g_FormationManager.RemoveUnitList(entities) ? JS_TRUE : JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
JSBool lockEntityFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
REQUIRE_MIN_PARAMS(1, lockEntityFormation);
|
||||
|
||||
CEntity* entity = ToNative<CEntity>( argv[0] );
|
||||
entity->GetFormation()->SetLock( ToPrimitive<bool>( argv[1] ) );
|
||||
*rval = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
JSBool isFormationLocked( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
REQUIRE_MIN_PARAMS(1, isFormationLocked);
|
||||
|
||||
CEntity* entity = ToNative<CEntity>( argv[0] );
|
||||
*rval = entity->GetFormation()->IsLocked() ? JS_TRUE : JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Events
|
||||
@ -1072,6 +1113,11 @@ JSFunctionSpec ScriptFunctionTable[] =
|
||||
JS_FUNC(issueCommand, issueCommand, 2)
|
||||
JS_FUNC(startPlacing, startPlacing, 1)
|
||||
|
||||
JS_FUNC(createEntityFormation, createEntityFormation, 2)
|
||||
JS_FUNC(removeFromFormation, removeFromFormation, 1)
|
||||
JS_FUNC(lockEntityFormation, lockEntityFormation, 1)
|
||||
JS_FUNC(isFormationLocked, isFormationLocked, 1)
|
||||
|
||||
// Camera
|
||||
JS_FUNC(setCameraTarget, setCameraTarget, 1)
|
||||
|
||||
|
@ -31,14 +31,25 @@ CBaseEntity::CBaseEntity()
|
||||
AddProperty( L"traits.health.max", &m_healthMax );
|
||||
AddProperty( L"traits.health.bar_height", &m_healthBarHeight );
|
||||
AddProperty( L"traits.health.bar_size", &m_healthBarSize );
|
||||
AddProperty( L"traits.health.bar_width", &m_healthBarWidth );
|
||||
AddProperty( L"traits.health.border_height", &m_healthBorderHeight);
|
||||
AddProperty( L"traits.health.border_width", &m_healthBorderWidth );
|
||||
AddProperty( L"traits.health.border_name", &m_healthBorderName );
|
||||
AddProperty( L"traits.health.regen_rate", &m_healthRegenRate );
|
||||
AddProperty( L"traits.health.regen_start", &m_healthRegenStart );
|
||||
AddProperty( L"traits.health.decay_rate", &m_healthDecayRate );
|
||||
|
||||
AddProperty( L"traits.stamina.curr", &m_staminaCurr );
|
||||
AddProperty( L"traits.stamina.max", &m_staminaMax );
|
||||
AddProperty( L"traits.stamina.bar_height", &m_staminaBarHeight );
|
||||
AddProperty( L"traits.stamina.bar_size", &m_staminaBarSize );
|
||||
AddProperty( L"traits.rank.size", &m_rankSize );
|
||||
AddProperty( L"traits.stamina.bar_width", &m_staminaBarWidth );
|
||||
AddProperty( L"traits.stamina.border_height", &m_staminaBorderHeight);
|
||||
AddProperty( L"traits.stamina.border_width", &m_staminaBorderWidth );
|
||||
AddProperty( L"traits.stamina.border_name", &m_staminaBorderName );
|
||||
AddProperty( L"traits.angle_penalty.sectors", &m_sectorDivs );
|
||||
AddProperty( L"traits.angle_penalty.value", &m_sectorPenalty );
|
||||
AddProperty( L"traits.rank.width", &m_rankWidth );
|
||||
AddProperty( L"traits.rank.height", &m_rankHeight );
|
||||
AddProperty( L"traits.rank.name", &m_rankName );
|
||||
AddProperty( L"traits.minimap.type", &m_minimapType );
|
||||
|
@ -61,20 +61,30 @@ public:
|
||||
float m_staminaMax;
|
||||
float m_staminaBarHeight;
|
||||
int m_staminaBarSize;
|
||||
|
||||
float m_staminaBarWidth;
|
||||
|
||||
int m_staminaBorderWidth;
|
||||
int m_staminaBorderHeight;
|
||||
CStr m_staminaBorderName;
|
||||
|
||||
// HP properties
|
||||
float m_healthCurr;
|
||||
float m_healthMax;
|
||||
float m_healthBarHeight;
|
||||
int m_healthBarSize;
|
||||
float m_healthBarWidth;
|
||||
|
||||
int m_healthBorderWidth;
|
||||
int m_healthBorderHeight;
|
||||
CStr m_healthBorderName;
|
||||
|
||||
float m_healthRegenRate;
|
||||
float m_healthRegenStart;
|
||||
float m_healthDecayRate;
|
||||
|
||||
//Rank properties
|
||||
float m_rankHeight;
|
||||
int m_rankSize;
|
||||
float m_rankWidth;
|
||||
int m_rankHeight;
|
||||
CStr m_rankName;
|
||||
|
||||
// Minimap properties
|
||||
@ -100,6 +110,9 @@ public:
|
||||
SEntityAction m_run;
|
||||
SEntityAction m_generic;
|
||||
|
||||
int m_sectorDivs;
|
||||
float m_sectorPenalty;
|
||||
|
||||
float m_turningRadius;
|
||||
CScriptObject m_EventHandlers[EVENT_LAST];
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "BaseFormation.h"
|
||||
#include "CLogger.h"
|
||||
#include "CStr.h"
|
||||
#include "maths\MathUtil.h"
|
||||
|
||||
#define LOG_CATEGORY "Formation"
|
||||
|
||||
@ -30,6 +31,11 @@ bool CBaseFormation::loadXML(CStr filename)
|
||||
AT(penalty);
|
||||
AT(penaltytype);
|
||||
AT(penaltyval);
|
||||
AT(anglepenalty);
|
||||
AT(anglepenaltydivs);
|
||||
AT(anglepenaltytype);
|
||||
AT(anglepenaltyval);
|
||||
|
||||
AT(required);
|
||||
AT(next);
|
||||
AT(prior);
|
||||
@ -53,36 +59,46 @@ bool CBaseFormation::loadXML(CStr filename)
|
||||
for ( int i=0; i<Attributes.Count; ++i )
|
||||
{
|
||||
XMBAttribute Attr = Attributes.item(i);
|
||||
if ( Attr.Name == at_tag )
|
||||
if ( Attr.Name == at_tag )
|
||||
m_tag = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_bonus )
|
||||
else if ( Attr.Name == at_bonus )
|
||||
m_bonus = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_bonustype )
|
||||
else if ( Attr.Name == at_bonustype )
|
||||
m_bonusType = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_bonusval )
|
||||
else if ( Attr.Name == at_bonusval )
|
||||
m_bonusVal = CStr(Attr.Value).ToFloat();
|
||||
else if ( Attr.Name == at_penalty )
|
||||
else if ( Attr.Name == at_penalty )
|
||||
m_penalty = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_penaltytype )
|
||||
else if ( Attr.Name == at_penaltytype )
|
||||
m_penaltyType = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_penaltyval )
|
||||
else if ( Attr.Name == at_penaltyval )
|
||||
m_penaltyVal = CStr(Attr.Value).ToFloat();
|
||||
else if ( Attr.Name == at_required)
|
||||
|
||||
else if ( Attr.Name == at_anglepenalty )
|
||||
m_anglePenalty = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_anglepenaltydivs )
|
||||
m_anglePenaltyDivs = CStr(Attr.Value).ToInt();
|
||||
else if ( Attr.Name == at_anglepenaltytype )
|
||||
m_anglePenaltyType = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_anglepenaltyval )
|
||||
m_anglePenaltyVal = CStr(Attr.Value).ToFloat();
|
||||
|
||||
else if ( Attr.Name == at_required)
|
||||
m_required = CStr(Attr.Value).ToInt();
|
||||
else if ( Attr.Name == at_next )
|
||||
else if ( Attr.Name == at_next )
|
||||
m_next = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_prior )
|
||||
else if ( Attr.Name == at_prior )
|
||||
m_prior = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_movement )
|
||||
else if ( Attr.Name == at_movement )
|
||||
m_movement = CStr(Attr.Value);
|
||||
else if ( Attr.Name == at_rankspacing )
|
||||
else if ( Attr.Name == at_rankspacing )
|
||||
m_rankSpacing = CStr(Attr.Value).ToFloat();
|
||||
else if ( Attr.Name == at_filespacing )
|
||||
else if ( Attr.Name == at_filespacing )
|
||||
m_fileSpacing = CStr(Attr.Value).ToFloat();
|
||||
else
|
||||
{
|
||||
CStr invAttr = XeroFile.getAttributeString(Attr.Name);
|
||||
LOG( ERROR, LOG_CATEGORY, "CBaseFormation::LoadXML: Invalid attribute defined in formation file %s. Load failed.", filename.c_str() );
|
||||
const char* invAttr = XeroFile.getAttributeString(Attr.Name).c_str();
|
||||
LOG( ERROR, LOG_CATEGORY, "CBaseFormation::LoadXML: Invalid attribute %s defined in formation file %s. Load failed.", invAttr, filename.c_str() );
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,12 @@ public:
|
||||
CStr GetPenaltyType(){ return m_penaltyType; }
|
||||
float GetPenaltyVal(){ return m_penaltyVal; }
|
||||
|
||||
CStr GetAnglePenalty(){ return m_anglePenalty; }
|
||||
CStr GetAnglePenaltyType(){ return m_anglePenaltyType; }
|
||||
int GetAnglePenaltyDivs(){ return m_anglePenaltyDivs; }
|
||||
float GetAnglePenaltyVal(){ return m_anglePenaltyVal; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
CStr m_tag;
|
||||
@ -47,6 +53,11 @@ private:
|
||||
CStr m_penaltyType;
|
||||
float m_penaltyVal;
|
||||
|
||||
CStr m_anglePenalty;
|
||||
int m_anglePenaltyDivs;
|
||||
CStr m_anglePenaltyType;
|
||||
float m_anglePenaltyVal;
|
||||
|
||||
int m_required;
|
||||
CStr m_next;
|
||||
CStr m_prior;
|
||||
@ -60,6 +71,7 @@ private:
|
||||
|
||||
//The key is the "order" of the slot
|
||||
std::map<int, FormationSlot> m_slots;
|
||||
std::vector<float> m_angleValues; //cosine of angle divisions
|
||||
|
||||
bool loadXML(CStr filename);
|
||||
void AssignCategory(int order, CStr category); //takes care of formatting strings
|
||||
|
@ -61,14 +61,25 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
|
||||
AddProperty( L"traits.health.max", &m_healthMax );
|
||||
AddProperty( L"traits.health.bar_height", &m_healthBarHeight );
|
||||
AddProperty( L"traits.health.bar_size", &m_healthBarSize );
|
||||
AddProperty( L"traits.health.bar_width", &m_healthBarWidth );
|
||||
AddProperty( L"traits.health.border_height", &m_healthBorderHeight);
|
||||
AddProperty( L"traits.health.border_width", &m_healthBorderWidth );
|
||||
AddProperty( L"traits.health.border_name", &m_healthBorderName );
|
||||
AddProperty( L"traits.health.regen_rate", &m_healthRegenRate );
|
||||
AddProperty( L"traits.health.regen_start", &m_healthRegenStart );
|
||||
AddProperty( L"traits.health.decay_rate", &m_healthDecayRate );
|
||||
|
||||
AddProperty( L"traits.stamina.curr", &m_staminaCurr );
|
||||
AddProperty( L"traits.stamina.max", &m_staminaMax );
|
||||
AddProperty( L"traits.stamina.bar_height", &m_staminaBarHeight );
|
||||
AddProperty( L"traits.stamina.bar_size", &m_staminaBarSize );
|
||||
AddProperty( L"traits.rank.size", &m_rankSize );
|
||||
AddProperty( L"traits.stamina.bar_width", &m_staminaBarWidth );
|
||||
AddProperty( L"traits.stamina.border_height", &m_staminaBorderHeight);
|
||||
AddProperty( L"traits.stamina.border_width", &m_staminaBorderWidth );
|
||||
AddProperty( L"traits.stamina.border_name", &m_staminaBorderName );
|
||||
AddProperty( L"traits.angle_penalty.sectors", &m_sectorDivs);
|
||||
AddProperty( L"traits.angle_penalty.value", &m_sectorPenalty );
|
||||
AddProperty( L"traits.rank.width", &m_rankWidth );
|
||||
AddProperty( L"traits.rank.height", &m_rankHeight );
|
||||
AddProperty( L"traits.rank.name", &m_rankName );
|
||||
AddProperty( L"traits.minimap.type", &m_minimapType );
|
||||
@ -89,6 +100,18 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
|
||||
AddProperty( EventNames[t], &m_EventHandlers[t], false );
|
||||
AddHandler( t, &m_EventHandlers[t] );
|
||||
}
|
||||
if ( m_sectorDivs >= 0 )
|
||||
{
|
||||
m_sectorAngles.resize(m_sectorDivs);
|
||||
m_sectorValues.resize(m_sectorDivs);
|
||||
float step = DEGTORAD(360.0f / m_sectorDivs);
|
||||
|
||||
for ( int i=0; i<m_sectorDivs; ++i )
|
||||
{
|
||||
m_sectorAngles[i] = cosf( step*i );
|
||||
m_sectorValues[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_collisionPatch = NULL;
|
||||
|
||||
@ -127,7 +150,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
|
||||
m_frameCheck = 0;
|
||||
m_lastCombatTime = 0;
|
||||
m_currentNotification = 0;
|
||||
m_currentListener = NULL;
|
||||
m_currentRequest = 0;
|
||||
m_destroyNotifiers = true;
|
||||
|
||||
m_formationSlot = -1;
|
||||
m_formation = -1;
|
||||
@ -161,6 +185,10 @@ CEntity::~CEntity()
|
||||
}
|
||||
m_auras.clear();
|
||||
|
||||
for ( size_t i=0; i<m_listeners.size(); i++ )
|
||||
m_listeners[i].m_sender->DestroyNotifier( this );
|
||||
DestroyAllNotifiers();
|
||||
|
||||
CEntity* remove = this;
|
||||
g_FormationManager.RemoveUnit(remove);
|
||||
}
|
||||
@ -207,6 +235,8 @@ void CEntity::kill()
|
||||
|
||||
CEntity* remove = this;
|
||||
g_FormationManager.RemoveUnit(remove);
|
||||
|
||||
DestroyAllNotifiers();
|
||||
|
||||
if( m_bounds )
|
||||
delete( m_bounds );
|
||||
@ -662,9 +692,21 @@ void CEntity::Tick()
|
||||
|
||||
void CEntity::clearOrders()
|
||||
{
|
||||
m_orderQueue.clear();
|
||||
if ( m_orderQueue.empty() )
|
||||
return;
|
||||
CIdleEvent evt( m_orderQueue.front(), m_currentNotification );
|
||||
DispatchEvent(&evt);
|
||||
m_orderQueue.clear();
|
||||
}
|
||||
void CEntity::popOrder()
|
||||
{
|
||||
if ( m_orderQueue.empty() )
|
||||
return;
|
||||
CIdleEvent evt( m_orderQueue.front(), m_currentNotification );
|
||||
DispatchEvent(&evt);
|
||||
|
||||
m_orderQueue.pop_front();
|
||||
}
|
||||
void CEntity::pushOrder( CEntityOrder& order )
|
||||
{
|
||||
CEventPrepareOrder evt( order.m_data[0].entity, order.m_type, order.m_data[1].data, order.m_data[0].string );
|
||||
@ -683,17 +725,36 @@ void CEntity::DispatchNotification( CEntityOrder order, int type )
|
||||
CEventNotification evt( order, type );
|
||||
DispatchEvent( &evt );
|
||||
}
|
||||
void CEntity::DestroyListeners( CEntity* target )
|
||||
int CEntity::DestroyNotifier( CEntity* target )
|
||||
{
|
||||
if (target->m_listeners.empty())
|
||||
return;
|
||||
|
||||
for ( size_t i=0; i < target->m_listeners.size(); i++)
|
||||
if (target->m_listeners.empty() || !m_destroyNotifiers)
|
||||
return 0;
|
||||
//Stop listening
|
||||
for ( size_t i=0; i < target->m_listeners.size(); i++ )
|
||||
{
|
||||
if ( target->m_listeners[i].m_sender == this )
|
||||
target->m_listeners.erase(target->m_listeners.begin() + i);
|
||||
}
|
||||
|
||||
int removed=0;
|
||||
//Get rid of our copy
|
||||
for ( size_t i=0; i < target->m_notifiers.size(); i++ )
|
||||
{
|
||||
if ( m_notifiers[i] == target )
|
||||
{
|
||||
m_notifiers.erase(m_notifiers.begin() + i);
|
||||
++removed;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
void CEntity::DestroyAllNotifiers()
|
||||
{
|
||||
debug_assert(m_destroyNotifiers);
|
||||
//Make them stop listening to us
|
||||
if ( m_notifiers.empty() )
|
||||
return;
|
||||
for ( size_t i=0; i<m_notifiers.size(); i++ )
|
||||
i -= DestroyNotifier( m_notifiers[i] );
|
||||
}
|
||||
CEntityFormation* CEntity::GetFormation()
|
||||
{
|
||||
@ -1001,29 +1062,81 @@ void CEntity::renderSelectionOutline( float alpha )
|
||||
|
||||
glEnd();
|
||||
}
|
||||
CVector2D CEntity::getScreenCoords( float height )
|
||||
{
|
||||
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
|
||||
|
||||
float sx, sy;
|
||||
CVector3D above;
|
||||
above.X = m_position.X;
|
||||
above.Z = m_position.Z;
|
||||
above.Y = getAnchorLevel(m_position.X, m_position.Z) + height;
|
||||
g_Camera.GetScreenCoordinates(above, sx, sy);
|
||||
return CVector2D( sx, sy );
|
||||
}
|
||||
void CEntity::renderBarBorders()
|
||||
{
|
||||
pglActiveTextureARB( GL_TEXTURE0_ARB );
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
|
||||
|
||||
if ( g_Selection.m_unitUITextures.find(m_healthBorderName) != g_Selection.m_unitUITextures.end() )
|
||||
{
|
||||
ogl_tex_bind( g_Selection.m_unitUITextures[m_healthBorderName] );
|
||||
CVector2D pos = getScreenCoords( m_healthBarHeight );
|
||||
|
||||
float left = pos.x - m_healthBorderWidth/2;
|
||||
float right = pos.x + m_healthBorderWidth/2;
|
||||
pos.y = g_yres - pos.y;
|
||||
float bottom = pos.y + m_healthBorderHeight/2;
|
||||
float top = pos.y - m_healthBorderHeight/2;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( left, bottom, 0 );
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( left, top, 0 );
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( right, top, 0 );
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( right, bottom, 0 );
|
||||
|
||||
glEnd();
|
||||
}
|
||||
if ( g_Selection.m_unitUITextures.find(m_staminaBorderName) != g_Selection.m_unitUITextures.end() )
|
||||
{
|
||||
ogl_tex_bind( g_Selection.m_unitUITextures[m_staminaBorderName] );
|
||||
CVector2D pos = getScreenCoords( m_staminaBarHeight );
|
||||
float left = pos.x - m_staminaBorderWidth/2;
|
||||
float right = pos.x + m_staminaBorderWidth/2;
|
||||
pos.y = g_yres - pos.y;
|
||||
float bottom = pos.y + m_staminaBorderHeight/2;
|
||||
float top = pos.y - m_staminaBorderHeight/2;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( left, bottom, 0 );
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( left, top, 0 );
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( right, top, 0 );
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( right, bottom, 0 );
|
||||
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
void CEntity::renderHealthBar()
|
||||
{
|
||||
if( !m_bounds )
|
||||
return;
|
||||
if( m_healthBarHeight < 0 )
|
||||
return; // negative bar height means don't display health bar
|
||||
|
||||
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
|
||||
|
||||
float sx, sy;
|
||||
CVector3D above;
|
||||
above.X = m_position.X;
|
||||
above.Z = m_position.Z;
|
||||
above.Y = getAnchorLevel(m_position.X, m_position.Z) + m_healthBarHeight;
|
||||
g_Camera.GetScreenCoordinates(above, sx, sy);
|
||||
|
||||
CVector2D pos = getScreenCoords( m_healthBarHeight );
|
||||
float fraction = clamp(m_healthCurr / m_healthMax, 0.0f, 1.0f);
|
||||
|
||||
float x1 = sx - m_healthBarSize/2;
|
||||
float x2 = sx + m_healthBarSize/2;
|
||||
float y = g_yres - sy;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
float x1 = pos.x - m_healthBarSize/2;
|
||||
float x2 = pos.x + m_healthBarSize/2;
|
||||
float y = g_yres - pos.y;
|
||||
|
||||
glLineWidth( m_healthBarWidth );
|
||||
glBegin(GL_LINES);
|
||||
|
||||
// green part of bar
|
||||
glColor3f( 0, 1, 0 );
|
||||
@ -1038,6 +1151,9 @@ void CEntity::renderHealthBar()
|
||||
glVertex3f( x2, y, 0 );
|
||||
|
||||
glEnd();
|
||||
|
||||
glLineWidth(1.0f);
|
||||
|
||||
}
|
||||
|
||||
void CEntity::renderStaminaBar()
|
||||
@ -1047,20 +1163,13 @@ void CEntity::renderStaminaBar()
|
||||
if( m_staminaBarHeight < 0 )
|
||||
return; // negative bar height means don't display stamina bar
|
||||
|
||||
CCamera *g_Camera=g_Game->GetView()->GetCamera();
|
||||
|
||||
float sx, sy;
|
||||
CVector3D above;
|
||||
above.X = m_position.X;
|
||||
above.Z = m_position.Z;
|
||||
above.Y = getAnchorLevel(m_position.X, m_position.Z) + m_staminaBarHeight;
|
||||
g_Camera->GetScreenCoordinates(above, sx, sy);
|
||||
CVector2D pos = getScreenCoords( m_staminaBarHeight );
|
||||
float fraction = clamp(m_staminaCurr / m_staminaMax, 0.0f, 1.0f);
|
||||
|
||||
float x1 = sx - m_staminaBarSize/2;
|
||||
float x2 = sx + m_staminaBarSize/2;
|
||||
float y = g_yres - sy;
|
||||
|
||||
float x1 = pos.x - m_staminaBarSize/2;
|
||||
float x2 = pos.x + m_staminaBarSize/2;
|
||||
float y = g_yres - pos.y;
|
||||
|
||||
glLineWidth( m_staminaBarWidth );
|
||||
glBegin(GL_LINES);
|
||||
|
||||
// blue part of bar
|
||||
@ -1076,17 +1185,18 @@ void CEntity::renderStaminaBar()
|
||||
glVertex3f( x2, y, 0 );
|
||||
|
||||
glEnd();
|
||||
glLineWidth(1.0f);
|
||||
}
|
||||
void CEntity::renderRank()
|
||||
{
|
||||
if( !m_bounds )
|
||||
return;
|
||||
if( m_rankHeight < 0 )
|
||||
return; // negative bar height means don't display stamina bar
|
||||
return; // negative height means don't display stamina bar
|
||||
//Check for valid texture
|
||||
if( g_Selection.m_rankTextures.find( m_rankName ) == g_Selection.m_rankTextures.end() )
|
||||
if( g_Selection.m_unitUITextures.find( m_rankName ) == g_Selection.m_unitUITextures.end() )
|
||||
return;
|
||||
|
||||
|
||||
CCamera *g_Camera=g_Game->GetView()->GetCamera();
|
||||
|
||||
float sx, sy;
|
||||
@ -1095,14 +1205,14 @@ void CEntity::renderRank()
|
||||
above.Z = m_position.Z;
|
||||
above.Y = getAnchorLevel(m_position.X, m_position.Z) + m_rankHeight;
|
||||
g_Camera->GetScreenCoordinates(above, sx, sy);
|
||||
int size = m_rankSize/2;
|
||||
int size = m_rankWidth/2;
|
||||
|
||||
float x1 = sx - size;
|
||||
float x2 = sx + size;
|
||||
float y1 = g_yres - (sy - size); //top
|
||||
float y2 = g_yres - (sy + size); //bottom
|
||||
|
||||
ogl_tex_bind(g_Selection.m_rankTextures[m_rankName]);
|
||||
|
||||
ogl_tex_bind(g_Selection.m_unitUITextures[m_rankName]);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
|
||||
@ -1167,7 +1277,9 @@ void CEntity::ScriptingInit()
|
||||
AddMethod<jsval, &CEntity::RemoveAura>( "removeAura", 1 );
|
||||
AddMethod<jsval, &CEntity::SetActionParams>( "setActionParams", 5 );
|
||||
AddMethod<bool, &CEntity::ForceCheckListeners>( "forceCheckListeners", 2 );
|
||||
AddMethod<bool, &CEntity::RequestNotification>( "requestNotification", 3 );
|
||||
AddMethod<bool, &CEntity::RequestNotification>( "requestNotification", 4 );
|
||||
AddMethod<jsval, &CEntity::DestroyNotifier>( "destroyNotifier", 1 );
|
||||
AddMethod<jsval, &CEntity::DestroyAllNotifiers>( "destroyAllNotifiers", 0 );
|
||||
AddMethod<jsval, &CEntity::TriggerRun>( "triggerRun", 1 );
|
||||
AddMethod<jsval, &CEntity::SetRun>( "setRun", 1 );
|
||||
AddMethod<jsval, &CEntity::GetRunState>( "getRunState", 0 );
|
||||
@ -1178,7 +1290,8 @@ void CEntity::ScriptingInit()
|
||||
AddMethod<jsval, &CEntity::GetFormationPenalty>( "getFormationPenalty", 0 );
|
||||
AddMethod<jsval, &CEntity::GetFormationPenaltyType>( "getFormationPenaltyType", 0 );
|
||||
AddMethod<jsval, &CEntity::GetFormationPenaltyVal>( "getFormationPenaltyVal", 0 );
|
||||
AddMethod<bool, &CEntity::IsInClass>( "isInClass", 1 );
|
||||
AddMethod<jsval, &CEntity::RegisterDamage>( "registerDamage", 0 );
|
||||
AddMethod<jsval, &CEntity::RegisterIdle>( "registerIdle", 0 );
|
||||
|
||||
AddClassProperty( L"template", (CBaseEntity* CEntity::*)&CEntity::m_base, false, (NotifyFn)&CEntity::loadBase );
|
||||
AddClassProperty( L"traits.id.classes", (GetFn)&CEntity::getClassSet, (SetFn)&CEntity::setClassSet );
|
||||
@ -1311,11 +1424,12 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued )
|
||||
//It's not a notification order
|
||||
if ( argc == 3 )
|
||||
{
|
||||
if ( m_currentListener )
|
||||
DestroyListeners( m_currentListener );
|
||||
m_currentListener = NULL;
|
||||
if ( m_destroyNotifiers )
|
||||
{
|
||||
m_currentRequest=0;
|
||||
DestroyAllNotifiers();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case CEntityOrder::ORDER_GENERIC:
|
||||
if( argc < 3 )
|
||||
@ -1342,9 +1456,11 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued )
|
||||
//It's not a notification order
|
||||
if ( argc == 3 )
|
||||
{
|
||||
if ( m_currentListener )
|
||||
DestroyListeners( m_currentListener );
|
||||
m_currentListener = NULL;
|
||||
if ( m_destroyNotifiers )
|
||||
{
|
||||
m_currentRequest=0;
|
||||
DestroyAllNotifiers();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CEntityOrder::ORDER_PRODUCE:
|
||||
@ -1627,32 +1743,35 @@ jsval CEntity::SetActionParams( JSContext* UNUSED(cx), uintN argc, jsval* argv )
|
||||
|
||||
bool CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
if( argc < 3 )
|
||||
if( argc < 4 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
return( false );
|
||||
}
|
||||
|
||||
CEntityListener notify;
|
||||
notify.m_sender = this;
|
||||
//(Convert from int to enum)
|
||||
CEntity *target = ToNative<CEntity>( argv[0] );
|
||||
(int&)notify.m_type = ToPrimitive<int>( argv[1] );
|
||||
bool tmpDestroyNotifiers = ToPrimitive<bool>( argv[2] );
|
||||
bool m_destroyNotifiers = !ToPrimitive<bool>( argv[3] );
|
||||
|
||||
if (target == this)
|
||||
return false;
|
||||
|
||||
*( (int*) &(notify.m_type) ) = ToPrimitive<int>( argv[1] );
|
||||
|
||||
notify.m_sender = this;
|
||||
|
||||
//Clean up old requests
|
||||
if ( ToPrimitive<bool>( argv[2] ) && !target->m_listeners.empty() )
|
||||
DestroyListeners( target );
|
||||
|
||||
if ( target != m_currentListener && m_currentListener )
|
||||
DestroyListeners( m_currentListener );
|
||||
if ( tmpDestroyNotifiers )
|
||||
DestroyAllNotifiers();
|
||||
//If new request is not the same and we're destroy notifiers, reset
|
||||
else if ( !(notify.m_type & m_currentRequest) && m_destroyNotifiers )
|
||||
DestroyAllNotifiers();
|
||||
|
||||
m_currentListener = target;
|
||||
m_currentRequest = notify.m_type;
|
||||
m_notifiers.push_back( target );
|
||||
int result = target->m_currentNotification & notify.m_type;
|
||||
|
||||
//If our target isn't stationary and it's doing something we want to follow, send notification
|
||||
int result = target->m_currentNotification & notify.m_type;
|
||||
if ( result && !target->m_orderQueue.empty() )
|
||||
{
|
||||
CEntityOrder order = target->m_orderQueue.front();
|
||||
@ -1667,11 +1786,6 @@ bool CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv )
|
||||
case CEntityListener::NOTIFY_ATTACK:
|
||||
case CEntityListener::NOTIFY_GATHER:
|
||||
case CEntityListener::NOTIFY_DAMAGE:
|
||||
if( argc < 2 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
}
|
||||
|
||||
DispatchNotification( order, result );
|
||||
break;
|
||||
default:
|
||||
@ -1713,11 +1827,13 @@ bool CEntity::ForceCheckListeners( JSContext *cx, uintN argc, jsval* argv )
|
||||
case CEntityListener::NOTIFY_ATTACK:
|
||||
case CEntityListener::NOTIFY_GATHER:
|
||||
case CEntityListener::NOTIFY_DAMAGE:
|
||||
case CEntityListener::NOTIFY_IDLE: //target should be 'this'
|
||||
m_listeners[i].m_sender->DispatchNotification( order, result );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
JS_ReportError( cx, "Invalid order type" );
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1754,6 +1870,21 @@ void CEntity::CheckListeners( int type, CEntity *target)
|
||||
}
|
||||
}
|
||||
}
|
||||
jsval CEntity::DestroyAllNotifiers( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
|
||||
{
|
||||
DestroyAllNotifiers();
|
||||
return JS_TRUE;
|
||||
}
|
||||
jsval CEntity::DestroyNotifier( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
if ( argc < 1 )
|
||||
{
|
||||
JS_ReportError(cx, "too few parameters: CEntity::DestroyNotifier");
|
||||
return JS_FALSE;
|
||||
}
|
||||
DestroyNotifier( ToNative<CEntity>( argv[0] ) );
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsval CEntity::TriggerRun( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
|
||||
{
|
||||
@ -1800,13 +1931,64 @@ jsval CEntity::GetFormationBonusVal( JSContext* UNUSED(cx), uintN UNUSED(argc),
|
||||
{
|
||||
return ToJSVal( GetFormation()->GetBase()->GetBonusVal() );
|
||||
}
|
||||
bool CEntity::IsInClass( JSContext* cx, uintN argc, jsval* argv )
|
||||
|
||||
jsval CEntity::RegisterDamage( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
if( argc < 1 )
|
||||
if ( argc < 1 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
return( false );
|
||||
}
|
||||
CStr test = ToPrimitive<CStr>( argv[0] );
|
||||
return m_classes.IsMember( test );
|
||||
}
|
||||
CEntity* inflictor = ToNative<CEntity>( argv[0] );
|
||||
CVector2D up(1.0f, 0.0f);
|
||||
CVector2D pos = CVector2D( inflictor->m_position.X, inflictor->m_position.Z );
|
||||
CVector2D posDelta = (pos - m_position).normalize();
|
||||
|
||||
float angle = up.dot(posDelta);
|
||||
//Find what section it is between and "activate" it
|
||||
for ( int i=0; i<m_sectorDivs; ++i )
|
||||
{
|
||||
//Wrap around to the start-if we've made it this far, it's here
|
||||
if ( i == m_base->m_sectorDivs )
|
||||
m_sectorValues[i] = true;
|
||||
else if ( angle > m_sectorAngles[i] && angle < m_sectorAngles[i+1] )
|
||||
m_sectorValues[i] = true;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
jsval CEntity::RegisterIdle( JSContext* cx, uintN argc, jsval* argv )
|
||||
{
|
||||
if ( argc < 1 )
|
||||
{
|
||||
JS_ReportError( cx, "Too few parameters" );
|
||||
return( false );
|
||||
}
|
||||
CEntity* idleEntity = ToNative<CEntity>( argv[0] );
|
||||
|
||||
CVector2D up(1.0f, 0.0f);
|
||||
CVector2D pos = CVector2D( idleEntity->m_position.X, idleEntity->m_position.Z );
|
||||
CVector2D posDelta = (pos - m_position).normalize();
|
||||
|
||||
float angle = up.dot(posDelta);
|
||||
//Find what section it is between and "activate" it
|
||||
for ( int i=0; i<m_sectorDivs; ++i )
|
||||
{
|
||||
//Wrap around to the start-if we've made it this far, it's here
|
||||
if ( i == m_base->m_sectorDivs )
|
||||
m_sectorValues[i] = false;
|
||||
else if ( angle > m_sectorAngles[i] && angle < m_sectorAngles[i+1] )
|
||||
m_sectorValues[i] = false;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
jsval CEntity::GetAttackDirections( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
|
||||
{
|
||||
int directions=0;
|
||||
|
||||
for ( std::vector<bool>::iterator it=m_sectorValues.begin(); it != m_sectorValues.end(); it++ )
|
||||
{
|
||||
if ( *it )
|
||||
++directions;
|
||||
}
|
||||
return ToJSVal( directions );
|
||||
}
|
||||
|
@ -114,16 +114,26 @@ public:
|
||||
float m_staminaMax;
|
||||
float m_staminaBarHeight;
|
||||
int m_staminaBarSize;
|
||||
float m_staminaBarWidth;
|
||||
|
||||
int m_staminaBorderWidth;
|
||||
int m_staminaBorderHeight;
|
||||
CStr m_staminaBorderName;
|
||||
|
||||
// HP properties
|
||||
float m_healthCurr;
|
||||
float m_healthMax;
|
||||
float m_healthBarHeight;
|
||||
int m_healthBarSize;
|
||||
float m_healthBarWidth;
|
||||
|
||||
int m_healthBorderWidth;
|
||||
int m_healthBorderHeight;
|
||||
CStr m_healthBorderName;
|
||||
|
||||
//Rank properties
|
||||
float m_rankHeight;
|
||||
int m_rankSize;
|
||||
int m_rankWidth;
|
||||
CStr m_rankName;
|
||||
|
||||
bool m_healthDecay;
|
||||
@ -189,8 +199,16 @@ public:
|
||||
|
||||
std::deque<CEntityOrder> m_orderQueue;
|
||||
std::deque<CEntityListener> m_listeners;
|
||||
int m_currentNotification;
|
||||
CEntity* m_currentListener;
|
||||
|
||||
std::vector<CEntity*> m_notifiers;
|
||||
int m_currentNotification; //Current order in the form of a notification code
|
||||
int m_currentRequest; //Notification we our notifiers are sending
|
||||
bool m_destroyNotifiers; //True: we destroy them. False: the script does.
|
||||
|
||||
std::vector<bool> m_sectorValues;
|
||||
std::vector<float> m_sectorAngles;
|
||||
int m_sectorDivs;
|
||||
float m_sectorPenalty;
|
||||
|
||||
private:
|
||||
CEntity( CBaseEntity* base, CVector3D position, float orientation, const std::set<CStrW>& actorSelections, CStrW building = L"" );
|
||||
@ -261,10 +279,11 @@ public:
|
||||
// Things like selection circles and debug info - possibly move to gui if/when it becomes responsible for (and capable of) it.
|
||||
void render();
|
||||
void renderSelectionOutline( float alpha = 1.0f );
|
||||
void renderBarBorders( );
|
||||
void renderHealthBar();
|
||||
void renderStaminaBar();
|
||||
void renderRank();
|
||||
|
||||
CVector2D getScreenCoords( float height );
|
||||
// After a collision, recalc the path to the next fixed waypoint.
|
||||
void repath();
|
||||
|
||||
@ -283,10 +302,12 @@ public:
|
||||
void checkExtant(); // Existence
|
||||
|
||||
void clearOrders();
|
||||
void popOrder(); //Use this if and order has finished instead of m_orderQueue.pop_front()
|
||||
void pushOrder( CEntityOrder& order );
|
||||
|
||||
void DispatchNotification( CEntityOrder order, int type );
|
||||
void DestroyListeners( CEntity* target );
|
||||
int DestroyNotifier( CEntity* target ); //Stop notifier from sending to us
|
||||
void DestroyAllNotifiers();
|
||||
|
||||
CEntityFormation* GetFormation();
|
||||
bool IsInClass( JSContext* cx, uintN argc, jsval* argv );
|
||||
@ -297,7 +318,12 @@ public:
|
||||
jsval GetFormationBonus( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval GetFormationBonusType( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval GetFormationBonusVal( JSContext* cx, uintN argc, jsval* argv );
|
||||
|
||||
void DispatchFormationEvent( int type );
|
||||
|
||||
jsval RegisterDamage( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval RegisterIdle( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval GetAttackDirections( JSContext* cx, uintN argc, jsval* argv );
|
||||
// Script constructor
|
||||
|
||||
static JSBool Construct( JSContext* cx, JSObject* obj, uint argc, jsval* argv, jsval* rval );
|
||||
@ -322,6 +348,8 @@ public:
|
||||
//Just in case we want to explicitly check the listeners without waiting for the order to be pushed
|
||||
bool ForceCheckListeners( JSContext* cx, uintN argc, jsval* argv );
|
||||
void CheckListeners( int type, CEntity *target );
|
||||
jsval DestroyAllNotifiers( JSContext* cx, uintN argc, jsval* argv );
|
||||
jsval DestroyNotifier( JSContext* cx, uintN argc, jsval* argv );
|
||||
|
||||
bool IsInFormation( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
|
||||
{
|
||||
|
@ -91,19 +91,21 @@ void CEntityFormation::RemoveUnit( CEntity*& entity )
|
||||
--m_numEntities;
|
||||
//UpdateFormation();
|
||||
}
|
||||
bool CEntityFormation::IsSlotAppropriate( int order, CEntity*& entity )
|
||||
bool CEntityFormation::IsSlotAppropriate( int order, CEntity* entity )
|
||||
{
|
||||
debug_assert( entity );
|
||||
if ( !IsValidOrder(order) )
|
||||
return false;
|
||||
|
||||
for ( size_t idx=0; idx < m_base->m_slots[order].category.size(); ++idx )
|
||||
{
|
||||
if ( entity->m_classes.IsMember( m_base->m_slots[order].category[idx] ) )
|
||||
CStr tmp( m_base->m_slots[order].category[idx] );
|
||||
if ( entity->m_classes.IsMember( tmp ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CEntityFormation::IsBetterUnit( int order, CEntity*& entity )
|
||||
bool CEntityFormation::IsBetterUnit( int order, CEntity* entity )
|
||||
{
|
||||
if ( !( IsValidOrder(order) || entity ) )
|
||||
return false;
|
||||
@ -163,6 +165,11 @@ void CEntityFormation::ResetAllEntities()
|
||||
for ( int i=0; i<m_base->m_numSlots; ++i )
|
||||
m_entities[i] = NULL;
|
||||
}
|
||||
void CEntityFormation::ResetAngleDivs()
|
||||
{
|
||||
for ( int i=0; i<m_base->m_anglePenaltyDivs; ++i )
|
||||
m_angleDivs[i] = false;
|
||||
}
|
||||
void CEntityFormation::SelectAllUnits()
|
||||
{
|
||||
for ( int i=0; i<m_base->m_numSlots; ++i )
|
||||
|
@ -36,8 +36,6 @@ public:
|
||||
|
||||
inline void SetDuplication( bool duplicate ) { m_duplication=duplicate; }
|
||||
inline bool IsDuplication() { return m_duplication; }
|
||||
//inline void SetDuplication( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) );
|
||||
//inline bool IsDuplication( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) );
|
||||
inline void SetLock( bool lock ){ m_locked=lock; }
|
||||
inline bool IsLocked() { return m_locked; }
|
||||
inline bool IsValidOrder(int order) { return ( order >= 0 && order < m_base->m_numSlots ); }
|
||||
@ -55,19 +53,21 @@ private:
|
||||
|
||||
CBaseFormation* m_base;
|
||||
CBaseFormation* m_self; //Keeps track of base (referred to during movement switching)
|
||||
std::vector<CEntity*> m_entities; //number of units currently in this formation
|
||||
|
||||
|
||||
std::vector<CEntity*> m_entities; //number of units currently in this formation
|
||||
std::vector<bool> m_angleDivs; //attack direction penalty-true=being attacked from sector
|
||||
std::vector<float> m_angleVals;
|
||||
|
||||
bool AddUnit( CEntity*& entity );
|
||||
void RemoveUnit( CEntity*& entity );
|
||||
bool IsSlotAppropriate( int order, CEntity*& entity ); //If empty, can we use this slot?
|
||||
bool IsBetterUnit( int order, CEntity*& entity );
|
||||
bool IsSlotAppropriate( int order, CEntity* entity ); //If empty, can we use this slot?
|
||||
bool IsBetterUnit( int order, CEntity* entity );
|
||||
|
||||
void UpdateFormation();
|
||||
void SwitchBase( CBaseFormation*& base );
|
||||
//void UpdateGridOffset();
|
||||
|
||||
void ResetIndex( size_t index );
|
||||
void ResetAllEntities(); //Sets all handles to invalid
|
||||
void ResetAngleDivs();
|
||||
};
|
||||
#endif
|
@ -66,7 +66,10 @@ public:
|
||||
|
||||
NOTIFY_ESCORT = 0x0F, //GOTO | ATTACK | DAMAGE
|
||||
NOTIFY_HEAL = 0x10,
|
||||
NOTIFY_GATHER = 0x20
|
||||
NOTIFY_GATHER = 0x20,
|
||||
|
||||
NOTIFY_IDLE = 0x40,
|
||||
NOTIFY_ALL = 0x7F
|
||||
|
||||
} m_type;
|
||||
|
||||
|
@ -379,7 +379,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
if(!DispatchEvent( contactEvent ))
|
||||
{
|
||||
// Cancel current order
|
||||
m_orderQueue.pop_front();
|
||||
popOrder();
|
||||
m_isRunning = false;
|
||||
m_shouldRun = false;
|
||||
m_actor->SetEntitySelection( L"idle" );
|
||||
@ -406,7 +406,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
//TODO: eventually when stances/formations are implemented, if applicable (e.g. not
|
||||
//heal or if defensive stance), the unit should expand and continue the order.
|
||||
|
||||
m_orderQueue.pop_front();
|
||||
popOrder();
|
||||
m_isRunning = false;
|
||||
m_shouldRun = false;
|
||||
return( false );
|
||||
|
@ -97,8 +97,21 @@ CEventNotification::CEventNotification( CEntityOrder order, int notifyType ) : C
|
||||
AddLocalProperty( L"target", &m_target );
|
||||
AddLocalProperty( L"location", &m_location );
|
||||
}
|
||||
CFormationEvent::CFormationEvent( int type ) : CScriptEvent( L"formationEvent", EVENT_FORMATION, true )
|
||||
CFormationEvent::CFormationEvent( int type ) : CScriptEvent( L"formationEvent", EVENT_FORMATION, true )
|
||||
{
|
||||
(int&) m_formationEvent = type;
|
||||
AddLocalProperty( L"formationEvent", &m_formationEvent );
|
||||
}
|
||||
CIdleEvent::CIdleEvent( CEntityOrder order, int notifyType ) : CScriptEvent( L"idleEvent", EVENT_IDLE, false )
|
||||
{
|
||||
m_notifyType = notifyType;
|
||||
m_orderType = order.m_type;
|
||||
m_target = order.m_data[0].entity;
|
||||
CVector3D convert( order.m_data[0].location.x, 0.0f, order.m_data[0].location.y );
|
||||
m_location = convert;
|
||||
|
||||
AddLocalProperty( L"notifyType", &m_notifyType );
|
||||
AddLocalProperty( L"orderType", &m_orderType );
|
||||
AddLocalProperty( L"target", &m_target );
|
||||
AddLocalProperty( L"location", &m_location );
|
||||
}
|
@ -116,8 +116,21 @@ public:
|
||||
{
|
||||
FORMATION_ENTER,
|
||||
FORMATION_LEAVE,
|
||||
FORMATION_DAMAGE,
|
||||
FORMATION_ATTACK,
|
||||
|
||||
FORMATION_LAST
|
||||
};
|
||||
};
|
||||
class CIdleEvent : public CScriptEvent
|
||||
{
|
||||
int m_notifyType; //previous order in notification code form
|
||||
int m_orderType;
|
||||
int m_action; //previous order in terms of generic order action
|
||||
CVector3D m_location;
|
||||
CEntity* m_target;
|
||||
public:
|
||||
CIdleEvent( CEntityOrder order, int notifyType );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -13,7 +13,7 @@ CFormationManager::~CFormationManager()
|
||||
for ( size_t i=0; i<m_formations.size(); i++ )
|
||||
delete m_formations[i];
|
||||
}
|
||||
void CFormationManager::CreateFormation( CStrW& name, CEntityList& entities )
|
||||
void CFormationManager::CreateFormation( CEntityList& entities, CStrW& name )
|
||||
{
|
||||
if ( entities.empty() )
|
||||
{
|
||||
@ -120,6 +120,16 @@ bool CFormationManager::RemoveUnit( CEntity*& entity )
|
||||
(*it)->RemoveUnit( entity );
|
||||
return true;
|
||||
}
|
||||
bool CFormationManager::RemoveUnitList( CEntityList& entities )
|
||||
{
|
||||
for ( CEntityList::iterator it=entities.begin(); it != entities.end(); it++ )
|
||||
{
|
||||
CEntity* entity = *it;
|
||||
if ( !RemoveUnit(entity) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
CEntityFormation* CFormationManager::GetFormation(int form)
|
||||
{
|
||||
if ( IsValidFormation(form) )
|
||||
|
@ -23,7 +23,7 @@ class CFormationManager : public Singleton<CFormationManager>
|
||||
public:
|
||||
CFormationManager() {}
|
||||
~CFormationManager();
|
||||
void CreateFormation( CStrW& name, CEntityList& entities );
|
||||
void CreateFormation( CEntityList& entities, CStrW& name );
|
||||
//entity is any unit in the formation
|
||||
void DestroyFormation( size_t form );
|
||||
inline bool IsValidFormation( int index )
|
||||
@ -35,6 +35,7 @@ public:
|
||||
|
||||
//Returns false if the formation is destroyed
|
||||
bool RemoveUnit( CEntity*& entity );
|
||||
bool RemoveUnitList( CEntityList& entities );
|
||||
CEntityFormation* GetFormation(int form);
|
||||
void UpdateIndexes( size_t update );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user