- Joined
- Feb 14, 2015
- Messages
- 5,643
- Solutions
- 559
- Reaction score
- 3,949
^Edit up post: I wanted to mention Togu, not Tagu. @Togu
^Edit up post: I wanted to mention Togu, not Tagu. @Togu
static int luaPlayerAddAutoLootItem(lua_State* L);
static int luaPlayerRemoveAutoLootItem(lua_State* L);
static int luaPlayerGetAutoLootItem(lua_State* L);
static int luaPlayerGetAutoLootList(lua_State* L);
if (autolooted != "" and corpse->getContentDescription() == "nothing") {
lootMsg = autolooted.erase(0,2) + " that was auto looted";
} else if (autolooted != "") {
lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted.";
}
if (autolooted != "" && corpse->getContentDescription() == "nothing") {
lootMsg = autolooted.erase(0,2) + " that was auto looted";
} else if (autolooted != "") {
lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted.";
}
Lua Script Error: [TalkAction Interface]
data/talkactions/scripts/autoloot.lua:onSay
data/talkactions/scripts/autoloot.lua:23: attempt to call method 'getAutoLootList' (a nil value)
stack traceback:
[C]: in function 'getAutoLootList'
data/talkactions/scripts/autoloot.lua:23: in function <data/talkactions/scripts/autoloot.lua:21>
What's the difference here?C++:if (autolooted != "" and corpse->getContentDescription() == "nothing") { lootMsg = autolooted.erase(0,2) + " that was auto looted"; } else if (autolooted != "") { lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted."; }
To this one:
C++:if (autolooted != "" && corpse->getContentDescription() == "nothing") { lootMsg = autolooted.erase(0,2) + " that was auto looted"; } else if (autolooted != "") { lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted."; }
That error means the program cannot find a function called getAutoLootList, you did something wrong with this one.Code:Lua Script Error: [TalkAction Interface] data/talkactions/scripts/autoloot.lua:onSay data/talkactions/scripts/autoloot.lua:23: attempt to call method 'getAutoLootList' (a nil value) stack traceback: [C]: in function 'getAutoLootList' data/talkactions/scripts/autoloot.lua:23: in function <data/talkactions/scripts/autoloot.lua:21>
I understand that the method "getAutoLootList" is returning a nil value, so I think that the functions add to compat.lua aren't being loaded.
I already registered the talk action and their scripts.
Anyone can help here?
registerMethod("Player", "addAutoLootItem", LuaScriptInterface::luaPlayerAddAutoLootItem);
registerMethod("Player", "removeAutoLootItem", LuaScriptInterface::luaPlayerRemoveAutoLootItem);
registerMethod("Player", "getAutoLootItem", LuaScriptInterface::luaPlayerGetAutoLootItem);
registerMethod("Player", "getAutoLootList", LuaScriptInterface::luaPlayerGetAutoLootList);
The difference is the "&&" instead of the "and". I'm not that good in C++, but I think that the Boolean operator that represents "AND" is "&&", as the "OR" is "||".What's the difference here?
That error means the program cannot find a function called getAutoLootList, you did something wrong with this one.
Thanks, @Vulcan_ . It worked!no, he needs to registerMethod the functions in the main post because psychonaut left them out
in luascript.cpp where the rest of the player registermethods are, add these:
C++:registerMethod("Player", "addAutoLootItem", LuaScriptInterface::luaPlayerAddAutoLootItem); registerMethod("Player", "removeAutoLootItem", LuaScriptInterface::luaPlayerRemoveAutoLootItem); registerMethod("Player", "getAutoLootItem", LuaScriptInterface::luaPlayerGetAutoLootItem); registerMethod("Player", "getAutoLootList", LuaScriptInterface::luaPlayerGetAutoLootList);
std::unordered_set<uint32_t> autoLootList;
std::set<uint32_t> autoLootList;
std::forward_list<uint32_t> autoLootList;
Fix for this?
in player.h used codes
> No errorC++:std::unordered_set<uint32_t> autoLootList;
player.h> compiler errorC++:std::set<uint32_t> autoLootList;
player.h> compiler errorC++:std::forward_list<uint32_t> autoLootList;
Post your monsters.cpp
Fix for this?
in player.h used codes
> No errorC++:std::unordered_set<uint32_t> autoLootList;
player.h> compiler errorC++:std::set<uint32_t> autoLootList;
player.h> compiler errorC++:std::forward_list<uint32_t> autoLootList;
hastebinPost your monsters.cpp
registerMethod("Player", "getFightMode", LuaScriptInterface::luaPlayerGetFightMode);
registerMethod("Player", "addAutoLootItem", LuaScriptInterface::luaPlayerAddAutoLootItem);
registerMethod("Player", "removeAutoLootItem", LuaScriptInterface::luaPlayerRemoveAutoLootItem);
registerMethod("Player", "getAutoLootItem", LuaScriptInterface::luaPlayerGetAutoLootItem);
registerMethod("Player", "getAutoLootList", LuaScriptInterface::luaPlayerGetAutoLootList);
static int luaPlayerGetFightMode(lua_State* L);
static int luaPlayerAddAutoLootItem(lua_State* L);
static int luaPlayerRemoveAutoLootItem(lua_State* L);
static int luaPlayerGetAutoLootItem(lua_State* L);
static int luaPlayerGetAutoLootList(lua_State* L);
if (autolooted != "" and corpse->getContentDescription() == "nothing") {
lootMsg = autolooted.erase(0,2) + " that was auto looted";
} else if (autolooted != "") {
lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted."; }
if (autolooted != "" && corpse->getContentDescription() == "nothing") {
lootMsg = autolooted.erase(0,2) + " that was auto looted";
} else if (autolooted != "") {
lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted."; }
ss << "Loot of " << nameDescription << ": " << lootMsg;
if (owner->getAutoLootItem(item->getID())) {
g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
autolooted = autolooted + ", " + item->getNameDescription();
} else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
corpse->internalAddThing(item);
}
if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
corpse->internalAddThing(item);
}
if (owner->getAutoLootItem(item->getID())) {
g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
autolooted = autolooted + ", " + item->getNameDescription();
} else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
corpse->internalAddThing(item);
}
void MonsterType::createLoot(Container* corpse)
{
if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) {
corpse->startDecaying();
return;
}
Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner());
std::string autolooted = "";
if (!owner || owner->getStaminaMinutes() > 840) {
for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) {
auto itemList = createLootItem(*it);
if (itemList.empty()) {
continue;
}
for (Item* item : itemList) {
//check containers
if (Container* container = item->getContainer()) {
if (!createLootContainer(container, *it)) {
delete container;
continue;
}
}
if (owner->getAutoLootItem(item->getID())){
g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
autolooted = autolooted + ", " + item->getNameDescription();
} else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
corpse->internalAddThing(item);
}
}
}
if (owner) {
std::ostringstream ss;
std::string lootMsg = corpse->getContentDescription();
//ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); -- change for autoloot system
if (autolooted != "" && corpse->getContentDescription() == "nothing"){
lootMsg = autolooted.erase(0,2) + " that was autolooted";
} else if (autolooted != ""){
lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted";
}
ss << "Loot of " << nameDescription << ": " << lootMsg;
if (owner->getParty()) {
ss << " by " << owner->getName();
owner->getParty()->broadcastPartyLoot(ss.str());
} else {
owner->sendTextMessage(MESSAGE_LOOT, ss.str());
}
}
} else {
std::ostringstream ss;
ss << "Loot of " << nameDescription << ": nothing (due to low stamina)";
if (owner->getParty()) {
owner->getParty()->broadcastPartyLoot(ss.str());
} else {
owner->sendTextMessage(MESSAGE_LOOT, ss.str());
}
}
corpse->startDecaying();
}
what is wrong?
C++:/home/.ots/src/player.h:1378:8: error: ‘set’ in namespace ‘std’ does not name a template type std::set<uint32_t>autoLootList; ^ CMakeFiles/tfs.dir/build.make:119: recipe for target 'CMakeFiles/tfs.dir/src/act ions.cpp.o' failed make[2]: *** [CMakeFiles/tfs.dir/src/actions.cpp.o] Error 1 CMakeFiles/Makefile2:122: recipe for target 'CMakeFiles/tfs.dir/all' failed make[1]: *** [CMakeFiles/tfs.dir/all] Error 2 Makefile:76: recipe for target 'all' failed make: *** [all] Error 2
God Of Pain!
Code:use forward_list<uint32_t>
Fix for this?
in player.h used codes
> No errorC++:std::unordered_set<uint32_t> autoLootList;
player.h> compiler errorC++:std::set<uint32_t> autoLootList;
player.h> compiler errorC++:std::forward_list<uint32_t> autoLootList;
very good! However there is a missing condition that is enabling a possible crash ...This is a mess, I won't point to anyone, but remember that developers who wrote this did it as a hobby and FOR FREE, okay, the code from @psychonaut have some errors, but they might be because he did this because he was bored, and coding is fun except when you have to deal with cry babies complaining about some very simple lines not working. Really guys, if you come to the C++ codes section, try to read and understand code, creating a server is not just to copy and paste other people's systems.
Now, I'm going to TRY to explain every error I think the system have.
first, psychonaut didn't post the code to register the lua functions, and you need to do that so your lua code will recognize the addloot functions.
As @flaviiojr said, on luascript.cpp search for:
Lua:registerMethod("Player", "getFightMode", LuaScriptInterface::luaPlayerGetFightMode);
That should be your last player method if you are using a recent TFS 1.3, below that add:
Code:registerMethod("Player", "addAutoLootItem", LuaScriptInterface::luaPlayerAddAutoLootItem); registerMethod("Player", "removeAutoLootItem", LuaScriptInterface::luaPlayerRemoveAutoLootItem); registerMethod("Player", "getAutoLootItem", LuaScriptInterface::luaPlayerGetAutoLootItem); registerMethod("Player", "getAutoLootList", LuaScriptInterface::luaPlayerGetAutoLootList);
Now, go to luascript.h and search for:
Code:static int luaPlayerGetFightMode(lua_State* L);
And add below that:
Code:static int luaPlayerAddAutoLootItem(lua_State* L); static int luaPlayerRemoveAutoLootItem(lua_State* L); static int luaPlayerGetAutoLootItem(lua_State* L); static int luaPlayerGetAutoLootList(lua_State* L);
Now, the next error is the one of people claiming that there is no loot message anymore, first there is a typo mistake on this part of code that the OP told everyone to add
Code:if (autolooted != "" and corpse->getContentDescription() == "nothing") { lootMsg = autolooted.erase(0,2) + " that was auto looted"; } else if (autolooted != "") { lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted."; }
If you read carefully, it says "if (autolooted != "" and corpse->....." the AND on C++ is &&, so you have to change that, it will look like this:
Code:if (autolooted != "" && corpse->getContentDescription() == "nothing") { lootMsg = autolooted.erase(0,2) + " that was auto looted"; } else if (autolooted != "") { lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted."; }
Now, the next mistake is, that you were told to REPLACE the line with "ss << "Loot of " << nameDescription..." so after that last if block you need to add it again but with the lootMsg variable, so one line below add:
Code:ss << "Loot of " << nameDescription << ": " << lootMsg;
Now the last mistake is that after all those, the system at all doesn't works (it doesn't take the item), that because you where told to REPLACE the line with "corpse->internalAddThing(item);" to the following:
Code:if (owner->getAutoLootItem(item->getID())) { g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER); autolooted = autolooted + ", " + item->getNameDescription(); } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) { corpse->internalAddThing(item); }
Which is wrong, what you really have to reaplce is the entire if block, so.
REPLACE:
Code:if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) { corpse->internalAddThing(item); }
WITH:
Code:if (owner->getAutoLootItem(item->getID())) { g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER); autolooted = autolooted + ", " + item->getNameDescription(); } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) { corpse->internalAddThing(item); }
So your function create loot over monsters.cpp should look like this:
Code:void MonsterType::createLoot(Container* corpse) { if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) { corpse->startDecaying(); return; } Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner()); std::string autolooted = ""; if (!owner || owner->getStaminaMinutes() > 840) { for (auto it = info.lootItems.rbegin(), end = info.lootItems.rend(); it != end; ++it) { auto itemList = createLootItem(*it); if (itemList.empty()) { continue; } for (Item* item : itemList) { //check containers if (Container* container = item->getContainer()) { if (!createLootContainer(container, *it)) { delete container; continue; } } if (owner->getAutoLootItem(item->getID())){ g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER); autolooted = autolooted + ", " + item->getNameDescription(); } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) { corpse->internalAddThing(item); } } } if (owner) { std::ostringstream ss; std::string lootMsg = corpse->getContentDescription(); //ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); -- change for autoloot system if (autolooted != "" && corpse->getContentDescription() == "nothing"){ lootMsg = autolooted.erase(0,2) + " that was autolooted"; } else if (autolooted != ""){ lootMsg = corpse->getContentDescription() + " and " + autolooted.erase(0,2) + " was auto looted"; } ss << "Loot of " << nameDescription << ": " << lootMsg; if (owner->getParty()) { ss << " by " << owner->getName(); owner->getParty()->broadcastPartyLoot(ss.str()); } else { owner->sendTextMessage(MESSAGE_LOOT, ss.str()); } } } else { std::ostringstream ss; ss << "Loot of " << nameDescription << ": nothing (due to low stamina)"; if (owner->getParty()) { owner->getParty()->broadcastPartyLoot(ss.str()); } else { owner->sendTextMessage(MESSAGE_LOOT, ss.str()); } } corpse->startDecaying(); }
Be sure to read my post slowly and step by step to understand what you have to do, and remember, we are helping with hope to receive no more than a thanks in exchange, nobody is perfect, and nobody will like to help a crybaby just because they don't understand the code, maybe I'm missing something too, I read the whole thread and I was able to figure out how to make it works (I'm a developer, but I'm not a C++ developer).
Best regards
if (owner->getAutoLootItem(item->getID())){
g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
autolooted = autolooted + ", " + item->getNameDescription();
} else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
corpse->internalAddThing(item);
}
if (owner && owner->getAutoLootItem(item->getID())){
g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER);
autolooted = autolooted + ", " + item->getNameDescription();
} else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) {
corpse->internalAddThing(item);
}
-- Can not edit ...
C++:if (owner && owner->getAutoLootItem(item->getID())){ g_game.internalPlayerAddItem(owner, item, true, CONST_SLOT_WHEREEVER); autolooted = autolooted + ", " + item->getNameDescription(); } else if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) { corpse->internalAddThing(item); }