384 lines
8.7 KiB
C++
384 lines
8.7 KiB
C++
// Copyright (C) 2007 Id Software, Inc.
|
|
//
|
|
|
|
#include "../precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "RoleManager.h"
|
|
#include "../structures/TeamManager.h"
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
sdRequirementCondition
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::sdRequirementCondition
|
|
================
|
|
*/
|
|
sdRequirementCondition::sdRequirementCondition( const char* requirement ) {
|
|
idLexer parser( requirement, idStr::Length( requirement ), "sdRequirementCondition::sdRequirementCondition" );
|
|
valueRegister = ParseExpression( &parser );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ExpressionOp
|
|
================
|
|
*/
|
|
sdRequirementCondition::rexpOp_t& sdRequirementCondition::ExpressionOp( void ) {
|
|
rexpOp_t& wop = ops.Alloc();
|
|
memset( &wop, 0, sizeof( wop ) );
|
|
return wop;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ExpressionTemporary
|
|
================
|
|
*/
|
|
int sdRequirementCondition::ExpressionTemporary( void ) {
|
|
int i = registers.Num();
|
|
expressionRegister_t& r = registers.Alloc();
|
|
r.temporary = true;
|
|
r.value = false;
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::EmitOp
|
|
================
|
|
*/
|
|
int sdRequirementCondition::EmitOp( int a, int b, rexpOpType_t opType, rexpOp_t** opp ) {
|
|
rexpOp_t& op = ExpressionOp();
|
|
op.opType = opType;
|
|
op.a = a;
|
|
op.b = b;
|
|
op.c = ExpressionTemporary();
|
|
|
|
if ( opp ) {
|
|
*opp = &op;
|
|
}
|
|
return op.c;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ParseEmitOp
|
|
================
|
|
*/
|
|
int sdRequirementCondition::ParseEmitOp( idLexer *src, int a, rexpOpType_t opType, int priority, rexpOp_t** opp ) {
|
|
int b = ParseExpressionPriority( src, priority );
|
|
return EmitOp( a, b, opType, opp );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ParseExpression
|
|
================
|
|
*/
|
|
int sdRequirementCondition::ParseExpression( idLexer *src ) {
|
|
const int TOP_PRIORITY = 2;
|
|
return ParseExpressionPriority( src, TOP_PRIORITY );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ExpressionConstant
|
|
================
|
|
*/
|
|
int sdRequirementCondition::ExpressionConstant( bool v ) {
|
|
int i;
|
|
|
|
for ( i = 0; i < registers.Num(); i++ ) {
|
|
if ( !registers[ i ].temporary && registers[ i ].value == v ) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
i = registers.Num();
|
|
expressionRegister_t& r = registers.Alloc();
|
|
r.temporary = false;
|
|
r.value = v;
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ParseTerm
|
|
=================
|
|
*/
|
|
int sdRequirementCondition::ParseTerm( idLexer *src ) {
|
|
idToken token;
|
|
int a;
|
|
|
|
src->ReadToken( &token );
|
|
|
|
if ( token == "(" ) {
|
|
a = ParseExpression( src );
|
|
src->ExpectTokenString( ")" );
|
|
return a;
|
|
}
|
|
|
|
if ( !token.Icmp( "true" ) ) {
|
|
return ExpressionConstant( true );
|
|
}
|
|
|
|
if ( !token.Icmp( "false" ) ) {
|
|
return ExpressionConstant( false );
|
|
}
|
|
|
|
const sdDeclRequirement* requirement = gameLocal.declRequirementType[ token ];
|
|
if ( requirement ) {
|
|
return ExpressionRequirement( requirement );
|
|
}
|
|
|
|
src->Error( "sdRequirementCondition::ParseTerm Invalid Term '%s'", token.c_str() );
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::ExpressionRequirement
|
|
================
|
|
*/
|
|
int sdRequirementCondition::ExpressionRequirement( const sdDeclRequirement* requirement ) {
|
|
int i = ExpressionTemporary();
|
|
expressionRequirement_t& er = requirements.Alloc();
|
|
er.requirement = requirement;
|
|
er.index = i;
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
sdRequirementCondition::ParseExpressionPriority
|
|
=================
|
|
*/
|
|
int sdRequirementCondition::ParseExpressionPriority( idLexer *src, int priority ) {
|
|
idToken token;
|
|
int a = -1;
|
|
|
|
if ( priority == 0 ) {
|
|
return ParseTerm( src );
|
|
}
|
|
|
|
a = ParseExpressionPriority( src, priority - 1 );
|
|
|
|
if ( !src->ReadToken( &token ) ) {
|
|
return a;
|
|
}
|
|
|
|
switch( priority ) {
|
|
case 1: {
|
|
if ( token == "==" ) {
|
|
return ParseEmitOp( src, a, ROP_TYPE_EQ, priority );
|
|
}
|
|
if ( token == "!=" ) {
|
|
return ParseEmitOp( src, a, ROP_TYPE_NE, priority );
|
|
}
|
|
src->UnreadToken( &token );
|
|
return a;
|
|
}
|
|
case 2: {
|
|
if ( token == "&&" ) {
|
|
return ParseEmitOp( src, a, ROP_TYPE_AND, priority );
|
|
}
|
|
if ( token == "||" ) {
|
|
return ParseEmitOp( src, a, ROP_TYPE_OR, priority );
|
|
}
|
|
src->UnreadToken( &token );
|
|
return a; // FIXME: this is not correct, but I cba fixing this parser atm
|
|
}
|
|
}
|
|
|
|
// assume that anything else terminates the expression
|
|
// not too robust error checking...
|
|
|
|
src->Error( "sdRequirementCondition::ParseExpressionPriority Unknown Token '%s'", token.c_str() );
|
|
|
|
return a;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementCondition::Evaluate
|
|
================
|
|
*/
|
|
bool sdRequirementCondition::Evaluate( idEntity* main, idEntity* other ) {
|
|
|
|
int i;
|
|
for ( i = 0; i < requirements.Num(); i++ ) {
|
|
registers[ requirements[ i ].index ].value = requirements[ i ].requirement->Check( main, other );
|
|
}
|
|
|
|
for ( i = 0 ; i < ops.Num() ; i++ ) {
|
|
rexpOp_t& op = ops[ i ];
|
|
|
|
switch( op.opType ) {
|
|
case ROP_TYPE_EQ:
|
|
registers[ op.c ].value = registers[ op.a ].value == registers[ op.b ].value;
|
|
break;
|
|
case ROP_TYPE_NE:
|
|
registers[ op.c ].value = registers[ op.a ].value != registers[ op.b ].value;
|
|
break;
|
|
case ROP_TYPE_AND:
|
|
registers[ op.c ].value = registers[ op.a ].value && registers[ op.b ].value;
|
|
break;
|
|
case ROP_TYPE_OR:
|
|
registers[ op.c ].value = registers[ op.a ].value || registers[ op.b ].value;
|
|
break;
|
|
default:
|
|
gameLocal.Error( "sdFloatParmExpression::EvaluateRegisters: bad opcode" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return registers[ valueRegister ].value;
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
sdRequirementContainer
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
sdRequirementContainer::Load
|
|
================
|
|
*/
|
|
void sdRequirementContainer::Load( const idDict& requirementList, const char* mode ) {
|
|
const idKeyValue* kv = NULL;
|
|
while( kv = requirementList.MatchPrefix( mode, kv ) ) {
|
|
if( kv->GetValue().Length() <= 0 ) {
|
|
continue;
|
|
}
|
|
Load( kv->GetValue().c_str() );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementContainer::Load
|
|
================
|
|
*/
|
|
void sdRequirementContainer::Load( const char* requirement ) {
|
|
if ( !*requirement ) {
|
|
return;
|
|
}
|
|
Alloc() = new sdRequirementCondition( requirement );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementContainer::~sdRequirementContainer
|
|
================
|
|
*/
|
|
sdRequirementContainer::~sdRequirementContainer( void ) {
|
|
DeleteContents( true );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementContainer::Check
|
|
================
|
|
*/
|
|
bool sdRequirementContainer::Check( idEntity* main, idEntity* other ) const {
|
|
|
|
int i;
|
|
for( i = 0; i < Num(); i++ ) {
|
|
if( !( *this )[ i ]->Evaluate( main, other ) ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// All requirement checks passed, let 'em have it
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
sdAbilityProvider
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
sdAbilityProvider::Add
|
|
================
|
|
*/
|
|
void sdAbilityProvider::Add( const char* abilityName ) {
|
|
Alloc() = sdRequirementManager::GetInstance().RegisterAbility( abilityName );
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
sdRequirementManagerLocal
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
sdRequirementManagerLocal::sdRequirementManagerLocal
|
|
================
|
|
*/
|
|
sdRequirementManagerLocal::sdRequirementManagerLocal( void ) {
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementManagerLocal::~sdRequirementManagerLocal
|
|
================
|
|
*/
|
|
sdRequirementManagerLocal::~sdRequirementManagerLocal( void ) {
|
|
Shutdown();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementManagerLocal::Init
|
|
================
|
|
*/
|
|
void sdRequirementManagerLocal::Init( void ) {
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementManagerLocal::Shutdown
|
|
================
|
|
*/
|
|
void sdRequirementManagerLocal::Shutdown( void ) {
|
|
registeredAbilities.Clear();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdRequirementManagerLocal::RegisterRequirement
|
|
================
|
|
*/
|
|
qhandle_t sdRequirementManagerLocal::RegisterAbility( const char* name ) {
|
|
qhandle_t* handle = NULL;
|
|
if ( registeredAbilities.Get( name, &handle ) ) {
|
|
return *handle;
|
|
}
|
|
|
|
return registeredAbilities.Set( name, ( qhandle_t )registeredAbilities.Num() );
|
|
}
|