/** ** Parse the Condition for spell. ** ** @param l Lua state. ** @param autocast pointer to autocast to fill with data. ** ** @note: autocast must be allocated. All data already in is LOST. */ static void CclSpellAutocast(lua_State *l, AutoCastInfo *autocast) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int args = lua_rawlen(l, -1); for (int j = 0; j < args; ++j) { lua_rawgeti(l, -1, j + 1); const char *value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "range")) { lua_rawgeti(l, -1, j + 1); autocast->Range = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "combat")) { lua_rawgeti(l, -1, j + 1); autocast->Combat = Ccl2Condition(l, LuaToString(l, -1)); lua_pop(l, 1); } else if (!strcmp(value, "condition")) { if (!autocast->Condition) { autocast->Condition = new ConditionInfo; } lua_rawgeti(l, -1, j + 1); CclSpellCondition(l, autocast->Condition); lua_pop(l, 1); } else { LuaError(l, "Unsupported autocast tag: %s" _C_ value); } } }
/** ** Parse the Condition for spell. ** ** @param l Lua state. ** @param autocast pointer to autocast to fill with data. ** ** @note: autocast must be allocated. All data already in is LOST. */ static void CclSpellAutocast(lua_State *l, AutoCastInfo *autocast) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int args = lua_rawlen(l, -1); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, -1, j + 1); ++j; if (!strcmp(value, "range")) { autocast->Range = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "min-range")) { autocast->MinRange = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "position-autocast")) { lua_rawgeti(l, -1, j + 1); autocast->PositionAutoCast = new LuaCallback(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "combat")) { autocast->Combat = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "attacker")) { autocast->Attacker = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "corpse")) { autocast->Corpse = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "priority")) { lua_rawgeti(l, -1, j + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, -1, 1); std::string var = LuaToString(l, -1); int index = UnitTypeVar.VariableNameLookup[var.c_str()];// User variables if (index == -1) { if (!strcmp(var.c_str(), "Distance")) { index = ACP_DISTANCE; } else { fprintf(stderr, "Bad variable name '%s'\n", var.c_str()); Exit(1); } } autocast->PriorytyVar = index; lua_pop(l, 1); autocast->ReverseSort = LuaToBoolean(l, -1, 2); lua_pop(l, 1); } else if (!strcmp(value, "condition")) { if (!autocast->Condition) { autocast->Condition = new ConditionInfo; } lua_rawgeti(l, -1, j + 1); CclSpellCondition(l, autocast->Condition); lua_pop(l, 1); } else { LuaError(l, "Unsupported autocast tag: %s" _C_ value); } } }
/** ** Parse Spell. ** ** @param l Lua state. */ static int CclDefineSpell(lua_State *l) { const int args = lua_gettop(l); const std::string identname = LuaToString(l, 1); SpellType *spell = SpellTypeByIdent(identname); if (spell != NULL) { DebugPrint("Redefining spell-type `%s'\n" _C_ identname.c_str()); } else { spell = new SpellType(SpellTypeTable.size(), identname); for (std::vector<CUnitType *>::size_type i = 0; i < UnitTypes.size(); ++i) { // adjust array for caster already defined if (UnitTypes[i]->CanCastSpell) { char *newc = new char[(SpellTypeTable.size() + 1) * sizeof(char)]; memcpy(newc, UnitTypes[i]->CanCastSpell, SpellTypeTable.size() * sizeof(char)); delete[] UnitTypes[i]->CanCastSpell; UnitTypes[i]->CanCastSpell = newc; UnitTypes[i]->CanCastSpell[SpellTypeTable.size()] = 0; } if (UnitTypes[i]->AutoCastActive) { char *newc = new char[(SpellTypeTable.size() + 1) * sizeof(char)]; memcpy(newc, UnitTypes[i]->AutoCastActive, SpellTypeTable.size() * sizeof(char)); delete[] UnitTypes[i]->AutoCastActive; UnitTypes[i]->AutoCastActive = newc; UnitTypes[i]->AutoCastActive[SpellTypeTable.size()] = 0; } } SpellTypeTable.push_back(spell); } for (int i = 1; i < args; ++i) { const char *value = LuaToString(l, i + 1); ++i; if (!strcmp(value, "showname")) { spell->Name = LuaToString(l, i + 1); } else if (!strcmp(value, "manacost")) { spell->ManaCost = LuaToNumber(l, i + 1); } else if (!strcmp(value, "range")) { if (!lua_isstring(l, i + 1) && !lua_isnumber(l, i + 1)) { LuaError(l, "incorrect argument"); } if (lua_isstring(l, i + 1) && !strcmp(lua_tostring(l, i + 1), "infinite")) { spell->Range = INFINITE_RANGE; } else if (lua_isnumber(l, i + 1)) { spell->Range = static_cast<int>(lua_tonumber(l, i + 1)); } else { LuaError(l, "Invalid range"); } } else if (!strcmp(value, "repeat-cast")) { spell->RepeatCast = 1; --i; } else if (!strcmp(value, "target")) { value = LuaToString(l, i + 1); if (!strcmp(value, "self")) { spell->Target = TargetSelf; } else if (!strcmp(value, "unit")) { spell->Target = TargetUnit; } else if (!strcmp(value, "position")) { spell->Target = TargetPosition; } else { LuaError(l, "Unsupported spell target type tag: %s" _C_ value); } } else if (!strcmp(value, "action")) { if (!lua_istable(l, i + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, i + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, i + 1, k + 1); spell->Action.push_back(CclSpellAction(l)); lua_pop(l, 1); } } else if (!strcmp(value, "condition")) { if (!spell->Condition) { spell->Condition = new ConditionInfo; } lua_pushvalue(l, i + 1); CclSpellCondition(l, spell->Condition); lua_pop(l, 1); } else if (!strcmp(value, "autocast")) { if (!spell->AutoCast) { spell->AutoCast = new AutoCastInfo(); } lua_pushvalue(l, i + 1); CclSpellAutocast(l, spell->AutoCast); lua_pop(l, 1); } else if (!strcmp(value, "ai-cast")) { if (!spell->AICast) { spell->AICast = new AutoCastInfo(); } lua_pushvalue(l, i + 1); CclSpellAutocast(l, spell->AICast); lua_pop(l, 1); } else if (!strcmp(value, "sound-when-cast")) { // Free the old name, get the new one spell->SoundWhenCast.Name = LuaToString(l, i + 1); spell->SoundWhenCast.MapSound(); // Check for sound. if (!spell->SoundWhenCast.Sound) { spell->SoundWhenCast.Name.clear(); } } else if (!strcmp(value, "depend-upgrade")) { value = LuaToString(l, i + 1); spell->DependencyId = UpgradeIdByIdent(value); if (spell->DependencyId == -1) { lua_pushfstring(l, "Bad upgrade name: %s", value); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }