//----------------------------------------------------------------------------- // // $Logfile:: /Code/DLLs/game/characterstate.h $ // $Revision:: 15 $ // $Date:: 10/13/03 8:53a $ // // Copyright (C) 1999 by Ritual Entertainment, Inc. // All rights reserved. // // This source is may not be distributed and/or modified without // expressly written permission by Ritual Entertainment, Inc. // // // DESCRIPTION: // //=========================== // Forward Declarations //=========================== #ifndef __CHARACTERSTATE_H__ #define __CHARACTERSTATE_H__ #include "g_local.h" #include "script.h" enum testcondition_t { TC_ISTRUE, // no prefix TC_ISFALSE, // ! TC_EDGETRUE, // + TC_EDGEFALSE // - }; enum movecontrol_t { MOVECONTROL_USER, // Quake style MOVECONTROL_LEGS, // Quake style, legs state system active MOVECONTROL_ANIM, // move based on animation, with full collision testing MOVECONTROL_ABSOLUTE, // move based on animation, with full collision testing but no turning MOVECONTROL_HANGING, // move based on animation, with full collision testing, hanging MOVECONTROL_WALLHUG, // move based on animation, with full collision testing, hanging MOVECONTROL_MONKEYBARS, // move based on animation, with full collision testing, monkey bars MOVECONTROL_PIPECRAWL, // move based on animation, with full collision testing, crawling on pipe MOVECONTROL_PIPEHANG, // move based on animation, with full collision testing, hanging from pipe MOVECONTROL_STEPUP, MOVECONTROL_ROPE_GRAB, MOVECONTROL_ROPE_RELEASE, MOVECONTROL_ROPE_MOVE, MOVECONTROL_PICKUPENEMY, MOVECONTROL_PUSH, MOVECONTROL_CLIMBWALL, MOVECONTROL_USEANIM, MOVECONTROL_CROUCH, MOVECONTROL_LOOPUSEANIM, MOVECONTROL_USEOBJECT, MOVECONTROL_COOLOBJECT, MOVECONTROL_FAKEPLAYER }; enum cameratype_t { CAMERA_TOPDOWN, CAMERA_BEHIND, CAMERA_FRONT, CAMERA_SIDE, CAMERA_BEHIND_FIXED, CAMERA_SIDE_LEFT, CAMERA_SIDE_RIGHT, CAMERA_BEHIND_NOPITCH }; #define DEFAULT_MOVETYPE MOVECONTROL_LEGS #define DEFAULT_CAMERA CAMERA_BEHIND class Conditional; template< class Type > struct Condition { const char *name; qboolean ( Type::*func )( Conditional &condition ); }; class Conditional : public Class { private : qboolean result; qboolean previous_result; bool checked; public : Condition condition; Container parmList; bool getResult( testcondition_t test, Entity &ent ); const char *getName( void ); Conditional( void ); Conditional( const Condition &condition ); const char *getParm( int number ); void addParm( const str &parm ); int numParms( void ); void clearCheck( void ); }; inline void Conditional::addParm ( const str &parm ) { parmList.AddObject( parm ); } inline const char *Conditional::getParm ( int number ) { if ( ( number < 1 ) || ( number > parmList.NumObjects() ) ) { gi.Error( ERR_DROP, "Parm #%d out of range on %s condition\n", number, condition.name ); } return parmList.ObjectAt( number ).c_str(); } inline int Conditional::numParms ( void ) { return parmList.NumObjects(); } inline void Conditional::clearCheck ( void ) { checked = false; } inline const char *Conditional::getName ( void ) { return condition.name; } inline bool Conditional::getResult ( testcondition_t test, Entity &ent ) { if ( condition.func && !checked ) { checked = true; previous_result = result; result = ( ent.*condition.func )( (Conditional&)*this ); } switch( test ) { case TC_ISFALSE : return !result; break; case TC_EDGETRUE : return result && !previous_result; break; case TC_EDGEFALSE : return !result && previous_result; break; case TC_ISTRUE : default : return result != false; } } class State; class StateMap; class FuzzyVar; class Expression : public Class { private : struct condition_t { testcondition_t test; int condition_index; }; str value; Container conditions; // For Fuzzy Vars float points; public : Expression(); Expression( const Expression &exp ); Expression( Script &script, State &state ); Expression( Script &script, FuzzyVar &fuzzyVar ); void operator=( const Expression &exp ); bool getResult( const State &state, Entity &ent, const Container *sent_conditionals ); bool getResult( const FuzzyVar &fVar, Entity &ent, const Container *sent_conditionals ); const char *getValue( void ); // For Fuzzy Vars float getPoints(); }; inline void Expression::operator= ( const Expression &exp ) { int i; Expression *temp_exp = (Expression *)&exp; // This is here to get around some const issues value = exp.value; points = exp.points; conditions.FreeObjectList(); for( i = 1; i <= temp_exp->conditions.NumObjects(); i++ ) { conditions.AddObject( temp_exp->conditions.ObjectAt( i ) ); } } inline const char *Expression::getValue ( void ) { return value.c_str(); } inline float Expression::getPoints() { return points; } class State : public Class { private : Container condition_indexes; StateMap &statemap; str name; str nextState; movecontrol_t movetype; cameratype_t cameratype; str behaviorName; Container behaviorParmList; str headBehaviorName; Container headBehaviorParmList; str eyeBehaviorName; Container eyeBehaviorParmList; str torsoBehaviorName; Container torsoBehaviorParmList; float minTime; float maxTime; Container legAnims; Container torsoAnims; Container states; Container entryCommands; Container exitCommands; qboolean ignoreGlobalStates; void readNextState( Script &script ); void readMoveType( Script &script ); void readCamera( Script &script ); void readLegs( Script &script ); void readTorso( Script &script ); void readBehavior( Script &script ); void readHeadBehavior( Script &script ); void readEyeBehavior( Script &script ); void readTorsoBehavior( Script &script ); void readTime( Script &script ); void readStates( Script &script ); void readCommands( Script &script, Container &container ); void ParseAndProcessCommand( const str &command, Entity *target ); public : State( const char *name, Script &script, StateMap &map ); State *Evaluate( Entity &ent, Container *ent_conditionals ); int addCondition( const char *name, Script &script ); void CheckStates( void ); const char *getName( void ); const char *getLegAnim( Entity &ent, Container *sent_conditionals ); const char *getTorsoAnim( Entity &ent, Container *sent_conditionals ); const char *getBehaviorName( void ); const char *getHeadBehaviorName( void ); const char *getEyeBehaviorName( void ); const char *getTorsoBehaviorName( void ); State *getNextState( void ); movecontrol_t getMoveType( void ); cameratype_t getCameraType( void ); qboolean setCameraType( const str &ctype ); const char *getBehaviorParm( int number=1 ); const char *getHeadBehaviorParm( int number=1 ); const char *getEyeBehaviorParm( int number=1 ); const char *getTorsoBehaviorParm( int number=1 ); void addBehaviorParm( const str &parm ); void addHeadBehaviorParm( const str &parm ); void addEyeBehaviorParm( const str &parm ); void addTorsoBehaviorParm( const str &parm ); int numBehaviorParms( void ); int numHeadBehaviorParms( void ); int numEyeBehaviorParms( void ); int numTorsoBehaviorParms( void ); float getMinTime( void ); float getMaxTime( void ); void ProcessEntryCommands( Entity *target ); void ProcessExitCommands( Entity *target ); void GetLegAnims( Container *c ); void GetTorsoAnims( Container *c ); qboolean IgnoreGlobalStates(); }; inline void State::addBehaviorParm ( const str &parm ) { behaviorParmList.AddObject( parm ); } inline void State::addHeadBehaviorParm ( const str &parm ) { headBehaviorParmList.AddObject( parm ); } inline void State::addEyeBehaviorParm ( const str &parm ) { eyeBehaviorParmList.AddObject( parm ); } inline void State::addTorsoBehaviorParm ( const str &parm ) { torsoBehaviorParmList.AddObject( parm ); } inline const char *State::getBehaviorParm ( int number ) { return behaviorParmList.ObjectAt( number ).c_str(); } inline const char *State::getHeadBehaviorParm ( int number ) { return headBehaviorParmList.ObjectAt( number ).c_str(); } inline const char *State::getEyeBehaviorParm ( int number ) { return eyeBehaviorParmList.ObjectAt( number ).c_str(); } inline const char *State::getTorsoBehaviorParm ( int number ) { return torsoBehaviorParmList.ObjectAt( number ).c_str(); } inline int State::numBehaviorParms ( void ) { return behaviorParmList.NumObjects(); } inline int State::numHeadBehaviorParms ( void ) { return headBehaviorParmList.NumObjects(); } inline int State::numEyeBehaviorParms ( void ) { return eyeBehaviorParmList.NumObjects(); } inline int State::numTorsoBehaviorParms ( void ) { return torsoBehaviorParmList.NumObjects(); } class StateMap : public Class { private : Container stateList; Container globalStateList; Condition *current_conditions; Container *current_conditionals; str filename; public : StateMap(); StateMap( const char *filename, Condition *conditions, Container *conditionals ); ~StateMap(); Condition *getCondition( const char *name ); int findConditional( Conditional *condition ); int addConditional( Conditional *condition ); Conditional *getConditional( const char *name ); void GetAllAnims( Container *c ); State *FindState( const char *name ); State *FindGlobalState( const char *name ); const char *Filename(); void ReadStates( Script *script ); State *GotoGlobalState( State *CurrentState, State *newState ); }; inline const char *StateMap::Filename ( void ) { return filename.c_str(); } inline const char *State::getName ( void ) { return name.c_str(); } inline State *State::getNextState ( void ) { return statemap.FindState( nextState.c_str() ); } inline movecontrol_t State::getMoveType ( void ) { return movetype; } inline cameratype_t State::getCameraType ( void ) { return cameratype; } //================================================ // Class Name: Fuzzy Engine // // Description: // //================================================ class FuzzyEngine : public Class { public : FuzzyEngine( const char *filename, Condition *conditions, Container *conditionals ); Condition *getCondition( const char *name ); int findConditional( Conditional *condition ); int addConditional( Conditional *condition ); Conditional *getConditional( const char *name ); FuzzyVar *FindFuzzyVar( const char *name ); const char *Filename(); void ReadFuzzyVars( const char *filename ); private : Container _varList; Condition *_current_conditions; Container *_current_conditionals; str _filename; }; //================================================ // Class Name: Fuzzy Engine // // Description: // //================================================ class FuzzyVar : public Class { public: FuzzyVar( const char *name, Script &script, FuzzyEngine &f_engine ); float Evaluate( Entity &ent, Container *ent_conditionals ); int addCondition( const char *name, Script &script ); void readEvaluations( Script &script ); const char *getName( void ); private : Container _condition_indexes; Container _evaluations; FuzzyEngine &_fuzzyEngine; str _name; Container _points; }; void ClearCachedStatemaps( void ); StateMap *GetStatemap( const str &filename, Condition *conditions, Container *conditionals, qboolean reload, qboolean cache_only = false ); void CacheStatemap( const str &filename, Condition *conditions ); void ClearCachedFuzzyEngines( void ); FuzzyEngine *GetFuzzyEngine( const str &filename, Condition *conditions, Container *conditionals, qboolean reload, qboolean cache_only = false ); void CacheFuzzyEngine( const str &filename, Condition *conditions ); #endif /* !__CHARACTERSTATE_H__ */