SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
LUACondition.h
Go to the documentation of this file.
1 
6 #pragma once
7 
8 #include "ICondition.h"
9 #include "LUAFunctions.h"
10 
11 namespace ai {
12 
16 class LUACondition : public ICondition {
17 protected:
18  lua_State* _s;
19 
20  bool evaluateLUA(const AIPtr& entity) {
21  // get userdata of the condition
22  const std::string name = "__meta_condition_" + _name;
23  lua_getfield(_s, LUA_REGISTRYINDEX, name.c_str());
24 #if AI_LUA_SANTITY > 0
25  if (lua_isnil(_s, -1)) {
26  ai_log_error("LUA condition: could not find lua userdata for %s", _name.c_str());
27  return false;
28  }
29 #endif
30  // get metatable
31  lua_getmetatable(_s, -1);
32 #if AI_LUA_SANTITY > 0
33  if (!lua_istable(_s, -1)) {
34  ai_log_error("LUA condition: userdata for %s doesn't have a metatable assigned", _name.c_str());
35  return false;
36  }
37 #endif
38  // get evaluate() method
39  lua_getfield(_s, -1, "evaluate");
40  if (!lua_isfunction(_s, -1)) {
41  ai_log_error("LUA condition: metatable for %s doesn't have the evaluate() function assigned", _name.c_str());
42  return false;
43  }
44 
45  // push self onto the stack
46  lua_getfield(_s, LUA_REGISTRYINDEX, name.c_str());
47 
48  // first parameter is ai
49  if (luaAI_pushai(_s, entity) == 0) {
50  return false;
51  }
52 
53 #if AI_LUA_SANTITY > 0
54  if (!lua_isfunction(_s, -3)) {
55  ai_log_error("LUA condition: expected to find a function on stack -3");
56  return false;
57  }
58  if (!lua_isuserdata(_s, -2)) {
59  ai_log_error("LUA condition: expected to find the userdata on -2");
60  return false;
61  }
62  if (!lua_isuserdata(_s, -1)) {
63  ai_log_error("LUA condition: second parameter should be the ai");
64  return false;
65  }
66 #endif
67  const int error = lua_pcall(_s, 2, 1, 0);
68  if (error) {
69  ai_log_error("LUA condition script: %s", lua_isstring(_s, -1) ? lua_tostring(_s, -1) : "Unknown Error");
70  // reset stack
71  lua_pop(_s, lua_gettop(_s));
72  return false;
73  }
74  const int state = lua_toboolean(_s, -1);
75  if (state != 0 && state != 1) {
76  ai_log_error("LUA condition: illegal evaluate() value returned: %i", state);
77  return false;
78  }
79 
80  // reset stack
81  lua_pop(_s, lua_gettop(_s));
82  return state == 1;
83  }
84 
85 public:
87  private:
88  lua_State* _s;
89  std::string _type;
90  public:
91  LUAConditionFactory(lua_State* s, const std::string& typeStr) :
92  _s(s), _type(typeStr) {
93  }
94 
95  inline const std::string& type() const {
96  return _type;
97  }
98 
99  ConditionPtr create(const ConditionFactoryContext* ctx) const override {
100  return std::make_shared<LUACondition>(_type, ctx->parameters, _s);
101  }
102  };
103 
104  LUACondition(const std::string& name, const std::string& parameters, lua_State* s) :
105  ICondition(name, parameters), _s(s) {
106  }
107 
108  ~LUACondition() {
109  }
110 
111  bool evaluate(const AIPtr& entity) override {
112 #if AI_EXCEPTIONS
113  try {
114 #endif
115  return evaluateLUA(entity);
116 #if AI_EXCEPTIONS
117  } catch (...) {
118  ai_log_error("Exception while evaluating lua condition");
119  }
120  return false;
121 #endif
122  }
123 };
124 
125 }
Definition: LUACondition.h:86
bool evaluate(const AIPtr &entity) override
Checks whether the condition evaluates to true for the given entity.
Definition: LUACondition.h:111
#define ai_log_error(...)
Logging macro to provide your own loggers.
Definition: Types.h:23
A condition can be placed on a TreeNode to decide which node is going to get executed. In general they are stateless. If they are not, it should explicitly get noted.
Definition: ICondition.h:124
Definition: AIFactories.h:51
Definition: LUACondition.h:16
Condition related stuff.
Definition: AIFactories.h:96