zuber966
Member
Hi!
Here is a Battle Royale mode for tfs 1.3 I have beed working on. Now I don't really have time to go on with this so I will leave it here for the community. It was my first time with LUA so there might be some garbage code D:
How does it work?
Determine area where players can fight in this event/mode. After some time, area starts burning with fire circle by circle starting from given radius to area origin point. Every player stars as a Knight with given level, max hp, mp, and skill level so every one have the same chances at the beginning. Stats of every player are stored so after death in this mode no one looses anything (skills, level, eq, vocation). Each player is teleported to the random position in the royale area, also chests are distributed randomly. Each chest contains x not repetitive items, where at least on item is weapon.
After death player's stats are returned, bonus exp time, coins are given and gold is distributed based on how many player take part in the event.
I was testing it on otservbr-global from develop branch and it was fine.
First creature events:
Global events
Libs
Part two in next post
royale_utils.lua
Talkaction
SQL schema
In
And add those two tables
C++
In
Add
after
add
after
add
add somewhere in player methods
add implementations
Part three in next post
find
change to
find (this can be found in two places, apply changes in both)
right after for loop add
before
add
at the end add
player.h
add
Disclaimer
Lua function player:removeAllConditions() defined in luascript.cpp was working fine in windows, but in ubuntu was causing server crash. Instead you might try global function removeAllConditions(player).
Things that I wanted to do, but don't have time:
If you have any questions I will try to answer and if it is too much garbage just remove thread.
Also some custom runes and items like monster summoner rune can be found on github.
Cheers :*
Here is a Battle Royale mode for tfs 1.3 I have beed working on. Now I don't really have time to go on with this so I will leave it here for the community. It was my first time with LUA so there might be some garbage code D:
How does it work?
Determine area where players can fight in this event/mode. After some time, area starts burning with fire circle by circle starting from given radius to area origin point. Every player stars as a Knight with given level, max hp, mp, and skill level so every one have the same chances at the beginning. Stats of every player are stored so after death in this mode no one looses anything (skills, level, eq, vocation). Each player is teleported to the random position in the royale area, also chests are distributed randomly. Each chest contains x not repetitive items, where at least on item is weapon.
After death player's stats are returned, bonus exp time, coins are given and gold is distributed based on how many player take part in the event.
I was testing it on otservbr-global from develop branch and it was fine.
First creature events:
data/scripts/creaturescripts/battle_royale_death.lua
Lua:
-- credits: https://github.com/gurgaczj
-- contact: https://otland.net/members/zuber966.239759/
local BRPlayerDeath = CreatureEvent("BattleRoyaleDeath")
function BRPlayerDeath.onDeath(player, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
if lasthitkiller and lasthitkiller:isPlayer() then
local targetID = player:getGuid()
lasthitkiller:removeUnjustifiedKill(targetID)
db.asyncQuery("UPDATE `player_deaths` SET `unjustified` = 0 and `mostdamage_unjustified` = 0 WHERE `player_id` = " .. db.escapeString(targetID) .. " AND `mostdamage_by` LIKE " .. db.escapeString(lasthitkiller:getName()))
end
for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
local item = player:getSlotItem(i)
if item ~= nil then
item:moveTo(corpse)
end
end
brGame:playerDied(player)
teleportToTemple(player)
player:remove()
return true
end
BRPlayerDeath:register()
data/scripts/creaturescripts/battle_royale_message_after_death.lua
Lua:
-- credits: https://github.com/gurgaczj
-- contact: https://otland.net/members/zuber966.239759/
local brMessage = CreatureEvent("BattleRoyaleMessageAfterDeath")
function brMessage.onLogin(player)
local resultId = db.storeQuery("SELECT `id`, `message`, `message_type` FROM `battle_royale_reward_msg` WHERE `player_id` = " .. db.escapeString(player:getGuid()) .. " AND `unreaded` = 1")
if resultId ~= false then
repeat
local message = result.getString(resultId, "message")
local messageType = result.getNumber(resultId, "message_type")
player:sendTextMessage(messageType, message)
local messageId = result.getNumber(resultId, "id")
db.asyncQuery("DELETE FROM `battle_royale_reward_msg` WHERE `id` = " .. db.escapeString(messageId))
until not result.next(resultId)
result.free(resultId) -- Free memory
end
return true
end
brMessage:register()
data/scripts/creaturescripts/battle_royale_on_health_change.lua
Lua:
-- credits: https://github.com/gurgaczj
-- contact: https://otland.net/members/zuber966.239759/
local brHealthChange = CreatureEvent("BattleRoyaleHealthChange")
function brHealthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
if attacker and attacker:isPlayer() then
resetSkull(attacker)
end
return primaryDamage, primaryType, -secondaryDamage, secondaryType
end
brHealthChange:register()
data/scripts/creaturescripts/battle_royale_player_logout.lua
Lua:
-- credits: https://github.com/gurgaczj
-- contact: https://otland.net/members/zuber966.239759/
local brPlayerOnLogout = CreatureEvent("BattleRoyaleLogout")
function brPlayerOnLogout.onLogout(player)
if brGame.canRegister and not brGame.isBattle then
brGame:removePlayer(player)
end
if brGame.isBattle then
if brPlayersStats[player:getName()] ~= nil then
player:sendCancelMessage("You can not logout from battle royale.")
return false
end
end
return true
end
brPlayerOnLogout:register()
Global events
data/scripts/globalevents/royale_events.lua
Lua:
-- credits: https://github.com/gurgaczj
-- contact: https://otland.net/members/zuber966.239759/
local royaleStartSign = GlobalEvent("royaleRegisterStart")
function royaleStartSign.onTime(interval)
brGame:startRegister()
end
royaleStartSign:time("20:00")
royaleStartSign:register()
local royaleStopSign = GlobalEvent("royaleRegisterStop")
function royaleStopSign.onTime(interval)
brGame:closeRegister()
broadcastMessage("Signing up for Battle Royale just stopped. \nBattle will start in minute", MESSAGE_STATUS_CONSOLE_BLUE)
end
royaleStopSign:time("20:14")
royaleStopSign:register()
local royaleBegin = GlobalEvent("royaleBegin")
function royaleBegin.onTime(interval)
brGame:begin()
end
royaleBegin:time("20:15")
royaleBegin:register()
local royaleClean = GlobalEvent("royaleClean")
function royaleClean.onTime(interval)
cleanBattleRoyaleMap()
end
royaleClean:time("03:00")
royaleClean:register()
Libs
data/scripts/lib/royale.lua
Lua:
-- credits: https://github.com/gurgaczj
-- contact: https://otland.net/members/zuber966.239759/
BattleRoyale = {players = {}, canRegister = false, isBattle = false, goldPool = 0}
function BattleRoyale:new (o, players, canReg, battle, pool)
o = o or {}
setmetatable(o, self)
self.__index = self
table = table or {}
self.players = players;
self.canRegister = canReg;
self.isBattle = battle;
self.goldPool = pool;
return o
end
brGame = BattleRoyale:new(nil, {}, false, false, 1000000)
brPlayersStats = {} -- players stats, global becouse used in onDeath event, I know, should have use getter
local totalPlayerCount = 0 -- need to calculate gold reward for each player
-- everything starts here
function BattleRoyale:begin()
totalPlayerCount = #self.players
if totalPlayerCount <= 1 then
broadcastMessage("Not enough players for BattleRoyale. Need at least 2. No match today :/", MESSAGE_STATUS_CONSOLE_BLUE)
self:reset()
return
end
print(totalPlayerCount .. " players registered for Battle Royale.")
self.isBattle = true
spawnChests()
-- for each registered player
for playerNum = 1, totalPlayerCount do
local actualPlayer = self.players[playerNum]
actualPlayer:save()
local playerID = actualPlayer:getName()
brPlayersStats[playerID] = getPlayerStatsInfo(actualPlayer)
actualPlayer:removeAllConditions()
local playerParty = actualPlayer:getParty()
if playerParty ~= nil then
playerParty:removeMember(actualPlayer)
end
actualPlayer:setSkullTime(0)
actualPlayer:setVocation(4)
setHPAndMana(actualPlayer)
actualPlayer:setSkillLoss(false)
actualPlayer:resetSkills() -- remove player skills
actualPlayer:setSkillValues(1, 70, 0, 0)
actualPlayer:setSkillValues(2, 70, 0, 0)
actualPlayer:setSkillValues(3, 70, 0, 0)
actualPlayer:setBaseMagicLevel(3)
actualPlayer:setManaSpent(1)
actualPlayer:setBattleRoyalePlayer(true);
teleportPlayerToRoyale(actualPlayer)
moveItemsToDepot(actualPlayer)
actualPlayer:addItem(1988, 1, false, 1, CONST_SLOT_WHEREEVER)
registerEvent(actualPlayer, "BattleRoyaleDeath")
registerEvent(actualPlayer, "BattleRoyaleHealthChange")
actualPlayer:sendTextMessage(MESSAGE_STATUS_WARNING, "Beware of fire. Island will start burning in 2 minutes!")
end
addEvent(spawnFire, FIRE_SPAWN_TIME, 0, 1494)
end
-- after player death
function BattleRoyale:playerDied(deadPlayer)
self:returnPlayerStats(deadPlayer)
deadPlayer:removeAllConditions()
local actualPlayersCount = #self.players
self:removePlayer(deadPlayer)
deadPlayer:addItem(1988, 1, INDEX_WHEREEVER, 0)
if actualPlayersCount ~= 1 then
rewardPlayer(deadPlayer, totalPlayerCount, actualPlayersCount, self.goldPool)
end
return true
end
-- return stats for player
function BattleRoyale:returnPlayerStats(player)
unregisterEvent(player, "BattleRoyaleDeath")
unregisterEvent(player, "BattleRoyaleHealthChange")
local playerID = player:getName()
setPlayerStatsBack(player, brPlayersStats[playerID])
print(player:getName() .. " stats returned")
--brPlayersStats[playerID] = nil
giveBlessing(player)
player:setBattleRoyalePlayer(false);
player:save()
end
-- reward winner
function BattleRoyale:rewardWinner()
local player = self.players[1]
if player ~= nil then
print(player:getName() .. " won battle royale ")
moveItemsToPosition(player)
broadcastMessage("Player " .. player:getName() .. " won battle royale! Congratulations!", MESSAGE_STATUS_CONSOLE_BLUE)
self:returnPlayerStats(player)
local message = "You have earned " .. tostring(self.goldPool) .. " gold. Check your bank balance\n"
local bankBalance = player:getBankBalance()
bankBalance = bankBalance + self.goldPool
player:setBankBalance(bankBalance)
local playerId = player:getGuid()
addPremiumPointsForPlayer(playerId, 150)
message = message .. "Outstanding, you have earned yourself 150 tibia coins and 24 hours of 50% bonus experience.\n" .. thanks
player:sendTextMessage(MESSAGE_INFO_DESCR, message)
player:removeAllConditions()
teleportToTemple(player)
player:setSkillLoss(true)
giveBonusExp(player, 24)
player:addItem(1988, 1, false, 1, CONST_SLOT_WHEREEVER)
player:save()
db.asyncQuery("UPDATE `battle_royale_scores` SET `wins` = `wins` + 1 WHERE `player_id` = " .. db.escapeString(playerId))
self:reset()
end
end
-- reset br state
function BattleRoyale:reset()
-- cleanBattleRoyaleMap()
self.isBattle = false
brPlayersStats = {}
brGame = nil
totalPlayerCount = 0
brGame = BattleRoyale:new(nil, {}, false, false, 1000000)
end
-- adds player
function BattleRoyale:addPlayer(player)
if self.canRegister then
if self:alreadyRegistered(player) then
player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already signend for battle royale")
return
end
table.insert(self.players, player)
player:sendTextMessage(MESSAGE_INFO_DESCR, "You just signed up for battle royale. \n Remember that you can unregister from battle royale with !royale unregister until battle has not started.")
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "Signing up for battle royale is not open yet.")
end
end
-- remove player
function BattleRoyale:removePlayer(player)
local removedPlayerName = player:getName()
for i = 1, #self.players do
if self.players[i]:getName() == removedPlayerName then
table.remove(self.players, i)
return true
end
end
return false
end
-- checks if player is already registered
function BattleRoyale:alreadyRegistered(player)
local playerName = player:getName()
for _, p in ipairs(self.players) do
if p:getName() == playerName then
return true
end
end
return false
end
-- allows register
function BattleRoyale:startRegister()
self.canRegister = true
broadcastMessage("Signing up for Battle Royale just started! \nSign up with !royale command", MESSAGE_STATUS_CONSOLE_BLUE)
end
-- closes register
function BattleRoyale:closeRegister()
self.canRegister = false
end
Part two in next post
Post automatically merged:
data/scripts/lib/royale_utils.lua
royale_utils.lua
Talkaction
data/scripts/talkactions/royale-register.lua
Lua:
local royaleJoin = TalkAction("!royale")
function royaleJoin.onSay(player, words, param)
if player:getGroup():getAccess() or player:getAccountType() >= ACCOUNT_TYPE_TUTOR then
player:sendCancelMessage("Tutors and Gamemasters can not join battle royale")
return true
end
if brGame.isBattle then
player:sendCancelMessage("There is ongoing Battle Royale game. You should try tomorrow.")
return false
end
brGame:addPlayer(player)
return false
end
royaleJoin:separator(",")
royaleJoin:register()
local royaleUnregister = TalkAction("!royale unregister")
function royaleUnregister.onSay(player, words, param)
if not brGame.canRegister and not brGame.isBattle then
player:sendCancelMessage("Signing up for battle royale is not open yet so you can not unregister.")
return false
end
local alreadyRegistered = brGame:alreadyRegistered(player)
if br.canRegister and not brGame.isBattle and alreadyRegistered then
brGame:removePlayer(player)
player:sendTextMessage(MESSAGE_INFO_DESCR, "You just unregistered from battle royale.")
return false
end
if not alreadyRegistered and br.canRegister and not brGame.isBattle then
player:sendCancelMessage("You have not registered yet.")
return false
end
if brGame.isBattle and alreadyRegistered then
player:sendCancelMessage("You cannot unregister from ongoing battle.")
return false
end
return true
end
royaleUnregister:separator(" ")
royaleUnregister:register()
if brGame.canRegister and not brGame.isBattle then
brGame:removePlayer(player)
end
local startBR = TalkAction("!reg")
function startBR.onSay(player, words, param)
if not player:getGroup():getAccess() or player:getAccountType() < ACCOUNT_TYPE_GOD then
return true
end
brGame:startRegister()
return false
end
startBR:separator(" ")
startBR:register()
local beginBR = TalkAction("!start")
function beginBR.onSay(player, words, param)
if not player:getGroup():getAccess() or player:getAccountType() < ACCOUNT_TYPE_GOD then
return true
end
brGame:begin()
return false
end
beginBR:separator(" ")
beginBR:register()
local resetBR = TalkAction("!clean")
function resetBR.onSay(player, words, param)
if not player:getGroup():getAccess() or player:getAccountType() < ACCOUNT_TYPE_GOD then
return true
end
cleanBattleRoyaleMap()
brGame:reset()
return false
end
resetBR:separator(" ")
resetBR:register()
SQL schema
In
players
table add`bonusexp` bigint(20) UNSIGNED DEFAULT '0',
And add those two tables
SQL:
--
-- Table structure `battle_royale_scores`
--
CREATE TABLE IF NOT EXISTS `battle_royale_scores` (
`player_id` int(11) NOT NULL,
`wins` smallint(5) DEFAULT '0',
INDEX `player_id` (`player_id`),
CONSTRAINT `battle_royale_scores_fk`
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure `battle_royale_reward_msg`
--
CREATE TABLE IF NOT EXISTS `battle_royale_reward_msg` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`player_id` int(11) NOT NULL,
`message` varchar(512) NOT NULL,
`message_type` tinyint(2) NOT NULL,
`unreaded` tinyint(1) NOT NULL DEFAULT '1',
INDEX `player_id` (`player_id`),
CONSTRAINT `battle_royale_reward_msg_fk`
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`)
ON DELETE CASCADE,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
C++
In
iologindata.cpp
Add
bonusexp
to save and load player queryafter
player->healthMax = result->getNumber<int32_t>("healthmax");
add
player->bonusExpTime = result->getNumber<int32_t>("bonusexp");
after
query << "`bonus_rerolls` = " << player->getPreyBonusRerolls() << ',';
add
query << "`bonusexp` = " << static_cast<uint64_t>(player->getBonusExpTime()) << ",";
luascript.cpp
add somewhere in player methods
C++:
registerMethod("Player", "setMana", LuaScriptInterface::luaPlayerSetMana);
registerMethod("Player", "setBaseMagicLevel", LuaScriptInterface::luaPlayerSetBaseMagicLevel);
registerMethod("Player", "removeAllConditions", LuaScriptInterface::luaPlayerRemoveAllConditions);
registerMethod("Player", "setSkillValues", LuaScriptInterface::luaPlayerSetSkillValues);
registerMethod("Player", "resetSkills", LuaScriptInterface::luaPlayerResetSkills);
registerMethod("Player", "removeUnjustifiedKill", LuaScriptInterface::luaPlayerRemoveUnjustifiedKill);
registerMethod("Player", "setBattleRoyalePlayer", LuaScriptInterface::luaPlayerSetBattleRoyalePlayer);
registerMethod("Player", "setManaSpent", LuaScriptInterface::luaPlayerSetManaSpent);
registerMethod("Player", "setBonusExp", LuaScriptInterface::luaPlayerSetBonusExp);
add implementations
C++:
int LuaScriptInterface::luaPlayerSetMana(lua_State* L)
{
// player:setMana(maxMana)
Player* player = getPlayer(L, 1);
if (player) {
player->mana = getNumber<int32_t>(L, 2);
player->sendStats();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerSetBaseMagicLevel(lua_State* L)
{
// player:addSkillTries(skillType, tries)
Player* player = getUserdata<Player>(L, 1);
uint32_t baseMagLevel = getNumber<uint32_t>(L, 2);
if (player && baseMagLevel >= 0) {
player->magLevel = baseMagLevel;
player->sendSkills();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerRemoveAllConditions(lua_State* L)
{
// player:removeAllConditions()
Player* player = getUserdata<Player>(L, 1);
if (player) {
player->removeAllConditions();
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerSetSkillValues(lua_State* L)
{
// player:setSkillValues()
Player* player = getUserdata<Player>(L, 1);
if (player) {
uint16_t skill = getNumber<uint16_t>(L, 2);
uint16_t skillLevel = getNumber<uint16_t>(L, 3);
uint16_t skillPercent = getNumber<uint16_t>(L, 4);
uint16_t skillTries = getNumber<uint16_t>(L, 5);
player->setSkillValues(skill, skillLevel, skillPercent, skillTries);
player->sendSkills();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerResetSkills(lua_State* L)
{
// player:resetSkills()
Player* player = getUserdata<Player>(L, 1);
if (player) {
player->resetSkills();
player->sendStats();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerRemoveUnjustifiedKill(lua_State* L)
{
// player:removeUnjustifiedKill()
Player* killer = getUserdata<Player>(L, 1);
uint32_t targetID = getNumber<uint32_t>(L, 2);
if (killer && targetID > 0) {
killer->removeUnjustifiedKill(targetID);
killer->sendStats();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerSetBattleRoyalePlayer(lua_State* L)
{
// player:setBattleRoyalePlayer(true/false)
Player* player = getUserdata<Player>(L, 1);
if (player) {
player->isBattleRoyalePlayer = getBoolean(L, 2);
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerSetManaSpent(lua_State* L)
{
// player:setManaSpent(int val)
Player* player = getUserdata<Player>(L, 1);
uint64_t newManaSpent = getNumber<uint64_t>(L, 2);
if (player && newManaSpent >= 0) {
player->manaSpent = newManaSpent;
player->sendSkills();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerSetBonusExp(lua_State* L)
{
// player:setBaseXpGain(value)
Player* player = getUserdata<Player>(L, 1);
if (player) {
player->setBonusExpTime(getNumber<uint64_t>(L, 2));
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
luascript.h
C++:
static int luaPlayerSetMana(lua_State* L);
static int luaPlayerSetBaseMagicLevel(lua_State* L);
static int luaPlayerRemoveAllConditions(lua_State* L);
static int luaPlayerSetSkillValues(lua_State* L);
static int luaPlayerResetSkills(lua_State* L);
static int luaPlayerRemoveUnjustifiedKill(lua_State* L);
static int luaPlayerSetBattleRoyalePlayer(lua_State* L);
static int luaPlayerSetManaSpent(lua_State* L);
static int luaPlayerSetBonusExp(lua_State* L);
Part three in next post
Post automatically merged:
player.cpp
find
if (targetPlayer->getSkull() == SKULL_NONE && getSkull() == SKULL_NONE && !targetPlayer->hasKilled(this)) {
change to
if (targetPlayer->getSkull() == SKULL_NONE && getSkull() == SKULL_NONE && !targetPlayer->hasKilled(this) && !isBattleRoyalePlayer) {
find (this can be found in two places, apply changes in both)
C++:
uint8_t monthKills = 0;
for (const auto& kill : unjustifiedKills) {
right after for loop add
C++:
if (!kill.unavenged) {
continue;
}
before
addExperience(source, gainExp, true);
add
C++:
if (bonusExpTime >= time(nullptr)) {
gainExp = gainExp + (gainExp * 0.5);
}
at the end add
C++:
void Player::removeAllConditions()
{
for (Condition* condition : conditions) {
if (hasCondition(condition->getType(), condition->getSubId())) {
removeCondition(condition->getType(), true);
}
}
}
void Player::setSkillValues(uint16_t skill, uint16_t skillLevel, uint16_t skillPercent, uint16_t skillTries) {
skills[skill].level = skillLevel;
skills[skill].percent = skillPercent;
skills[skill].tries = skillTries;
}
void Player::resetSkills() {
for (uint16_t skill = SKILL_FIST; skill <= SKILL_FISHING; skill++) {
setSkillValues(skill, 10, 0, 0);
}
}
void Player::setBonusExpTime(uint64_t bonusExpTime) {
if (this->bonusExpTime > time(nullptr))
{
this->bonusExpTime += bonusExpTime;
}
else {
this->bonusExpTime = time(nullptr) + bonusExpTime;
}
}
uint64_t Player::getBonusExpTime() {
return bonusExpTime;
}
void Player::removeUnjustifiedKill(uint32_t killID) {
for (auto& kill : unjustifiedKills) {
if (kill.target == killID && kill.unavenged) {
kill.unavenged = false;
break;
}
}
sendUnjustifiedPoints();
}
player.h
add
C++:
void removeAllConditions();
void setSkillValues(uint16_t skill, uint16_t skillLevel, uint16_t skillPercent, uint16_t skillTries);
void resetSkills();
void setBonusExpTime(uint64_t bonusExpTime);
uint64_t getBonusExpTime();
void removeUnjustifiedKill(uint32_t killID);
time_t bonusExpTime = 0;
bool isBattleRoyalePlayer = false;
Disclaimer
Lua function player:removeAllConditions() defined in luascript.cpp was working fine in windows, but in ubuntu was causing server crash. Instead you might try global function removeAllConditions(player).
Things that I wanted to do, but don't have time:
- number of chests spawned depends on number of players taking part in event,
- speed of fire filling area depends on number of players taking part in event,
- move player's original items after his death to owner.
If you have any questions I will try to answer and if it is too much garbage just remove thread.
Also some custom runes and items like monster summoner rune can be found on github.
Cheers :*
Last edited: