psychonaut
Well-Known Member
- Joined
- Dec 1, 2017
- Messages
- 75
- Solutions
- 6
- Reaction score
- 56
I was bored so i did this code, thanks @Thexamx for the general help.
In player.h, above
Add:
Below:
Add:
In player.cpp, add these lines:
In monsters.cpp, before:
Add:
Replace:
With:
Below:
Add:
And replace
With:
In luascript.cpp, add these lines:
And in iologindata.cpp, below:
Add:
And above:
Add:
Note that in both you could use the same stream as conditions and clear it, but idk what you changed or not in the code.
Go to your database and create a new table named player_autoloot with id(primary/auto increment), player_id(int) and autoloot_list(blob). Something like:
And then go to data/lib/compat/compat.lua(or where you wanna use it) and add these lines:
These are the commands:
xml:
The function can do a check for id/names but i'm doing in lua as i already need to getting the itemType anyway.
Sometimes when i copy part of a code here the identation goes away(and i can't fix it here), so tab it yourself where it happened.
You can call these functions in a npc if you doesn't wanna use talkactions or anywhere that you want.
In player.h, above
Code:
std::unordered_set<uint32_t> attackedSet;
Code:
std::set<uint32_t> autoLootList;
Below:
Code:
bool hasLearnedInstantSpell(const std::string& spellName) const;
Code:
void addAutoLootItem(uint16_t itemId);
void removeAutoLootItem(uint16_t itemId);
bool getAutoLootItem(uint16_t itemId);
In player.cpp, add these lines:
Code:
void Player::addAutoLootItem(uint16_t itemId)
{
autoLootList.insert(itemId);
}
void Player::removeAutoLootItem(uint16_t itemId)
{
autoLootList.erase(itemId);
}
bool Player::getAutoLootItem(const uint16_t itemId)
{
return autoLootList.find(itemId) != autoLootList.end();
}
In monsters.cpp, before:
Code:
if (!owner || owner->getStaminaMinutes() > 840) {
Code:
std::string autolooted = "";
Replace:
Code:
corpse->internalAddThing(item);
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);
}
Below:
Code:
std::ostringstream ss;
Code:
std::string lootMsg = corpse->getContentDescription();
And replace
Code:
ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription();
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.";
}
In luascript.cpp, add these lines:
Code:
//Autoloot wrote by Psychonaut#4421
int LuaScriptInterface::luaPlayerAddAutoLootItem(lua_State* L)
{
// player:addAutoLootItem(itemId)
Player* player = getUserdata<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
player->addAutoLootItem(itemId);
pushBoolean(L, true);
return 1;
}
int LuaScriptInterface::luaPlayerRemoveAutoLootItem(lua_State* L)
{
// player:removeAutoLootItem(itemId)
Player* player = getUserdata<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
player->removeAutoLootItem(itemId);
pushBoolean(L, true);
return 1;
}
int LuaScriptInterface::luaPlayerGetAutoLootItem(lua_State* L)
{
// player:getAutoLootItem(itemId)
Player* player = getUserdata<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
if (player->getAutoLootItem(itemId)) {
pushBoolean(L, true);
} else {
pushBoolean(L, false);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetAutoLootList(lua_State* L)
{
// player:getAutoLootList()
Player* player = getUserdata<Player>(L, 1);
if (player) {
std::set<uint32_t> value = player->autoLootList;
if (value.size() == 0) {
lua_pushnil(L);
return 1;
}
int index = 0;
lua_createtable(L, value.size(), 0);
for(auto i : value) {
lua_pushnumber(L, i);
lua_rawseti(L, -2, ++index);
}
} else {
lua_pushnil(L);
}
return 1;
}
And in iologindata.cpp, below:
Code:
//load storage map
query.str(std::string());
query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID();
if ((result = db.storeQuery(query.str()))) {
do {
player->addStorageValue(result->getNumber<uint32_t>("key"), result->getNumber<int32_t>("value"), true);
} while (result->next());
}
Add:
Code:
//load autoloot list set
query.str(std::string());
query << "SELECT `autoloot_list` FROM `player_autoloot` WHERE `player_id` = " << player->getGUID();
if ((result = db.storeQuery(query.str()))) {
unsigned long lootlistSize;
const char* autolootlist = result->getStream("autoloot_list", lootlistSize);
PropStream propStreamList;
propStreamList.init(autolootlist, lootlistSize);
int16_t value;
int16_t item = propStreamList.read<int16_t>(value);
while (item) {
player->addAutoLootItem(value);
item = propStreamList.read<int16_t>(value);
}
}
And above:
Code:
//save inbox items
Add:
Code:
//save autolootlist
query.str(std::string());
query << "DELETE FROM `player_autoloot` WHERE `player_id` = " << player->getGUID();
if (!db.executeQuery(query.str())) {
return false;
}
PropWriteStream propWriteStreamAutoLoot;
for (auto i : player->autoLootList) {
propWriteStreamAutoLoot.write<uint16_t>(i);
}
size_t lootlistSize;
const char* autolootlist = propWriteStreamAutoLoot.getStream(lootlistSize);
query.str(std::string());
DBInsert autolootQuery("INSERT INTO `player_autoloot` (`player_id`, `autoloot_list`) VALUES ");
query << player->getGUID() << ',' << db.escapeBlob(autolootlist, lootlistSize);
if (!autolootQuery.addRow(query)) {
return false;
}
if (!autolootQuery.execute()) {
return false;
}
Note that in both you could use the same stream as conditions and clear it, but idk what you changed or not in the code.
Go to your database and create a new table named player_autoloot with id(primary/auto increment), player_id(int) and autoloot_list(blob). Something like:
Code:
CREATE TABLE player_autoloot (
id int NOT NULL AUTO_INCREMENT,
player_id int NOT NULL,
autoloot_list blob,
PRIMARY KEY (id)
);
And then go to data/lib/compat/compat.lua(or where you wanna use it) and add these lines:
Lua:
--AutoLoot written by Psychonaut#4421
function getPlayerAutoLootItem(cid, itemId) local p = Player(cid) return p ~= nil and p:getAutoLootItem(itemId) or false end
function getPlayerAutoLootList(cid) local p = Player(cid) return p ~= nil and p:getAutoLootList() or false end
function removePlayerAutoLootItem(cid, itemId) local p = Player(cid) return p ~= nil and p:removeAutoLootItem(itemId) or false end
function addPlayerAutoLootItem(cid, itemId) local p = Player(cid) return p ~= nil and p:addAutoLootItem(itemId) or false end
These are the commands:
xml:
Code:
<talkaction words="!autoloot" script="autoloot.lua" />
<talkaction words="!add" separator=" " script="addautoloot.lua" />
<talkaction words="!remove" separator=" " script="remautoloot.lua" />
Lua:
function onSay(player, words, param)
local list = "You're auto looting: "
local alist = player:getAutoLootList()
if alist then
for _, item in ipairs(alist) do
list = list .. (ItemType(item)):getName() .. ", "
end
else
player:sendCancelMessage("The list is empty.")
return false
end
player:sendTextMessage(MESSAGE_INFO_DESCR, list:sub(1, -3))
return false
end
Lua:
function onSay(player, words, param)
local itemType = ItemType(param)
if itemType:getId() == 0 then
itemType = ItemType(tonumber(param))
if itemType:getName() == '' then
player:sendCancelMessage("There is no item with that id or name.")
return false
end
end
if player:getAutoLootItem(itemType:getId()) then
player:sendCancelMessage("You're already autolooting this item.")
return false
end
player:addAutoLootItem(itemType:getId())
player:sendTextMessage(MESSAGE_INFO_DESCR, "You're now auto looting " .. itemType:getName())
return false
end
Lua:
function onSay(player, words, param)
local itemType = ItemType(param)
if itemType:getId() == 0 then
itemType = ItemType(tonumber(param))
if itemType:getName() == '' then
player:sendCancelMessage("There is no item with that id or name.")
return false
end
end
if player:getAutoLootItem(itemType:getId()) then
player:removeAutoLootItem(itemType:getId())
player:sendTextMessage(MESSAGE_INFO_DESCR, "You're not auto looting " .. itemType:getName() .. " anymore.")
else
player:sendCancelMessage("You're not autolooting this item.")
end
return false
end
Sometimes when i copy part of a code here the identation goes away(and i can't fix it here), so tab it yourself where it happened.
You can call these functions in a npc if you doesn't wanna use talkactions or anywhere that you want.
Last edited by a moderator: