*Custom depot as reward chest to store the unclaimed loot of bosses.
*Individual reward for each player that hits the boss.
*Loot chance determined by % of damage dealt to boss.
*Player may "pick up" his reward container directly from the corpse.
*Unclaimed reward is sent to online and offline participant players when corpse rots.
*Unclaimed loot containers get erased after seven days of being stored.
*Only items may be taken out from reward chest, cannot put items in there.
*Players' reward containers are stored as encoded, serialized tables on database.
*Exhaustion limit to open reward chest, in order to avoid the spam of sql queries.
*Individual reward for each player that hits the boss.
*Loot chance determined by % of damage dealt to boss.
*Player may "pick up" his reward container directly from the corpse.
*Unclaimed reward is sent to online and offline participant players when corpse rots.
*Unclaimed loot containers get erased after seven days of being stored.
*Only items may be taken out from reward chest, cannot put items in there.
*Players' reward containers are stored as encoded, serialized tables on database.
*Exhaustion limit to open reward chest, in order to avoid the spam of sql queries.
*Damage taken by the boss leads to a % of loot drop.
*Healers' amount of health given to boss slayers leads to a % of loot drop.
*Open reward chest as an inner depot.
*Set the corpses of the bosses as virtual and temporary depots to make it more realistic.
*Healers' amount of health given to boss slayers leads to a % of loot drop.
*Open reward chest as an inner depot.
*Set the corpses of the bosses as virtual and temporary depots to make it more realistic.
(0.1) initial release
(0.2) base64 coding for serialized rewards
(0.3) fix for infinite corpses' decay
(0.4) fix for bosses with lowercase names
(0.2) base64 coding for serialized rewards
(0.3) fix for infinite corpses' decay
(0.4) fix for bosses with lowercase names
This is a system which I got requested to write a year ago, now released with the consent of the customer. It's kinda like Tibia's Boss Reward feature that lets all participant players that kill a boss to get a part of his loot. It is still far away from the original creation, but at least it's something that many OTS owners want. I welcome all developers, programmers and scripters that desire to improve this code, so this can get closer to perfection.
@Dalkon, for his tips of C++
@gugahoa, for the loot functions
@Colandus and @Cykotitan, for the string.diff function
@Printer, for updating the exhaustion functions
@gugahoa, for the loot functions
@Colandus and @Cykotitan, for the string.diff function
@Printer, for updating the exhaustion functions
Execute query at database
Code:
CREATE TABLE IF NOT EXISTS `player_rewardchest` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`player_id` int(11) NOT NULL,
`reward` text NOT NULL,
`date` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
src/const.h
Below...
Code:
ITEM_MARKET = 14405
Code:
ITEM_REWARD_CHEST = 21584,
REWARD_CHEST_DEPOT = 99,
src/depotchest.h
Below...
Code:
explicit DepotChest(uint16_t _type);
Code:
uint32_t getDepotId() const {
return depotId;
}
void setDepotId(uint32_t id) {
depotId = id;
}
Code:
uint32_t maxDepotItems;
Code:
uint32_t depotId;
src/depotchest.cpp
Below...
Code:
maxDepotItems = 1500;
Code:
depotId = 0;
Code:
return Container::queryAdd(index, thing, count, flags, actor);
Code:
if (actor != nullptr && getDepotId() == REWARD_CHEST_DEPOT) {
return RETURNVALUE_NOTPOSSIBLE;
}
src/depotlocker.h
Above...
Code:
//cylinder implementations
Code:
void setMaxLockerItems(uint32_t maxitems) {
maxSize = maxitems;
}
src/luascript.h
Above...
Code:
static int luaContainerGetSize(lua_State* L);
Code:
static int luaContainerGetContentDescription(lua_State* L);
Above...
Code:
registerMethod("Container", "getSize", LuaScriptInterface::luaContainerGetSize);
Code:
registerMethod("Container", "getContentDescription", LuaScriptInterface::luaContainerGetContentDescription);
Code:
int LuaScriptInterface::luaContainerGetSize(lua_State* L)
Code:
int LuaScriptInterface::luaContainerGetContentDescription(lua_State* L)
{
// container:getContentDescription()
Container* container = getUserdata<Container>(L, 1);
if (container) {
std::ostringstream ss;
ss << container->getContentDescription();
pushString(L, ss.str());
} else {
lua_pushnil(L);
}
return 1;
}
src/actions.cpp
Change:
Code:
//depot container
if (DepotLocker* depot = container->getDepotLocker()) {
DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());
myDepotLocker->setParent(depot->getParent()->getTile());
openContainer = myDepotLocker;
player->setLastDepotId(depot->getDepotId());
} else {
openContainer = container;
}
Code:
//reward chest and depot container
if (item->getID() == ITEM_REWARD_CHEST) {
DepotLocker* myRewardChest = player->getRewardChest();
myRewardChest->setParent(item->getTile());
openContainer = myRewardChest;
player->setLastDepotId(REWARD_CHEST_DEPOT);
} else if (DepotLocker* depot = container->getDepotLocker()) {
DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId());
myDepotLocker->setParent(depot->getParent()->getTile());
openContainer = myDepotLocker;
player->setLastDepotId(depot->getDepotId());
} else {
openContainer = container;
}
src/player.h
Below...
Code:
DepotLocker* getDepotLocker(uint32_t depotId);
Code:
DepotLocker* getRewardChest();
src/player.cpp
Below...
Code:
DepotChest* depotChest = new DepotChest(ITEM_DEPOT);
Code:
depotChest->setDepotId(depotId);
Code:
void Player::sendCancelMessage(ReturnValue message) const
Code:
DepotLocker* Player::getRewardChest()
{
auto it = depotLockerMap.find(REWARD_CHEST_DEPOT);
if (it != depotLockerMap.end()) {
inbox->setParent(it->second);
return it->second;
}
DepotLocker* rewardChest = new DepotLocker(ITEM_LOCKER1);
rewardChest->setDepotId(REWARD_CHEST_DEPOT);
rewardChest->setMaxLockerItems(1);
rewardChest->internalAddThing(getDepotChest(REWARD_CHEST_DEPOT, true));
depotLockerMap[REWARD_CHEST_DEPOT] = rewardChest;
return rewardChest;
}
On player.cpp, container.cpp, inbox.cpp
Change:
Code:
if (!item->isPickupable()) {
Code:
if (item->getID() != 21518 && !item->isPickupable()) {