/** callback to use lua for spell functions */ static int lua_callspell(castorder * co, const char *fname) { lua_State *L = (lua_State *)global.vm_state; unit *caster = co_get_caster(co); region * r = co_get_region(co); int result = -1; lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { int nparam = 4; tolua_pushusertype(L, r, TOLUA_CAST "region"); tolua_pushusertype(L, caster, TOLUA_CAST "unit"); lua_pushinteger(L, co->level); lua_pushnumber(L, co->force); if (co->sp->parameter && co->par->length) { const char *synp = co->sp->parameter; int i = 0; ++nparam; lua_newtable(L); while (*synp && i < co->par->length) { spllprm *param = co->par->param[i]; char c = *synp; if (c == '+') { push_param(L, *(synp - 1), param); } else { push_param(L, c, param); ++synp; } lua_rawseti(L, -2, ++i); } } if (lua_pcall(L, nparam, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("spell(%s) calling '%s': %s.\n", unitname(caster), fname, error); lua_pop(L, 1); } else { result = (int)lua_tonumber(L, -1); lua_pop(L, 1); } } else { int ltype = lua_type(L, -1); log_error("spell(%s) calling '%s': not a function, has type %d.\n", unitname(caster), fname, ltype); lua_pop(L, 1); } return result; }
int32 interpreter::call_function(int32 f, uint32 param_count, uint32 ret_count) { if (!f) { sprintf(pduel->strbuffer, "\"CallFunction\": attempt to call a null function."); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } if (param_count != params.size()) { sprintf(pduel->strbuffer, "\"CallFunction\": incorrect parameter count (%d expected, %ud pushed)", param_count, params.size()); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } function2value(current_state, f); if (!lua_isfunction(current_state, -1)) { sprintf(pduel->strbuffer, "\"CallFunction\": attempt to call an error function"); handle_message(pduel, 1); lua_pop(current_state, 1); params.clear(); return OPERATION_FAIL; } no_action++; call_depth++; push_param(current_state); if (lua_pcall(current_state, param_count, ret_count, 0)) { sprintf(pduel->strbuffer, lua_tostring(current_state, -1)); handle_message(pduel, 1); lua_pop(current_state, 1); no_action--; call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return OPERATION_FAIL; } no_action--; call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return OPERATION_SUCCESS; }
int32 interpreter::call_code_function(uint32 code, char* f, uint32 param_count, uint32 ret_count) { if (param_count != params.size()) { sprintf(pduel->strbuffer, "\"CallCodeFunction\": incorrect parameter count"); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } load_card_script(code); lua_getfield(current_state, -1, f); if (!lua_isfunction(current_state, -1)) { sprintf(pduel->strbuffer, "\"CallCodeFunction\": attempt to call an error function"); handle_message(pduel, 1); lua_pop(current_state, 2); params.clear(); return OPERATION_FAIL; } lua_remove(current_state, -2); no_action++; call_depth++; push_param(current_state); if (lua_pcall(current_state, param_count, ret_count, 0)) { sprintf(pduel->strbuffer, lua_tostring(current_state, -1)); handle_message(pduel, 1); lua_pop(current_state, 1); no_action--; call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return OPERATION_FAIL; } no_action--; call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return OPERATION_SUCCESS; }
int32 interpreter::call_card_function(card* pcard, char* f, uint32 param_count, uint32 ret_count) { if (param_count != params.size()) { sprintf(pduel->strbuffer, "\"CallCardFunction\"(c%d.%s): incorrect parameter count", pcard->data.code, f); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } card2value(current_state, pcard); lua_getfield(current_state, -1, f); if (!lua_isfunction(current_state, -1)) { sprintf(pduel->strbuffer, "\"CallCardFunction\"(c%d.%s): attempt to call an error function", pcard->data.code, f); handle_message(pduel, 1); lua_pop(current_state, 2); params.clear(); return OPERATION_FAIL; } no_action++; call_depth++; lua_remove(current_state, -2); push_param(current_state); if (lua_pcall(current_state, param_count, ret_count, 0)) { sprintf(pduel->strbuffer, lua_tostring(current_state, -1)); handle_message(pduel, 1); lua_pop(current_state, 1); no_action--; call_depth--; if(call_depth == 0) pduel->release_script_group(); return OPERATION_FAIL; } no_action--; call_depth--; if(call_depth == 0) pduel->release_script_group(); return OPERATION_SUCCESS; }
int32 interpreter::call_coroutine(int32 f, uint32 param_count, uint32 * yield_value, uint16 step) { *yield_value = 0; if (!f) { sprintf(pduel->strbuffer, "\"CallCoroutine\": attempt to call a null function"); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } if (param_count != params.size()) { sprintf(pduel->strbuffer, "\"CallCoroutine\": incorrect parameter count"); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } coroutine_map::iterator it; it = coroutines.find(f); lua_State* rthread; if (it == coroutines.end()) { rthread = lua_newthread(lua_state); function2value(rthread, f); if(!lua_isfunction(rthread, -1)) { sprintf(pduel->strbuffer, "\"CallCoroutine\": attempt to call an error function"); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } call_depth++; coroutines.insert(make_pair(f, rthread)); } else { rthread = it->second; if(step == 0) { sprintf(pduel->strbuffer, "recursive event trigger detected."); handle_message(pduel, 1); params.clear(); call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return OPERATION_FAIL; } } push_param(rthread, true); current_state = rthread; int32 result = lua_resume(rthread, 0, param_count); if (result == 0) { coroutines.erase(f); if(yield_value) *yield_value = lua_isboolean(rthread, -1) ? lua_toboolean(rthread, -1) : lua_tointeger(rthread, -1); current_state = lua_state; call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return COROUTINE_FINISH; } else if (result == LUA_YIELD) { return COROUTINE_YIELD; } else { coroutines.erase(f); sprintf(pduel->strbuffer, lua_tostring(rthread, -1)); handle_message(pduel, 1); lua_pop(rthread, 1); current_state = lua_state; call_depth--; if(call_depth == 0) { pduel->release_script_group(); pduel->restore_assumes(); } return COROUTINE_ERROR; } }