Jump to content

elitehox

Member
  • Content Count

    15
  • Joined

  • Last visited

  1. baixei e compilei do github do s3kk. https://github.com/s3kk/tfs04 Não aparece nenhum erro na distro. Simplismente ele conta 1 morte como duas pra a guild que invitou pra war. eu nao consigo achar o arquivo da função que registra na tabela guild_wars. acredito que o problema está no registro nessa tabela, na coluna guild_kills, o enemy_kills ta registrando direito. Se eu conseguisse achar o arquivo que registra as mortes na tabela eu conseguiria comparar a função de registro no guild_kills (que registrado errado) com a enemy_kills (que ta registrando corretamente) acredito que o problema esta na src da distro no arquivo ioguild.cpp. ioguild.cpp //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include "ioguild.h" #include "database.h" #include "player.h" #include "configmanager.h" #include "game.h" #include "chat.h" extern Chat g_chat; extern Game g_game; extern ConfigManager g_config; bool IOGuild::getGuildId(uint32_t& id, const std::string& name) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guilds` WHERE `name` " << db->getStringComparer() << db->escapeString(name) << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; id = result->getDataInt("id"); result->free(); return true; } bool IOGuild::getGuildById(std::string& name, uint32_t id) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `name` FROM `guilds` WHERE `id` = " << id << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; name = result->getDataString("name"); result->free(); return true; } bool IOGuild::swapGuildIdToOwner(uint32_t& value) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `ownerid` FROM `guilds` WHERE `id` = " << value << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; value = result->getDataInt("ownerid"); result->free(); return true; } bool IOGuild::guildExists(uint32_t guild) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guilds` WHERE `id` = " << guild << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; result->free(); return true; } uint32_t IOGuild::getRankIdByName(uint32_t guild, const std::string& name) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guild_ranks` WHERE `guild_id` = " << guild << " AND `name` " << db->getStringComparer() << db->escapeString(name) << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return 0; const uint32_t id = result->getDataInt("id"); result->free(); return id; } uint32_t IOGuild::getRankIdByLevel(uint32_t guild, GuildLevel_t level) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guild_ranks` WHERE `guild_id` = " << guild << " AND `level` = " << level << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return 0; const uint32_t id = result->getDataInt("id"); result->free(); return id; } bool IOGuild::getRankEx(uint32_t& id, std::string& name, uint32_t guild, GuildLevel_t level) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id`, `name` FROM `guild_ranks` WHERE `guild_id` = " << guild << " AND `level` = " << level; if(id) query << " AND `id` = " << id; query << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; name = result->getDataString("name"); if(!id) id = result->getDataInt("id"); result->free(); return true; } std::string IOGuild::getRank(uint32_t guid) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `guild_ranks`.`name` FROM `players`, `guild_ranks` WHERE `players`.`id` = " << guid << " AND `guild_ranks`.`id` = `players`.`rank_id` LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return ""; const std::string name = result->getDataString("name"); result->free(); return name; } bool IOGuild::changeRank(uint32_t guild, const std::string& oldName, const std::string& newName) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guild_ranks` WHERE `guild_id` = " << guild << " AND `name` " << db->getStringComparer() << db->escapeString(oldName) << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; const uint32_t id = result->getDataInt("id"); result->free(); query.str(""); query << "UPDATE `guild_ranks` SET `name` = " << db->escapeString(newName) << " WHERE `id` = " << id << db->getUpdateLimiter(); if(!db->query(query.str())) return false; for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it) { if(it->second->getRankId() == id) it->second->setRankName(newName); } return true; } bool IOGuild::createGuild(Player* player) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "INSERT INTO `guilds` (`id`, `world_id`, `name`, `ownerid`, `creationdata`, `motd`) VALUES (NULL, " << g_config.getNumber(ConfigManager::WORLD_ID) << ", " << db->escapeString(player->getGuildName()) << ", " << player->getGUID() << ", " << time(NULL) << ", 'Your guild has been successfully created, to view all available commands type: !commands. If you would like to remove this message use !cleanmotd and to set new motd use !setmotd text.')"; if(!db->query(query.str())) return false; query.str(""); query << "SELECT `id` FROM `guilds` WHERE `ownerid` = " << player->getGUID() << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; const uint32_t guildId = result->getDataInt("id"); result->free(); return joinGuild(player, guildId, true); } bool IOGuild::joinGuild(Player* player, uint32_t guildId, bool creation/* = false*/) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guild_ranks` WHERE `guild_id` = " << guildId << " AND `level` = " << (creation ? "3" : "1") << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; const uint32_t rankId = result->getDataInt("id"); result->free(); std::string guildName; if(!creation) { query.str(""); query << "SELECT `name` FROM `guilds` WHERE `id` = " << guildId << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; guildName = result->getDataString("name"); result->free(); } query.str(""); query << "UPDATE `players` SET `rank_id` = " << rankId << " WHERE `id` = " << player->getGUID() << db->getUpdateLimiter(); if(!db->query(query.str())) return false; player->setGuildId(guildId); GuildLevel_t level = GUILDLEVEL_MEMBER; if(!creation) player->setGuildName(guildName); else level = GUILDLEVEL_LEADER; player->setGuildLevel(level, rankId); player->invitedToGuildsList.clear(); return true; } bool IOGuild::disbandGuild(uint32_t guildId) { Database* db = Database::getInstance(); DBQuery query; query << "UPDATE `players` SET `rank_id` = '' AND `guildnick` = '' WHERE `rank_id` = " << getRankIdByLevel(guildId, GUILDLEVEL_LEADER) << " OR rank_id = " << getRankIdByLevel(guildId, GUILDLEVEL_VICE) << " OR rank_id = " << getRankIdByLevel(guildId, GUILDLEVEL_MEMBER); if(!db->query(query.str())) return false; InvitedToGuildsList::iterator iit; for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it) { if(it->second->getGuildId() == guildId) it->second->leaveGuild(); else { iit = std::find(it->second->invitedToGuildsList.begin(), it->second->invitedToGuildsList.end(), guildId); if(iit != it->second->invitedToGuildsList.end()) it->second->invitedToGuildsList.erase(iit); } } query.str(""); query << "DELETE FROM `guilds` WHERE `id` = " << guildId << db->getUpdateLimiter(); if(!db->query(query.str())) return false; query.str(""); query << "DELETE FROM `guild_invites` WHERE `guild_id` = " << guildId; if(!db->query(query.str())) return false; query.str(""); query << "DELETE FROM `guild_ranks` WHERE `guild_id` = " << guildId; return db->query(query.str()); } bool IOGuild::hasGuild(uint32_t guid) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `rank_id` FROM `players` WHERE `id` = " << guid << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; const bool ret = result->getDataInt("rank_id") != 0; result->free(); return ret; } bool IOGuild::isInvited(uint32_t guild, uint32_t guid) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `guild_id` FROM `guild_invites` WHERE `player_id` = " << guid << " AND `guild_id`= " << guild << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; result->free(); return true; } bool IOGuild::invitePlayer(uint32_t guild, uint32_t guid) { Database* db = Database::getInstance(); DBQuery query; query << "INSERT INTO `guild_invites` (`player_id`, `guild_id`) VALUES ('" << guid << "', '" << guild << "')"; return db->query(query.str()); } bool IOGuild::revokeInvite(uint32_t guild, uint32_t guid) { Database* db = Database::getInstance(); DBQuery query; query << "DELETE FROM `guild_invites` WHERE `player_id` = " << guid << " AND `guild_id` = " << guild; return db->query(query.str()); } uint32_t IOGuild::getGuildId(uint32_t guid) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `guild_ranks`.`guild_id` FROM `players`, `guild_ranks` WHERE `players`.`id` = " << guid << " AND `guild_ranks`.`id` = `players`.`rank_id` LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return 0; const uint32_t guildId = result->getDataInt("guild_id"); result->free(); return guildId; } GuildLevel_t IOGuild::getGuildLevel(uint32_t guid) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `guild_ranks`.`level` FROM `players`, `guild_ranks` WHERE `players`.`id` = " << guid << " AND `guild_ranks`.`id` = `players`.`rank_id` LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return GUILDLEVEL_NONE; const GuildLevel_t level = (GuildLevel_t)result->getDataInt("level"); result->free(); return level; } bool IOGuild::setGuildLevel(uint32_t guid, GuildLevel_t level) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `id` FROM `guild_ranks` WHERE `guild_id` = " << getGuildId(guid) << " AND `level` = " << level << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return false; query.str(""); query << "UPDATE `players` SET `rank_id` = " << result->getDataInt("id") << " WHERE `id` = " << guid << db->getUpdateLimiter(); result->free(); return db->query(query.str()); } bool IOGuild::updateOwnerId(uint32_t guild, uint32_t guid) { Database* db = Database::getInstance(); DBQuery query; query << "UPDATE `guilds` SET `ownerid` = " << guid << " WHERE `id` = " << guild << db->getUpdateLimiter(); return db->query(query.str()); } bool IOGuild::setGuildNick(uint32_t guid, const std::string& nick) { Database* db = Database::getInstance(); DBQuery query; query << "UPDATE `players` SET `guildnick` = " << db->escapeString(nick) << " WHERE `id` = " << guid << db->getUpdateLimiter(); return db->query(query.str()); } bool IOGuild::setMotd(uint32_t guild, const std::string& newMessage) { Database* db = Database::getInstance(); DBQuery query; query << "UPDATE `guilds` SET `motd` = " << db->escapeString(newMessage) << " WHERE `id` = " << guild << db->getUpdateLimiter(); return db->query(query.str()); } std::string IOGuild::getMotd(uint32_t guild) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `motd` FROM `guilds` WHERE `id` = " << guild << " LIMIT 1"; if(!(result = db->storeQuery(query.str()))) return ""; const std::string motd = result->getDataString("motd"); result->free(); return motd; } bool IOGuild::war(War_t& enemy) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `g`.`name` AS `guild_name`, `e`.`name` AS `enemy_name`, `w`.* FROM `guild_wars` w INNER JOIN `guilds` g ON `w`.`guild_id` = `g`.`id` INNER JOIN `guilds` e ON `w`.`enemy_id` = `e`.`id` WHERE `w`.`id` = " << enemy.war; if(!(result = db->storeQuery(query.str()))) return false; enemy.ids[WAR_GUILD] = result->getDataInt("guild_id"); enemy.ids[WAR_ENEMY] = result->getDataInt("enemy_id"); enemy.names[WAR_GUILD] = result->getDataString("guild_name"); enemy.names[WAR_ENEMY] = result->getDataString("enemy_name"); enemy.frags[WAR_GUILD] = result->getDataInt("guild_kills"); enemy.frags[WAR_ENEMY] = result->getDataInt("enemy_kills"); enemy.frags[enemy.type]++; enemy.limit = result->getDataInt("frags"); enemy.end = result->getDataInt("end"); enemy.status = result->getDataInt("status"); enemy.payment = result->getDataInt("payment"); result->free(); if(enemy.frags[WAR_GUILD] < enemy.limit && enemy.frags[WAR_ENEMY] < enemy.limit && (enemy.status != 1 || !enemy.end || enemy.end > time(NULL))) { query.str(""); query << "UPDATE `guild_wars` SET `guild_kills` = " << enemy.frags[WAR_GUILD] << ", `enemy_kills` = " << enemy.frags[WAR_ENEMY] << " WHERE `id` = " << enemy.war; return db->query(query.str()); } query.str(""); query << "UPDATE `guilds` SET `balance` = `balance` + " << (enemy.payment * 2) << " WHERE `id` = " << enemy.ids[enemy.type]; if(!db->query(query.str())) return false; query.str(""); query << "UPDATE `guild_wars` SET `guild_kills` = " << enemy.frags[WAR_GUILD] << ", `enemy_kills` = " << enemy.frags[WAR_ENEMY] << ", `end` = " << time(NULL) << ", `status` = 5 WHERE `id` = " << enemy.war; if(!db->query(query.str())) return false; for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it) { if(it->second->isRemoved()) continue; bool update = false; if(it->second->getGuildId() == enemy.ids[WAR_GUILD]) { it->second->removeEnemy(enemy.ids[WAR_ENEMY]); update = true; } else if(it->second->getGuildId() == enemy.ids[WAR_ENEMY]) { it->second->removeEnemy(enemy.ids[WAR_GUILD]); update = true; } if(update) g_game.updateCreatureEmblem(it->second); } std::stringstream s; s << enemy.names[enemy.type] << " has just won the war against " << enemy.names[enemy.type == WAR_GUILD] << "."; return g_game.broadcastMessage(s.str().c_str(), MSG_EVENT_ADVANCE); } void IOGuild::frag(Player* player, uint64_t deathId, const DeathList& list) { Database* db = Database::getInstance(); War_t war; std::stringstream s; for(DeathList::const_iterator it = list.begin(); it != list.end(); ) { if(it->isLast()) war = it->getWar(); Creature* creature = it->getKillerCreature(); if(it != list.begin()) { ++it; if(it == list.end()) s << " and "; else s << ", "; } else ++it; s << creature->getName(); } std::string killers = s.str(); s.str(""); ChatChannel* channel = NULL; if((channel = g_chat.getChannel(player, CHANNEL_GUILD))) { s << "Guild member " << player->getName() << " was killed by " << killers << ". The new score is " << war.frags[ war.type == WAR_GUILD] << ":" << war.frags[war.type] << " frags (limit " << war.limit << ")."; channel->talk("", SPEAK_CHANNEL_RA, s.str()); } s.str(""); if((channel = g_chat.getChannel(list[0].getKillerCreature()->getPlayer(), CHANNEL_GUILD))) { s << "Opponent " << player->getName() << " was killed by " << killers << ". The new score is " << war.frags[ war.type] << ":" << war.frags[war.type == WAR_GUILD] << " frags (limit " << war.limit << ")."; channel->talk("", SPEAK_CHANNEL_RA, s.str()); } DBQuery query; query << "INSERT INTO `guild_kills` (`guild_id`, `war_id`, `death_id`) VALUES (" << war.ids[war.type] << ", " << war.war << ", " << deathId << ");"; db->query(query.str()); }
  2. pensei que havia citado, mas nao, desculpe. é o TFS0.4
  3. Boa noite pessoal, o placar do war system está com um pequeno problema no placar. O lado da guild que invitou para war cada morte esta sendo registrada como duas. Acredito que seja a função de registrar no banco de dados pois no banco de dados conforme mostra no print, esta realmente registrando com o valor que esta mostrando no placar do site, então não é problema do site. Se alguem puder ajudar agradeço exemplo de placar. O vermelho (da guild que invita) foi 6 mortes e está mostrando 12. O verde está correto, abaixo o registro do banco de dados, tabela guild_wars wars.lua function onSay(cid, words, param, channel) local guild = getPlayerGuildId(cid) if(not guild or getPlayerGuildLevel(cid) < GUILDLEVEL_LEADER) then doPlayerSendChannelMessage(cid, "", "You cannot execute this talkaction.", TALKTYPE_CHANNEL_W, 0) return true end local t = string.explode(param, ",") if(not t[2]) then doPlayerSendChannelMessage(cid, "", "Not enough param(s).", TALKTYPE_CHANNEL_W, 0) return true end local enemy = getGuildId(t[2]) if(not enemy) then doPlayerSendChannelMessage(cid, "", "Guild \"" .. t[2] .. "\" does not exists.", TALKTYPE_CHANNEL_W, 0) return true end if(enemy == guild) then doPlayerSendChannelMessage(cid, "", "You cannot perform war action on your own guild.", TALKTYPE_CHANNEL_W, 0) return true end local enemyName, tmp = "", db.getResult("SELECT `name` FROM `guilds` WHERE `id` = " .. enemy) if(tmp:getID() ~= -1) then enemyName = tmp:getDataString("name") tmp:free() end if(isInArray({"accept", "reject", "cancel"}, t[1])) then local query = "`guild_id` = " .. enemy .. " AND `enemy_id` = " .. guild if(t[1] == "cancel") then query = "`guild_id` = " .. guild .. " AND `enemy_id` = " .. enemy end tmp = db.getResult("SELECT `id`, `begin`, `end`, `payment` FROM `guild_wars` WHERE " .. query .. " AND `status` = 0") if(tmp:getID() == -1) then doPlayerSendChannelMessage(cid, "", "Currently there's no pending invitation for a war with " .. enemyName .. ".", TALKTYPE_CHANNEL_W, 0) return true end if(t[1] == "accept") then local _tmp = db.getResult("SELECT `balance` FROM `guilds` WHERE `id` = " .. guild) local state = _tmp:getID() < 0 or _tmp:getDataInt("balance") < tmp:getDataInt("payment") _tmp:free() if(state) then doPlayerSendChannelMessage(cid, "", "Your guild balance is too low to accept this invitation.", TALKTYPE_CHANNEL_W, 0) return true end db.executeQuery("UPDATE `guilds` SET `balance` = `balance` - " .. tmp:getDataInt("payment") .. " WHERE `id` = " .. guild) end query = "UPDATE `guild_wars` SET " local msg = "accepted " .. enemyName .. " invitation to war." if(t[1] == "reject") then query = query .. "`end` = " .. os.time() .. ", `status` = 2" msg = "rejected " .. enemyName .. " invitation to war." elseif(t[1] == "cancel") then query = query .. "`end` = " .. os.time() .. ", `status` = 3" msg = "canceled invitation to a war with " .. enemyName .. "." else query = query .. "`begin` = " .. os.time() .. ", `end` = " .. (tmp:getDataInt("end") > 0 and (os.time() + ((tmp:getDataInt("begin") - tmp:getDataInt("end")) / 86400)) or 0) .. ", `status` = 1" end query = query .. " WHERE `id` = " .. tmp:getDataInt("id") if(t[1] == "accept") then doGuildAddEnemy(guild, enemy, tmp:getDataInt("id"), WAR_GUILD) doGuildAddEnemy(enemy, guild, tmp:getDataInt("id"), WAR_ENEMY) end tmp:free() db.executeQuery(query) doBroadcastMessage(getPlayerGuildName(cid) .. " has " .. msg, MESSAGE_EVENT_ADVANCE) return true end if(t[1] == "invite") then local str = "" tmp = db.getResult("SELECT `guild_id`, `status` FROM `guild_wars` WHERE `guild_id` IN (" .. guild .. "," .. enemy .. ") AND `enemy_id` IN (" .. enemy .. "," .. guild .. ") AND `status` IN (0, 1)") if(tmp:getID() ~= -1) then if(tmp:getDataInt("status") == 0) then if(tmp:getDataInt("guild_id") == guild) then str = "You have already invited " .. enemyName .. " to war." else str = enemyName .. " have already invited you to war." end else str = "You are already on a war with " .. enemyName .. "." end tmp:free() end if(str ~= "") then doPlayerSendChannelMessage(cid, "", str, TALKTYPE_CHANNEL_W, 0) return true end local frags = tonumber(t[3]) if(frags ~= nil) then frags = math.max(10, math.min(1000, frags)) else frags = 100 end local payment = tonumber(t[4]) if(payment ~= nil) then payment = math.max(100000, math.min(1000000000, payment)) tmp = db.getResult("SELECT `balance` FROM `guilds` WHERE `id` = " .. guild) local state = tmp:getID() < 0 or tmp:getDataInt("balance") < payment tmp:free() if(state) then doPlayerSendChannelMessage(cid, "", "Your guild balance is too low for such payment.", TALKTYPE_CHANNEL_W, 0) return true end db.executeQuery("UPDATE `guilds` SET `balance` = `balance` - " .. payment .. " WHERE `id` = " .. guild) else payment = 0 end local begining, ending = os.time(), tonumber(t[5]) if(ending ~= nil and ending ~= 0) then ending = begining + (ending * 86400) else ending = 0 end db.executeQuery("INSERT INTO `guild_wars` (`guild_id`, `enemy_id`, `begin`, `end`, `frags`, `payment`) VALUES (" .. guild .. ", " .. enemy .. ", " .. begining .. ", " .. ending .. ", " .. frags .. ", " .. payment .. ");") doBroadcastMessage(getPlayerGuildName(cid) .. " has invited " .. enemyName .. " to war till " .. frags .. " frags.", MESSAGE_EVENT_ADVANCE) return true end if(not isInArray({"end", "finish"}, t[1])) then return false end local status = (t[1] == "end" and 1 or 4) tmp = db.getResult("SELECT `id` FROM `guild_wars` WHERE `guild_id` = " .. guild .. " AND `enemy_id` = " .. enemy .. " AND `status` = " .. status) if(tmp:getID() ~= -1) then local query = "UPDATE `guild_wars` SET `end` = " .. os.time() .. ", `status` = 5 WHERE `id` = " .. tmp:getDataInt("id") tmp:free() doGuildRemoveEnemy(guild, enemy) doGuildRemoveEnemy(enemy, guild) db.executeQuery(query) doBroadcastMessage(getPlayerGuildName(cid) .. " has " .. (status == 4 and "mend fences" or "ended up a war") .. " with " .. enemyName .. ".", MESSAGE_EVENT_ADVANCE) return true end if(status == 4) then doPlayerSendChannelMessage(cid, "", "Currently there's no pending war truce from " .. enemyName .. ".", TALKTYPE_CHANNEL_W, 0) return true end tmp = db.getResult("SELECT `id`, `end` FROM `guild_wars` WHERE `guild_id` = " .. enemy .. " AND `enemy_id` = " .. guild .. " AND `status` = 1") if(tmp:getID() ~= -1) then if(tmp:getDataInt("end") > 0) then tmp:free() doPlayerSendChannelMessage(cid, "", "You cannot request ending for war with " .. enemyName .. ".", TALKTYPE_CHANNEL_W, 0) return true end local query = "UPDATE `guild_wars` SET `status` = 4, `end` = " .. os.time() .. " WHERE `id` = " .. tmp:getDataInt("id") tmp:free() db.executeQuery(query) doBroadcastMessage(getPlayerGuildName(cid) .. " has signed an armstice declaration on a war with " .. enemyName .. ".", MESSAGE_EVENT_ADVANCE) return true end doPlayerSendChannelMessage(cid, "", "Currently there's no active war with " .. enemyName .. ".", TALKTYPE_CHANNEL_W, 0) return true end
  4. nao sei qual era o bug.. talvez um conflito... acabei de excluir o teambattle.xml e resolveu o problema. segue abaixo o codigo do mod. <?xml version="1.0" encoding="UTF-8"?> <mod name="Team Event" version="2.0" author="Igor Pereira" contact="doriusot@gmail.com" enabled="yes"> <description> Full auto Team BattleEvent(v2.0) for 0.4 : 1- I currently rescripted this event from scratch again. 2- This version is much more better than the one before, it is more cleaner, clearer and with more options. 3- This version was tested on 0.4 latest one 4626, should work on lower rev too. 4- Removed the npc part it is now based on tp creation. 5- More silent boradcasting for in event progress and no spam, I hope! 6- you now get the options to show event stats on cancel msg area and (to / not to) show left players with names each x interval. 8- Team balancer have been added to only balance count in both teams. 9- Added a countdown option before fight starts. 10- Now starts on a defined time every day </description> <config name="teamSetting"><![CDATA[ --[[Local Config]]-- --//storages inBlue = 9900 inRed = 9901 joiner = 9907 blueKills = 9902 redKills = 9903 eventRecruiting = 9904 eventStarted = 9905 eventTime = 9906 itemToGet = 9908 countItemToGet = 9909 nextExecute = 9910 blueCount = 9911 redCount = 9912 --// Positions teleporterPosition = {x = 32341, y = 32213, z = 7} --Place where the event tp will be created waitRoomPlace = {x = 189, y = 132, z = 7} --Place of the waitnig room (the place ppl will wait for team to be full) waitRoomDimensions = { --Enter the start pos[top left sqm] and end pos[bottom right sqm] of waitnig room here startPos = {x = 179, y = 125, z = 7}, endPos = {x = 200, y = 139, z = 7} } eventPlaceDimensions = { --Enter the start pos[top left sqm] and end pos[bottom right sqm] of event place here startPos = {x = 151, y = 46, z = 7}, endPos = {x = 232, y = 100, z = 7} } blueTeamPos = {x = 216, y = 54, z = 7} redTeamPos = {x = 159, y = 86, z = 7} --// General settings recruitTime = 10 -- Time in minutes to gather players to event, will broadcast event started each min minimumPlayersJoins = 2 --If the number of layer joined is less than that then event would be cancelled balanceTeams = true -- This will balance number of players in both teams the extra player will be kicked out of event removeTeleportOnEventEnd = false -- if you want to remove the tp when the event finish set it to true, normally tp will just be diabled eventMaxTime = 10 -- Time in minutes, this is the max time event will be running. After checks are caried winner is declared showEventSats = true -- This is like a timer that is always there about event stats (time,oponents left, teammates left). It appears in the cancel messages place. sendLeftPlayers = true -- Well this will send to all alive players the names& numebr of the oponents left each interval defined down intervalToSendLeftPlayers = 11 -- interval(in seconds) to sendLeftPlayers , must be more than 10 sec countDownOnStart = true -- Well this occurs when players are teleported to their places in the arena , so if this is true it start to count down to the joined players then when count down finish they can start killing each other(event really begins) countDownFrom = 10 -- Starts count down from this number when event start, if above is set true minJoinLevel = 100 -- minimm lvl that can join event rewards = { --Example [%] = { {itemid/name, count} ,..........} count isnt more than 100 [65] = { {8304,1} , {"Double Exp 60 Minutes",1} }, [25] = { {"boots of haste",1} , {2195,1} }, [10] = { {"Crystal Coin",30} , {"crystal coin",30} } } --[[ Note : make sure if you edited % that sum should be equal to 100, you can add more % elements to suit your needs also more items if you want in each % [65],[25],[10] -> is the % of this item to be found the rest is clear ,items in each % and it will be chosen randomly]]-- ]]></config> <lib name="teamFunctions"><![CDATA[ domodlib('teamSetting') --[[Conditions don't touch]]-- local bmale = createConditionObject(CONDITION_OUTFIT) setConditionParam(bmale, CONDITION_PARAM_TICKS, -1) addOutfitCondition(bmale, {lookType = math.random(128,134), lookHead = 88, lookBody = 88, lookLegs = 88, lookFeet = 88, lookTypeEx = 0, lookAddons = 3}) local bfemale = createConditionObject(CONDITION_OUTFIT) setConditionParam(bfemale, CONDITION_PARAM_TICKS, -1) addOutfitCondition(bfemale, {lookType = math.random(136,142), lookHead = 88, lookBody = 88, lookLegs = 88, lookFeet = 88, lookTypeEx = 0, lookAddons = 3}) local rmale = createConditionObject(CONDITION_OUTFIT) setConditionParam(rmale, CONDITION_PARAM_TICKS, -1) addOutfitCondition(rmale, {lookType = math.random(128,134), lookHead = 94, lookBody = 94, lookLegs = 94, lookFeet = 94, lookTypeEx = 0, lookAddons = 3}) local rfemale = createConditionObject(CONDITION_OUTFIT) setConditionParam(rfemale, CONDITION_PARAM_TICKS, -1) addOutfitCondition(rfemale, {lookType = math.random(136,142),lookHead = 94, lookBody = 94, lookLegs = 94, lookFeet = 94, lookTypeEx = 0, lookAddons = 3}) local infight = createConditionObject(CONDITION_INFIGHT,-1) --[[Local Config]]-- --[[Functions]]-- -- General info function isFightOn() return getStorage(eventStarted) > 0 end function isRecruitOn() return getStorage(eventRecruiting) > 0 end function getMinJoinLevel() return minJoinLevel end function getJoiners() joiners = {} for _,cid in ipairs(getPlayersOnline()) do if isJoiner(cid) then if isInRecruitArea(cid) or isInFightArea(cid) then table.insert(joiners,cid) end end end return joiners end function getLeftMembersNames(team) str = "Oponents left("..#team..") :" left = "" for k,cid in ipairs(team) do left = (left ..""..(k == 1 and "" or ", ")..""..getCreatureName(cid).."["..getPlayerLevel(cid).."]" ) end str = str .." " .. (left == "" and "none" or left).. "." return str end function disPlayEventStats() if not showEventSats then return false end if getStorage(eventTime) - os.time() <= 0 then return false end left = os.date("%M:%S",(getStorage(eventTime) - os.time())) for _,cid in ipairs(getJoiners()) do oponentsLeft = isBlue(cid) and #getRedMembers() or #getBlueMembers() teamMatesLeft = isBlue(cid) and math.max(0,#getBlueMembers()-1) or math.max(0,#getRedMembers()-1) doPlayerSendCancel(cid,"Time left: ".. left.." || Oponents left: "..oponentsLeft.."/"..oponentCount(cid).." || Team-mates left: "..teamMatesLeft.."/".. math.max(0,matesCount(cid)-1)) end end function doSendLeftPlayers() if not sendLeftPlayers then return false end if intervalToSendLeftPlayers <= 10 then return false end for _,cid in ipairs(getJoiners()) do doPlayerSendTextMessage(cid,MESSAGE_TYPES["orange"],getLeftMembersNames(isRed(cid) and getBlueMembers() or getRedMembers())) end end function getBlueMembers() members = {} for _,cid in ipairs(getPlayersOnline()) do if isBlue(cid) then table.insert(members,cid) end end return members end function getRedMembers() members = {} for _,cid in ipairs(getPlayersOnline()) do if isRed(cid) then table.insert(members,cid) end end return members end -- starting fight function startRecruiting() doSetStorage(eventRecruiting,1) end function startEvent() doSetStorage(eventRecruiting,-1) if removeTeleportOnEventEnd then tp = getTileItemById(teleporterPosition,1387).uid if tp > 0 then doRemoveItem(tp) end end if not balanceTeams() then resetEvent() return false end for _,cid in ipairs(getBlueMembers()) do doTeleportThing(cid,blueTeamPos,false) doSendMagicEffect(getThingPos(cid),10) end setBlueCount(#getBlueMembers()) for _,cid in ipairs(getRedMembers()) do doTeleportThing(cid,redTeamPos,false) doSendMagicEffect(getThingPos(cid),10) end setRedCount(#getRedMembers()) startCountDown() return true end function setBlueCount(count) doSetStorage(blueCount,-1) doSetStorage(blueCount,count) end function oponentCount(cid) return isBlue(cid) and getStorage(redCount) or getStorage(blueCount) end function matesCount(cid) return isBlue(cid) and getStorage(blueCount) or getStorage(redCount) end function setRedCount(count) doSetStorage(redCount,-1) doSetStorage(redCount,count) end function balanceTeams() members = getJoiners() if #members < minimumPlayersJoins then doBroadcastMessage("Team-Battle event was cancelled as only ".. #members .. " players joined.") return false end if (math.mod(#members,2) ~= 0) then kicked = members[#members] clearTeamEventStorages(kicked) doPlayerSendTextMessage(kicked,MESSAGE_TYPES["info"],"Sorry, you have been kicked out of event for balancing both teams.") end count = 1 for _,cid in ipairs(getJoiners()) do if (math.mod(count,2) ~= 0) then addToBlue(cid) else addToRed(cid) end count = count + 1 end return true end function startCountDown() if(countDownOnStart) then for _,cid in ipairs(getJoiners()) do doCreatureSetNoMove(cid,true) for i = 0,countDownFrom do addEvent(doPlayerSendTextMessage,i*1000, cid, MESSAGE_TYPES["info"], (i == 0 and countDownFrom or countDownFrom-i) ) end end addEvent(startFight,(countDownFrom+1)*1000) else startFight() end end function startFight() doSetStorage(eventStarted,1) for _,cid in ipairs(getJoiners()) do doCreatureSetNoMove(cid,false) doPlayerSendTextMessage(cid,MESSAGE_TYPES["warning"],"Fight Starts!") end addEvent(endTeamEvent,eventMaxTime*60*1000,"maxTime") doSetStorage(eventTime,os.time()+eventMaxTime*60) end function teleportToWaitRoom(cid) doTeleportThing(cid,waitRoomPlace) doSendMagicEffect(waitRoomPlace,10) if getPlayerGroupId(cid) < 4 then addToJoiners(cid) end doPlayerSendTextMessage(cid,MESSAGE_TYPES["blue"],"Please be patient till the event starts and don't logout.") return true end -- Modifing teams & checking member states function isBlue(cid) return (getPlayerStorageValue(cid,inBlue) > 0) end function isRed(cid) return (getPlayerStorageValue(cid,inRed) > 0) end function isJoiner(cid) return (getPlayerStorageValue(cid,joiner) > 0) end function addToBlue(cid) setPlayerStorageValue(cid,inBlue,1) doAddCondition(cid, (getPlayerSex(cid) == 1) and bmale or bfemale) doAddCondition(cid,infight) end function addToRed(cid) setPlayerStorageValue(cid,inRed,1) doAddCondition(cid, (getPlayerSex(cid) == 1) and rmale or rfemale) doAddCondition(cid,infight) end function addToJoiners(cid) setPlayerStorageValue(cid,joiner,1) end function removeFromBlue(cid) setPlayerStorageValue(cid,inBlue,-1) end function removeFromRed(cid) setPlayerStorageValue(cid,inRed,-1) end function removeFromjoiners(cid) setPlayerStorageValue(cid,joiner,-1) end function isInRecruitArea(cid) return isInRange(getThingPos(cid),waitRoomDimensions.startPos,waitRoomDimensions.endPos) end function isInFightArea(cid) return isInRange(getThingPos(cid),eventPlaceDimensions.startPos,eventPlaceDimensions.endPos) end function clearTeamEventStorages(cid) if isInRecruitArea(cid) or isInFightArea(cid) then doTeleportThing(cid,getTownTemplePosition(getPlayerTown(cid))) doSendMagicEffect(getThingPos(cid),10) end if isFightOn() then if isJoiner(cid) then if isBlue(cid) then addRedKills() elseif isRed(cid) then addBlueKills() end doPlayerSendTextMessage(cid,MESSAGE_TYPES["orange"],"You have died in Team-Battle Event.") end end removeFromjoiners(cid) removeFromBlue(cid) removeFromRed(cid) doRemoveConditions(cid, false) end function haveUnrecivedReward(cid) return getPlayerStorageValue(cid,itemToGet) > 0 and getPlayerStorageValue(cid,countItemToGet) > 0 end function recieveLateReward(cid) if haveUnrecivedReward(cid) then if not doPlayerAddItem(cid,getPlayerStorageValue(cid,itemToGet),getPlayerStorageValue(cid,countItemToGet),false) then msg = "You need to free some space then relog to take your reward." doPlayerSendTextMessage(cid,MESSAGE_TYPES["warning"],msg) else setPlayerStorageValue(cid,itemToGet,-1) setPlayerStorageValue(cid,countItemToGet,-1) doPlayerSendTextMessage(cid,MESSAGE_TYPES["info"],"You have recieved your reward.") end end end -- Win or lose function thereIsAWinner() if redWon() or blueWon() then return true end return false end function blueWon() return( (#getBlueMembers() > 0 ) and ( #getRedMembers() == 0) ) end function redWon() return( (#getRedMembers() > 0) and (#getBlueMembers() == 0) ) end function isDraw() return #getBlueMembers() == #getRedMembers() end function getWinner() if #getBlueMembers() > #getRedMembers() then return {getBlueMembers(),getRedMembers(),"Blue team won."} elseif #getRedMembers() > #getBlueMembers() then return {getRedMembers(),getBlueMembers(),"Red team won."} else return { {},{},"it was a draw."} end end -- Adding kills function addBlueKills() doSetStorage(blueKills, math.max(1,getStorage(blueKills)+1)) end function addRedKills() doSetStorage(redKills, math.max(1,getStorage(redKills)+1)) end -- Ending event function endTeamEvent(type) if isFightOn() then doSetStorage(eventStarted,-1) doBroadcastMessage("Team-Battle event ended and "..getWinner()[3]) if not isDraw() then win(getWinner()[1],type) lose(getWinner()[2],type) else draw() end end addEvent(resetEvent,2 * 1000) --- tp player to home remove all storages and reset event global storages end function getPercent() rand= math.random(1,100) prev = 0 chosenItem = 0 for k, v in pairs(rewards) do if rand > prev and rand <= k+prev then chosenItem = k break else prev = k+prev end end return chosenItem end function generateReward(cid) percent = getPercent() if percent == 0 then print("Error in the reward item. Please inform Doggynub.") return true end randomizer = rewards[percent][math.random(1,#rewards[percent])] item = not tonumber(randomizer[1]) and getItemIdByName(randomizer[1]) or randomizer[1] count = isItemStackable(item) and math.min(randomizer[2],100) or 1 if item == nil or item == 0 then print("Error in the item format. Please inform Doggynub.") return true end msg = "You have won ".. (count == 1 and "a" or count) .." " .. getItemNameById(item) .. "" .. (count == 1 and "" or "s").."." if not doPlayerAddItem(cid,item,count,false) then msg = msg.. "You need to free some space then relog to take your reward." setPlayerStorageValue(cid,itemToGet,item) setPlayerStorageValue(cid,countItemToGet,count) end doPlayerSendTextMessage(cid,MESSAGE_TYPES["white"],msg) end function generateStatsMessage(cid, type, stats) msg = { ["KO"] = { ["win"] = "Event ended. Your team have won by killing all oponent's team members. You will recieve your reward shortly, check incoming messages.", ["lose"] = "Event ended. Your team have lost as the Oponent team killed all your team's members." }, ["maxTime"] = { ["win"] = "Event max-time finished and your team have won. You will recieve your reward shortly, check incoming messages.", ["lose"] = "Event max-time finished and your team have lost.", ["draw"] = "Event max-time finished and it is a draw.(no team won)" } } doPlayerSendTextMessage(cid,MESSAGE_TYPES["info"],msg[type][stats]) end function win(winners,type) for _,cid in ipairs(winners) do generateStatsMessage(cid, type, "win") generateReward(cid) end end function lose(losers,type) for _,cid in ipairs(losers) do generateStatsMessage(cid, type, "lose") end end function draw() for _,cid in ipairs(getJoiners()) do generateStatsMessage(cid, "maxTime", "draw") end end function resetEvent() doSetStorage(eventRecruiting,-1) doSetStorage(nextExecute,-1) doSetStorage(eventStarted,-1) doSetStorage(eventTime,-1) doSetStorage(blueKills,-1) doSetStorage(redKills,-1) for _,cid in ipairs(getPlayersOnline()) do if isBlue(cid) or isRed(cid) or isJoiner(cid) then clearTeamEventStorages(cid) end end end ]]></lib> <event type="login" name="teambattleLogin" event="script"><![CDATA[ domodlib('teamFunctions') function onLogin(cid) clearTeamEventStorages(cid) recieveLateReward(cid) registerCreatureEvent(cid, "teamEventStats") registerCreatureEvent(cid, "teambattleLogout") registerCreatureEvent(cid, "teambattleCombat") return true end ]]></event> <event type="combat" name="teambattleCombat" event="script"><![CDATA[ domodlib('teamFunctions') function onCombat(cid, target) if isFightOn() then if isBlue(cid) and isBlue(target) then return false end if isRed(cid) and isRed(target) then return false end end return true end ]]></event> <event type="logout" name="teambattleLogout" event="script"><![CDATA[ domodlib('teamFunctions') function onLogout(cid) clearTeamEventStorages(cid) if thereIsAWinner() then endTeamEvent("KO") end return true end ]]></event> <event type="statschange" name="teamEventStats" event="script"><![CDATA[ domodlib('teamFunctions') corpse_ids = { [0] = 3065, -- female [1] = 3058 -- male } function onStatsChange(cid, attacker, type, combat, value) if combat == COMBAT_HEALING then return true end if getCreatureHealth(cid) > value then return true end if isInFightArea(cid) and isFightOn() then if isBlue(cid) or isRed(cid) then corpse = doCreateItem(corpse_ids[getPlayerSex(cid)], 1, getThingPos(cid)) doCreateItem(2016, 2, getThingPos(cid)) clearTeamEventStorages(cid) doItemSetAttribute(corpse, "description", "You recognize "..getCreatureName(cid)..". He was killed by "..(isMonster(attacker) and "a "..string.lower(getCreatureName(attacker)) or isCreature(attacker) and getCreatureName(attacker) or "a field item")..".\n[Team-Event kill]") doCreatureAddHealth(cid,getCreatureMaxHealth(cid)) if thereIsAWinner() then endTeamEvent("KO") end return false end end return true end ]]></event> <globalevent name="teamBattleStart" time="20:02:00" event="script"><![CDATA[ domodlib('teamFunctions') function onTime() resetEvent() if getTileItemById(teleporterPosition,1387).uid < 1 then tp = doCreateItem(1387,1,teleporterPosition) doItemSetAttribute(tp, "aid", 9990) end startRecruiting() for i = 0, recruitTime-1 do addEvent(doBroadcastMessage, i * 60* 1000,"Team-Battle event is recruting players by entering event tp. Fight begins in "..(i == 0 and recruitTime or recruitTime-i).." minutes.",MESSAGE_TYPES["warning"]) end addEvent(startEvent, recruitTime * 60 * 1000) return true end ]]></globalevent> <globalevent name = "teamBattletime" interval="1" event="script"><![CDATA[ domodlib('teamFunctions') function onThink() if isFightOn() then disPlayEventStats() if getStorage(nextExecute) == -1 or getStorage(nextExecute) <= os.time() then doSendLeftPlayers() doSetStorage(nextExecute,os.time()+intervalToSendLeftPlayers) end end return true end ]]></globalevent> <movevent type="StepIn" actionid="9990" event="script"><![CDATA[ domodlib('teamFunctions') function onStepIn(cid, item, position, fromPosition) if not isRecruitOn() then doPlayerSendTextMessage(cid,MESSAGE_TYPES["orange"],"Event isn't currently opened.") doTeleportThing(cid,fromPosition) doSendMagicEffect(fromPosition,2) return true end if getPlayerLevel(cid) < getMinJoinLevel() then doPlayerSendTextMessage(cid,MESSAGE_TYPES["orange"],"Only players of level ".. getMinJoinLevel().. "+ can join this event.") doTeleportThing(cid,fromPosition) return true end teleportToWaitRoom(cid) return true end ]]> </movevent> </mod>
  5. eu falei mods mas na realidade é data/libs.. to tomando uma coça aqui kkkk assim que eu descobrir qual é o arquivo eu vou postar o codigo.. só nao postei porque realmente nao sei exatamente o arquivo onde o bug esta... mas ja ja posto o codigo do arquivo, to chegando proximo rsrs obrigado pela ajuda
  6. pelo que estou percebendo o problema esta na pasta (editado) data/libs mas ainda nao sei aonde. peguei um outro ot compacto que esta sem esse problema e comecei fazer a substituição dos arquivos e só acontece apos a substituição da pasta data/libs. ainda estou na luta aqui rsrs uso tsf0.4.
  7. Boa tarde galera, estou com um problema que os aneis e boots quando equipados no logout, ao relogar eles não funcionam mais. Se eu estiver com um stealth ring, life ring, stealth boots ou qualquer equip ele funciona normalmente, mas se eu fizer logout e entrar novamente ele nao esta mais funcionando. So volta quando eu liberto o slot e ocupo ele novamente com o item, se eu apenas substituir o item por um outro ele continua sem funcionar. alguem sabe como consigo resolver isso? teria algum script q verificasse os slots e ativasse os itens? obrigado desde já
  8. Boa noite pessoal, Resumindo: O problema é que o forum tem algumas boards (News, Wars, Quests, Pictures e Bug reports), suponhamos que dessas boards Pictures tem 4 posts e Quests 1 post. Se o primeito post do forum for em Pictures, quando eu tentar abrir o post de Quests ele ira me redirecionar para Pictures, e dentro de pictures terá todos os posts de todas as boards. Se eu tentar excluir algum topico de qualquer board, todos os topicos são excluidos. Acredito que o problema esteja no criação do ID do post na database, todos estão sendo gerados como ID 0. Imagino que a função new_post não está trabalhando corretamente. 1º print todas as boards do forum 2º print dentro da board WARS (repare que so existe 1 post)) 3º print é apos clicar no unico post do board WARS e fui direcionado para o lugar errado (os postas aparecem em sequencia de postagem) 4º registro no banco de dados (Observer ID 0 em todos os posts) / / / alguem tem alguma ideia de como consigo arrumar isso? segue meu forum.php <?php if(!defined('INITIALIZED')) exit; // CONFIG $level_limit = 30; // minimum 1 character with 30 lvl on account to post $post_interval = 20; // 20 seconds between posts $group_not_blocked = $config['site']['access_admin_panel']; // group id of player that can always post, remove post, remove threads $posts_per_page = 20; $threads_per_page = 20; // SECTION WITH ID 1 IS FOR "NEWS", ONLY ADMINS CAN CREATE NEW THREAD IN IT $sections = array(1 => 'News', 2 => 'Wars', 3 => 'Quests', 4 => 'Pictures', 5 => 'Bug Report'); $sections_desc = array(1 => 'Here you can comment news.', 2 => 'Feel free to tell what you think about your enemy.', 3 => 'Talk with others about quests you made and how to make them.', 4 => 'Show others your best photos from server!', 5 => 'Report bugs on website and in-game here.'); // END function canPost($account) { if($account->isLoaded()) if(!$account->isBanned()) { $SQL = $GLOBALS['SQL']; $level_limit = $GLOBALS['level_limit']; $player = $SQL->query("SELECT " . $SQL->fieldName('level') . " FROM " . $SQL->tableName('players') . " WHERE " . $SQL->fieldName('account_id') . " = ".$SQL->quote($account->getId())." ORDER BY " . $SQL->fieldName('level') . " DESC")->fetch(); if($player['level'] >= $level_limit) return true; } return false; } function replaceSmile($text, $smile) { $smileys = array(';D' => 1, ':D' => 1, ':cool:' => 2, ';cool;' => 2, ':ekk:' => 3, ';ekk;' => 3, ';o' => 4, ';O' => 4, ':o' => 4, ':O' => 4, ':(' => 5, ';(' => 5, ':mad:' => 6, ';mad;' => 6, ';rolleyes;' => 7, ':rolleyes:' => 7, ':)' => 8, ';d' => 9, ':d' => 9, ';)' => 10); if($smile == 1) return $text; else { foreach($smileys as $search => $replace) $text = str_replace($search, '<img src="images/forum/smile/'.$replace.'.gif" />', $text); return $text; } } function replaceAll($text, $smile) { $rows = 0; while(stripos($text, '[code]') !== false && stripos($text, '[/code]') !== false && stripos($text, '[code]') < stripos($text, '[/code]')) { $code = substr($text, stripos($text, '[code]')+6, stripos($text, '[/code]') - stripos($text, '[code]') - 6); if(!is_int($rows / 2)) { $bgcolor = 'ABED25'; } else { $bgcolor = '23ED25'; } $rows++; $text = str_ireplace('[code]'.$code.'[/code]', '<i>Code:</i><br /><table cellpadding="0" style="background-color: #'.$bgcolor.'; width: 480px; border-style: dotted; border-color: #CCCCCC; border-width: 2px"><tr><td>'.$code.'</td></tr></table>', $text); } $rows = 0; while(stripos($text, '[quote]') !== false && stripos($text, '[/quote]') !== false && stripos($text, '[quote]') < stripos($text, '[/quote]')) { $quote = substr($text, stripos($text, '[quote]')+7, stripos($text, '[/quote]') - stripos($text, '[quote]') - 7); if(!is_int($rows / 2)) { $bgcolor = 'AAAAAA'; } else { $bgcolor = 'CCCCCC'; } $rows++; $text = str_ireplace('[quote]'.$quote.'[/quote]', '<table cellpadding="0" style="background-color: #'.$bgcolor.'; width: 480px; border-style: dotted; border-color: #007900; border-width: 2px"><tr><td>'.$quote.'</td></tr></table>', $text); } $rows = 0; while(stripos($text, '[url]') !== false && stripos($text, '[/url]') !== false && stripos($text, '[url]') < stripos($text, '[/url]')) { $url = substr($text, stripos($text, '[url]')+5, stripos($text, '[/url]') - stripos($text, '[url]') - 5); $text = str_ireplace('[url]'.$url.'[/url]', '<a href="'.$url.'" target="_blank">'.$url.'</a>', $text); } while(stripos($text, '[player]') !== false && stripos($text, '[/player]') !== false && stripos($text, '[player]') < stripos($text, '[/player]')) { $player = substr($text, stripos($text, '[player]')+8, stripos($text, '[/player]') - stripos($text, '[player]') - 8); $text = str_ireplace('[player]'.$player.'[/player]', '<a href="?subtopic=characters&name='.urlencode($player).'">'.$player.'</a>', $text); } while(stripos($text, '[img]') !== false && stripos($text, '[/img]') !== false && stripos($text, '[img]') < stripos($text, '[/img]')) { $img = substr($text, stripos($text, '[img]')+5, stripos($text, '[/img]') - stripos($text, '[img]') - 5); $text = str_ireplace('[img]'.$img.'[/img]', '<img src="'.$img.'">', $text); } while(stripos($text, '[b]') !== false && stripos($text, '[/b]') !== false && stripos($text, '[b]') < stripos($text, '[/b]')) { $b = substr($text, stripos($text, '[b]')+3, stripos($text, '[/b]') - stripos($text, '[b]') - 3); $text = str_ireplace('[b]'.$b.'[/b]', '<b>'.$b.'</b>', $text); } while(stripos($text, '[i]') !== false && stripos($text, '[/i]') !== false && stripos($text, '[i]') < stripos($text, '[/i]')) { $i = substr($text, stripos($text, '[i]')+3, stripos($text, '[/i]') - stripos($text, '[i]') - 3); $text = str_ireplace('[i]'.$i.'[/i]', '<i>'.$i.'</i>', $text); } while(stripos($text, '[u]') !== false && stripos($text, '[/u]') !== false && stripos($text, '[u]') < stripos($text, '[/u]')) { $u = substr($text, stripos($text, '[u]')+3, stripos($text, '[/u]') - stripos($text, '[u]') - 3); $text = str_ireplace('[u]'.$u.'[/u]', '<u>'.$u.'</u>', $text); } return replaceSmile($text, $smile); } function removeBBCode($text) { while(stripos($text, '[code]') !== false && stripos($text, '[/code]') !== false ) { $code = substr($text, stripos($text, '[code]')+6, stripos($text, '[/code]') - stripos($text, '[code]') - 6); $text = str_ireplace('[code]'.$code.'[/code]', $code, $text); } while(stripos($text, '[quote]') !== false && stripos($text, '[/quote]') !== false ) { $quote = substr($text, stripos($text, '[quote]')+7, stripos($text, '[/quote]') - stripos($text, '[quote]') - 7); $text = str_ireplace('[quote]'.$quote.'[/quote]', $quote, $text); } while(stripos($text, '[url]') !== false && stripos($text, '[/url]') !== false ) { $url = substr($text, stripos($text, '[url]')+5, stripos($text, '[/url]') - stripos($text, '[url]') - 5); $text = str_ireplace('[url]'.$url.'[/url]', $url, $text); } while(stripos($text, '[player]') !== false && stripos($text, '[/player]') !== false ) { $player = substr($text, stripos($text, '[player]')+8, stripos($text, '[/player]') - stripos($text, '[player]') - 8); $text = str_ireplace('[player]'.$player.'[/player]', $player, $text); } while(stripos($text, '[img]') !== false && stripos($text, '[/img]') !== false ) { $img = substr($text, stripos($text, '[img]')+5, stripos($text, '[/img]') - stripos($text, '[img]') - 5); $text = str_ireplace('[img]'.$img.'[/img]', $img, $text); } while(stripos($text, '[b]') !== false && stripos($text, '[/b]') !== false ) { $b = substr($text, stripos($text, '[b]')+3, stripos($text, '[/b]') - stripos($text, '[b]') - 3); $text = str_ireplace('[b]'.$b.'[/b]', $b, $text); } while(stripos($text, '[i]') !== false && stripos($text, '[/i]') !== false ) { $i = substr($text, stripos($text, '[i]')+3, stripos($text, '[/i]') - stripos($text, '[i]') - 3); $text = str_ireplace('[i]'.$i.'[/i]', $i, $text); } while(stripos($text, '[u]') !== false && stripos($text, '[/u]') !== false ) { $u = substr($text, stripos($text, '[u]')+3, stripos($text, '[/u]') - stripos($text, '[u]') - 3); $text = str_ireplace('[u]'.$u.'[/u]', $u, $text); } return $text; } function codeLower($text) { return str_ireplace(array('[b]', '[i]', '[u]', '[/u][/i][/b][i][u]', '[/u][/i][u]', '[/u]', '[url]', '[player]', '[img]', '[code]', '[quote]', '[/quote][/code][/url][code][quote]', '[/player]', '[/img]', '[/quote][/code][quote]', '[/quote]'), array('[b]', '[i]', '[u]', '[/u][/i][/b][i][u]', '[/u][/i][u]', '[/u]', '[url]', '[player]', '[img]', '[code]', '[quote]', '[/quote][/code][/url][code][quote]', '[/player]', '[/img]', '[/quote][/code][quote]', '[/quote]'), $text); } function showPost($topic, $text, $smile) { $text = nl2br($text); $post = ''; if(!empty($topic)) $post .= '<b>'.replaceSmile($topic, $smile).'</b><hr />'; $post .= replaceAll($text, $smile); return $post; } if(!$logged) $main_content .= 'You are not logged in. <a href="?subtopic=accountmanagement">Log in</a> to post on the forum.<br /><br />'; if($action == '') { $main_content .= '<b>Boards</b>'; $main_content .= '<table width="100%"><tr bgcolor="'.$config['site']['vdarkborder'].'"><td><font color="white" size="1"><b>Board</b></font></td><td><font color="white" size="1"><b>Posts</b></font></td><td><font color="white" size="1"><b>Threads</b></font></td><td align="center"><font color="white" size="1"><b>Last Post</b></font></td></tr>'; $info = $SQL->query("SELECT " . $SQL->fieldName('section') . ", COUNT(" . $SQL->fieldName('id') . ") AS 'threads', SUM(" . $SQL->fieldName('replies') . ") AS 'replies' FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->fieldName('first_post') . " = " . $SQL->fieldName('id') . " GROUP BY " . $SQL->fieldName('section') . "")->fetchAll(); foreach($info as $data) $counters[$data['section']] = array('threads' => $data['threads'], 'posts' => $data['replies'] + $data['threads']); foreach($sections as $id => $section) { $last_post = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . " = ".(int) $id." AND " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " ORDER BY " . $SQL->fieldName('post_date') . " DESC LIMIT 1")->fetch(); if(!is_int($number_of_rows / 2)) { $bgcolor = $config['site']['darkborder']; } else { $bgcolor = $config['site']['lightborder']; } $number_of_rows++; $main_content .= '<tr bgcolor="'.$bgcolor.'"><td><a href="?subtopic=forum&action=show_board&id='.$id.'">'.$section.'</a><br /><small>'.$sections_desc[$id].'</small></td><td>'.(int) $counters[$id]['posts'].'</td><td>'.(int) $counters[$id]['threads'].'</td><td>'; if(isset($last_post['name'])) $main_content .= date('d.m.y H:i:s', $last_post['post_date']).'<br />by <a href="?subtopic=characters&name='.urlencode($last_post['name']).'">'.$last_post['name'].'</a>'; else $main_content .= 'No posts'; $main_content .= '</td></tr>'; } $main_content .= '</table>'; } if($action == 'show_board') { $section_id = (int) $_REQUEST['id']; $page = (int) $_REQUEST['page']; $threads_count = $SQL->query("SELECT COUNT(" . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ") AS threads_count FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . " = ".(int) $section_id." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . "")->fetch(); for($i = 0; $i < $threads_count['threads_count'] / $threads_per_page; $i++) { if($i != $page) $links_to_pages .= '<a href="?subtopic=forum&action=show_board&id='.$section_id.'&page='.$i.'">'.($i + 1).'</a> '; else $links_to_pages .= '<b>'.($i + 1).' </b>'; } $main_content .= '<a href="?subtopic=forum">Boards</a> >> <b>'.$sections[$section_id].'</b><br /><br /><a href="?subtopic=forum&action=new_topic&section_id='.$section_id.'"><img src="images/forum/topic.gif" border="0" /></a><br /><br />Page: '.$links_to_pages.'<br />'; $last_threads = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_text') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('last_post') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('replies') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('views') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . " = ".(int) $section_id." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " ORDER BY " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('last_post') . " DESC LIMIT ".$threads_per_page." OFFSET ".($page * $threads_per_page))->fetchAll(); if(isset($last_threads[0])) { $main_content .= '<table width="100%"><tr bgcolor="'.$config['site']['vdarkborder'].'" align="center"><td><font color="white" size="1"><b>Thread</b></font></td><td><font color="white" size="1"><b>Thread Starter</b></font></td><td><font color="white" size="1"><b>Replies</b></font></td><td><font color="white" size="1"><b>Views</b></font></td><td><font color="white" size="1"><b>Last Post</b></font></td></tr>'; foreach($last_threads as $thread) { if(!is_int($number_of_rows / 2)) { $bgcolor = $config['site']['darkborder']; } else { $bgcolor = $config['site']['lightborder']; } $number_of_rows++; $main_content .= '<tr bgcolor="'.$bgcolor.'"><td>'; if($logged && $group_id_of_acc_logged >= $group_not_blocked) $main_content .= '<a href="?subtopic=forum&action=remove_post&id='.$thread['id'].'" onclick="return confirm(\'Are you sure you want remove thread > '.htmlspecialchars($thread['post_topic']).' <?\')"><font color="red">[REMOVE]</font></a> '; $main_content .= '<a href="?subtopic=forum&action=show_thread&id='.$thread['id'].'">'.htmlspecialchars($thread['post_topic']).'</a><br /><small>'.htmlspecialchars(substr(removeBBCode($thread['post_text']), 0, 50)).'...</small></td><td><a href="?subtopic=characters&name='.urlencode($thread['name']).'">'.$thread['name'].'</a></td><td>'.(int) $thread['replies'].'</td><td>'.(int) $thread['views'].'</td><td>'; if($thread['last_post'] > 0) { $last_post = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread['id']." AND " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " ORDER BY " . $SQL->fieldName('post_date') . " DESC LIMIT 1")->fetch(); if(isset($last_post['name'])) $main_content .= date('d.m.y H:i:s', $last_post['post_date']).'<br />by <a href="?subtopic=characters&name='.urlencode($last_post['name']).'">'.$last_post['name'].'</a>'; else $main_content .= 'No posts.'; } else $main_content .= date('d.m.y H:i:s', $thread['post_date']).'<br />by <a href="?subtopic=characters&name='.urlencode($thread['name']).'">'.$thread['name'].'</a>'; $main_content .= '</td></tr>'; } $main_content .= '</table><br /><a href="?subtopic=forum&action=new_topic&section_id='.$section_id.'"><img src="images/forum/topic.gif" border="0" /></a>'; } else $main_content .= '<h3>No threads in this board.</h3>'; } if($action == 'show_thread') { $thread_id = (int) $_REQUEST['id']; $page = (int) $_REQUEST['page']; $thread_name = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread_id." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " AND " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " LIMIT 1")->fetch(); if(!empty($thread_name['name'])) { $posts_count = $SQL->query("SELECT COUNT(" . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ") AS posts_count FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread_id)->fetch(); for($i = 0; $i < $posts_count['posts_count'] / $threads_per_page; $i++) { if($i != $page) $links_to_pages .= '<a href="?subtopic=forum&action=show_thread&id='.$thread_id.'&page='.$i.'">'.($i + 1).'</a> '; else $links_to_pages .= '<b>'.($i + 1).' </b>'; } $threads = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('account_id') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('world_id') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('rank_id') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('vocation') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('promotion') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('level') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . "," . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . "," . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_text') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_smile') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_aid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('last_edit_aid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('edit_date') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread_id." ORDER BY " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " LIMIT ".$posts_per_page." OFFSET ".($page * $posts_per_page))->fetchAll(); if(isset($threads[0]['name'])) $SQL->query("UPDATE " . $SQL->tableName('z_forum') . " SET " . $SQL->fieldName('views') . "=" . $SQL->fieldName('views') . "+1 WHERE " . $SQL->fieldName('id') . " = ".(int) $thread_id); $main_content .= '<a href="?subtopic=forum">Boards</a> >> <a href="?subtopic=forum&action=show_board&id='.$threads[0]['section'].'">'.$sections[$threads[0]['section']].'</a> >> <b>'.htmlspecialchars($thread_name['post_topic']).'</b>'; $main_content .= '<br /><br /><a href="?subtopic=forum&action=new_post&thread_id='.$thread_id.'"><img src="images/forum/post.gif" border="0" /></a><br /><br />Page: '.$links_to_pages.'<br /><table width="100%"><tr bgcolor="'.$config['site']['lightborder'].'" width="100%"><td colspan="2"><font size="4"><b>'.htmlspecialchars($thread_name['post_topic']).'</b></font><font size="1"><br />by <a href="?subtopic=characters&name='.urlencode($thread_name['name']).'">'.htmlspecialchars($thread_name['name']).'</a></font></td></tr><tr bgcolor="'.$config['site']['vdarkborder'].'"><td width="200"><font color="white" size="1"><b>Author</b></font></td><td>&nbsp;</td></tr>'; foreach($threads as $thread) { if(!is_int($number_of_rows / 2)) { $bgcolor = $config['site']['darkborder']; } else { $bgcolor = $config['site']['lightborder']; } $number_of_rows++; $main_content .= '<tr bgcolor="'.$bgcolor.'"><td valign="top"><a href="?subtopic=characters&name='.urlencode($thread['name']).'">'.htmlspecialchars($thread['name']).'</a><br /><br /><font size="1">Profession: '.htmlspecialchars(Website::getVocationName($thread['vocation'], $thread['promotion'])).'<br />Level: '.$thread['level'].'<br />'; $rank = new GuildRank($thread['rank_id']); if($rank->isLoaded()) { $guild = $rank->getGuild(); if($guild->isLoaded()) $main_content .= htmlspecialchars($rank->getName()).' of <a href="?subtopic=guilds&action=show&guild='.$guild->getId().'">'.htmlspecialchars($guild->getName()).'</a><br />'; } $posts = $SQL->query("SELECT COUNT(" . $SQL->fieldName('id') . ") AS 'posts' FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->fieldName('author_aid') . "=".(int) $thread['account_id'])->fetch(); $main_content .= '<br />Posts: '.(int) $posts['posts'].'<br /></font></td><td valign="top">'.showPost(htmlspecialchars($thread['post_topic']), htmlspecialchars($thread['post_text']), $thread['post_smile']).'</td></tr> <tr bgcolor="'.$bgcolor.'"><td><font size="1">'.date('d.m.y H:i:s', $thread['post_date']); if($thread['edit_date'] > 0) { if($thread['last_edit_aid'] != $thread['author_aid']) $main_content .= '<br />Edited by moderator'; else $main_content .= '<br />Edited by '.htmlspecialchars($thread['name']); $main_content .= '<br />on '.date('d.m.y H:i:s', $thread['edit_date']); } $main_content .= '</font></td><td>'; if($logged && $group_id_of_acc_logged >= $group_not_blocked) if($thread['first_post'] != $thread['id']) $main_content .= '<a href="?subtopic=forum&action=remove_post&id='.$thread['id'].'" onclick="return confirm(\'Are you sure you want remove post of '.htmlspecialchars($thread['name']).'?\')"><font color="red">REMOVE POST</font></a>'; else $main_content .= '<a href="?subtopic=forum&action=remove_post&id='.$thread['id'].'" onclick="return confirm(\'Are you sure you want remove thread > '.htmlspecialchars($thread['post_topic']).' <?\')"><font color="red">REMOVE THREAD</font></a>'; if($logged && ($thread['account_id'] == $account_logged->getId() || $group_id_of_acc_logged >= $group_not_blocked)) $main_content .= '<br/><a href="?subtopic=forum&action=edit_post&id='.$thread['id'].'">EDIT POST</a>'; if($logged) $main_content .= '<br/><a href="?subtopic=forum&action=new_post&thread_id='.$thread_id.'&quote='.$thread['id'].'">Quote</a>'; $main_content .= '</td></tr>'; } $main_content .= '</table><br /><a href="?subtopic=forum&action=new_post&thread_id='.$thread_id.'"><img src="images/forum/post.gif" border="0" /></a><br /><center>Pages:<br />'.$links_to_pages.'<br /></center>'; } else $main_content .= 'Thread with this ID does not exits.'; } if($action == 'remove_post') { if($logged && $group_id_of_acc_logged >= $group_not_blocked) { $id = (int) $_REQUEST['id']; $post = $SQL->query("SELECT " . $SQL->fieldName('id') . ", " . $SQL->fieldName('first_post') . ", " . $SQL->fieldName('section') . " FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->fieldName('id') . " = ".$id." LIMIT 1")->fetch(); if($post['id'] == $id) { if($post['id'] == $post['first_post']) { $SQL->query("DELETE FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->fieldName('first_post') . " = ".$post['id']); header('Location: ?subtopic=forum&action=show_board&id='.$post['section']); } else { $post_page = $SQL->query("SELECT COUNT(" . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ") AS posts_count FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " < ".$id." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $post['first_post'])->fetch(); $page = (int) ceil($post_page['posts_count'] / $threads_per_page) - 1; $SQL->query("UPDATE " . $SQL->tableName('z_forum') . " SET " . $SQL->fieldName('replies') . " = " . $SQL->fieldName('replies') . " - 1 WHERE " . $SQL->fieldName('id') . " = ".$post['first_post']); $SQL->query("DELETE FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->fieldName('id') . " = ".$post['id']); header('Location: ?subtopic=forum&action=show_thread&id='.$post['first_post'].'&page='.(int) $page); } } else $main_content .= 'Post with ID '.$id.' does not exist.'; } else $main_content .= 'You are not logged in or you are not moderator.'; } if($action == 'new_post') { if($logged) { if(canPost($account_logged) || $group_id_of_acc_logged >= $group_not_blocked) { $players_from_account = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " FROM " . $SQL->tableName('players') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('account_id') . " = ".(int) $account_logged->getId())->fetchAll(); $thread_id = (int) $_REQUEST['thread_id']; $thread = $SQL->query("SELECT " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . " FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " = ".(int) $thread_id." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread_id." LIMIT 1")->fetch(); $main_content .= '<a href="?subtopic=forum">Boards</a> >> <a href="?subtopic=forum&action=show_board&id='.$thread['section'].'">'.$sections[$thread['section']].'</a> >> <a href="?subtopic=forum&action=show_thread&id='.$thread_id.'">'.htmlspecialchars($thread['post_topic']).'</a> >> <b>Post new reply</b><br /><h3>'.htmlspecialchars($thread['post_topic']).'</h3>'; if(isset($thread['id'])) { $quote = (int) $_REQUEST['quote']; $text = trim(codeLower($_REQUEST['text'])); $char_id = (int) $_REQUEST['char_id']; $post_topic = trim($_REQUEST['topic']); $smile = (int) $_REQUEST['smile']; $saved = false; if(isset($_REQUEST['quote'])) { $quoted_post = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_text') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " = ".(int) $quote)->fetchAll(); if(isset($quoted_post[0]['name'])) $text = '[i]Originally posted by '.$quoted_post[0]['name'].' on '.date('d.m.y H:i:s', $quoted_post[0]['post_date']).':[/i][quote]'.$quoted_post[0]['post_text'].'[/quote]'; } elseif(isset($_REQUEST['save'])) { $lenght = 0; for($i = 0; $i <= strlen($text); $i++) { if(ord($text[$i]) >= 33 && ord($text[$i]) <= 126) $lenght++; } if($lenght < 1 || strlen($text) > 15000) $errors[] = 'Too short or too long post (short: '.$lenght.' long: '.strlen($text).' letters). Minimum 1 letter, maximum 15000 letters.'; if($char_id == 0) $errors[] = 'Please select a character.'; $player_on_account == false; if(count($errors) == 0) { foreach($players_from_account as $player) if($char_id == $player['id']) $player_on_account = true; if(!$player_on_account) $errors[] = 'Player with selected ID '.$char_id.' doesn\'t exist or isn\'t on your account'; } if(count($errors) == 0) { $last_post = $account_logged->getCustomField('last_post'); if($last_post+$post_interval-time() > 0 && $group_id_of_acc_logged < $group_not_blocked) $errors[] = 'You can post one time per '.$post_interval.' seconds. Next post after '.($last_post+$post_interval-time()).' second(s).'; } if(count($errors) == 0) { $saved = true; $account_logged->set('last_post', time()); $account_logged->save(); $SQL->query("INSERT INTO " . $SQL->tableName('z_forum') . " (" . $SQL->fieldName('first_post') . " ," . $SQL->fieldName('last_post') . " ," . $SQL->fieldName('section') . " ," . $SQL->fieldName('replies') . " ," . $SQL->fieldName('views') . " ," . $SQL->fieldName('author_aid') . " ," . $SQL->fieldName('author_guid') . " ," . $SQL->fieldName('post_text') . " ," . $SQL->fieldName('post_topic') . " ," . $SQL->fieldName('post_smile') . " ," . $SQL->fieldName('post_date') . " ," . $SQL->fieldName('last_edit_aid') . " ," . $SQL->fieldName('edit_date') . ", " . $SQL->fieldName('post_ip') . ") VALUES ('".$thread['id']."', '0', '".$thread['section']."', '0', '0', '".$account_logged->getId()."', '".(int) $char_id."', ".$SQL->quote($text).", ".$SQL->quote($post_topic).", '".(int) $smile."', '".time()."', '0', '0', '".$_SERVER['REMOTE_ADDR']."')"); $SQL->query("UPDATE " . $SQL->tableName('z_forum') . " SET " . $SQL->fieldName('replies') . "=" . $SQL->fieldName('replies') . "+1, " . $SQL->fieldName('last_post') . "=".time()." WHERE " . $SQL->fieldName('id') . " = ".(int) $thread_id); $post_page = $SQL->query("SELECT COUNT(" . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ") AS posts_count FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " <= ".time()." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread['id'])->fetch(); $page = (int) ceil($post_page['posts_count'] / $threads_per_page) - 1; header('Location: ?subtopic=forum&action=show_thread&id='.$thread_id.'&page='.$page); $main_content .= '<br />Thank you for posting.<br /><a href="?subtopic=forum&action=show_thread&id='.$thread_id.'">GO BACK TO LAST THREAD</a>'; } } if(!$saved) { if(count($errors) > 0) { $main_content .= '<font color="red" size="2"><b>Errors occured:</b>'; foreach($errors as $error) $main_content .= '<br />* '.$error; $main_content .= '</font><br />'; } $main_content .= '<form action="?" method="POST"><input type="hidden" name="action" value="new_post" /><input type="hidden" name="thread_id" value="'.$thread_id.'" /><input type="hidden" name="subtopic" value="forum" /><input type="hidden" name="save" value="save" /><table width="100%"><tr bgcolor="'.$config['site']['vdarkborder'].'"><td colspan="2"><font color="white"><b>Post New Reply</b></font></td></tr><tr bgcolor="'.$config['site']['darkborder'].'"><td width="180"><b>Character:</b></td><td><select name="char_id"><option value="0">(Choose character)</option>'; foreach($players_from_account as $player) { $main_content .= '<option value="'.$player['id'].'"'; if($player['id'] == $char_id) $main_content .= ' selected="selected"'; $main_content .= '>'.$player['name'].'</option>'; } $main_content .= '</select></td></tr><tr bgcolor="'.$config['site']['lightborder'].'"><td><b>Topic:</b></td><td><input type="text" name="topic" value="'.htmlspecialchars($post_topic).'" size="40" maxlength="60" /> (Optional)</td></tr> <tr bgcolor="'.$config['site']['darkborder'].'"><td valign="top"><b>Message:</b><font size="1"><br />You can use:<br />[player]Nick[/player]<br />[url=http://address.com/]Address Search - Find Email and Addresses @ Address.com[/url]<br />[img=http://images.com/images3.gif]<br />[code]Code[/code]<br />[b]<b>Text</b>[/b]<br />[i]<i>Text</i>[/i]<br />[u]<u>Text</u>[/u]<br />and smileys:<br />;) , :) , :D , :( , :rolleyes:<br />:cool: , :eek: , :o , :p</font></td><td><textarea rows="10" cols="60" name="text">'.htmlspecialchars($text).'</textarea><br />(Max. 15,000 letters)</td></tr> <tr bgcolor="'.$config['site']['lightborder'].'"><td valign="top">Options:</td><td><label><input type="checkbox" name="smile" value="1"'; if($smile == 1) $main_content .= ' checked="checked"'; $main_content .= '/>Disable Smileys in This Post </label></td></tr></table><center><input type="submit" value="Post Reply" /></center></form>'; $threads = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_text') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_smile') . " FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread_id." ORDER BY " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " DESC LIMIT 10")->fetchAll(); $main_content .= '<table width="100%"><tr bgcolor="'.$config['site']['vdarkborder'].'"><td colspan="2"><font color="white"><b>Last 5 posts from thread: '.htmlspecialchars($thread['post_topic']).'</b></font></td></tr>'; foreach($threads as $thread) { if(is_int($number_of_rows / 2)) { $bgcolor = $config['site']['darkborder']; } else { $bgcolor = $config['site']['lightborder']; } $number_of_rows++; $main_content .= '<tr bgcolor="'.$bgcolor.'"><td>'.$thread['name'].'</td><td>'.showPost(htmlspecialchars($thread['post_topic']), htmlspecialchars($thread['post_text']), $thread['post_smile']).'</td></tr>'; } $main_content .= '</table>'; } } else $main_content .= 'Thread with ID '.$thread_id.' doesn\'t exist.'; } else $main_content .= 'Your account is banned, deleted or you don\'t have any player with level '.$level_limit.' on your account. You can\'t post.'; } else $main_content .= 'Login first.'; } if($action == 'edit_post') { if($logged) { if(canPost($account_logged) || $group_id_of_acc_logged >= $group_not_blocked) { $post_id = (int) $_REQUEST['id']; $thread = $SQL->query("SELECT " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_aid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_text') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_smile') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . " FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " = ".(int) $post_id." LIMIT 1")->fetch(); if(isset($thread['id'])) { $first_post = $SQL->query("SELECT " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_aid') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_topic') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_text') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_smile') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ", " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('section') . " FROM " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . " = ".(int) $thread['first_post']." LIMIT 1")->fetch(); $main_content .= '<a href="?subtopic=forum">Boards</a> >> <a href="?subtopic=forum&action=show_board&id='.$thread['section'].'">'.$sections[$thread['section']].'</a> >> <a href="?subtopic=forum&action=show_thread&id='.$thread['first_post'].'">'.htmlspecialchars($first_post['post_topic']).'</a> >> <b>Edit post</b>'; if($account_logged->getId() == $thread['author_aid'] || $group_id_of_acc_logged >= $group_not_blocked) { $players_from_account = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " FROM " . $SQL->tableName('players') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('account_id') . " = ".(int) $account_logged->getId())->fetchAll(); $saved = false; if(isset($_REQUEST['save'])) { $text = trim(codeLower($_REQUEST['text'])); $char_id = (int) $_REQUEST['char_id']; $post_topic = trim($_REQUEST['topic']); $smile = (int) $_REQUEST['smile']; $lenght = 0; for($i = 0; $i <= strlen($post_topic); $i++) { if(ord($post_topic[$i]) >= 33 && ord($post_topic[$i]) <= 126) $lenght++; } if(($lenght < 1 || strlen($post_topic) > 60) && $thread['id'] == $thread['first_post']) $errors[] = 'Too short or too long topic (short: '.$lenght.' long: '.strlen($post_topic).' letters). Minimum 1 letter, maximum 60 letters.'; $lenght = 0; for($i = 0; $i <= strlen($text); $i++) { if(ord($text[$i]) >= 33 && ord($text[$i]) <= 126) $lenght++; } if($lenght < 1 || strlen($text) > 15000) $errors[] = 'Too short or too long post (short: '.$lenght.' long: '.strlen($text).' letters). Minimum 1 letter, maximum 15000 letters.'; if($char_id == 0) $errors[] = 'Please select a character.'; if(empty($post_topic) && $thread['id'] == $thread['first_post']) $errors[] = 'Thread topic can\'t be empty.'; $player_on_account == false; if(count($errors) == 0) { foreach($players_from_account as $player) if($char_id == $player['id']) $player_on_account = true; if(!$player_on_account) $errors[] = 'Player with selected ID '.$char_id.' doesn\'t exist or isn\'t on your account'; } if(count($errors) == 0) { $saved = true; if($account_logged->getId() != $thread['author_aid']) $char_id = $thread['author_guid']; $SQL->query("UPDATE " . $SQL->tableName('z_forum') . " SET " . $SQL->fieldName('author_guid') . " = ".(int) $char_id.", " . $SQL->fieldName('post_text') . " = ".$SQL->quote($text).", " . $SQL->fieldName('post_topic') . " = ".$SQL->quote($post_topic).", " . $SQL->fieldName('post_smile') . " = ".(int) $smile.", " . $SQL->fieldName('last_edit_aid') . " = ".(int) $account_logged->getId()."," . $SQL->fieldName('edit_date') . " = ".time()." WHERE " . $SQL->fieldName('id') . " = ".(int) $thread['id']); $post_page = $SQL->query("SELECT COUNT(" . $SQL->tableName('z_forum') . "." . $SQL->fieldName('id') . ") AS posts_count FROM " . $SQL->tableName('players') . ", " . $SQL->tableName('z_forum') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " = " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('author_guid') . " AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('post_date') . " <= ".$thread['post_date']." AND " . $SQL->tableName('z_forum') . "." . $SQL->fieldName('first_post') . " = ".(int) $thread['first_post'])->fetch(); $page = (int) ceil($post_page['posts_count'] / $threads_per_page) - 1; header('Location: ?subtopic=forum&action=show_thread&id='.$thread['first_post'].'&page='.$page); $main_content .= '<br />Thank you for editing post.<br /><a href="?subtopic=forum&action=show_thread&id='.$thread['first_post'].'">GO BACK TO LAST THREAD</a>'; } } else { $text = $thread['post_text']; $char_id = (int) $thread['author_guid']; $post_topic = $thread['post_topic']; $smile = (int) $thread['post_smile']; } if(!$saved) { if(count($errors) > 0) { $main_content .= '<br /><font color="red" size="2"><b>Errors occured:</b>'; foreach($errors as $error) $main_content .= '<br />* '.$error; $main_content .= '</font>'; } $main_content .= '<br /><form action="?" method="POST"><input type="hidden" name="action" value="edit_post" /><input type="hidden" name="id" value="'.$post_id.'" /><input type="hidden" name="subtopic" value="forum" /><input type="hidden" name="save" value="save" /><table width="100%"><tr bgcolor="'.$config['site']['vdarkborder'].'"><td colspan="2"><font color="white"><b>Edit Post</b></font></td></tr><tr bgcolor="'.$config['site']['darkborder'].'"><td width="180"><b>Character:</b></td><td><select name="char_id"><option value="0">(Choose character)</option>'; foreach($players_from_account as $player) { $main_content .= '<option value="'.$player['id'].'"'; if($player['id'] == $char_id) $main_content .= ' selected="selected"'; $main_content .= '>'.$player['name'].'</option>'; } $main_content .= '</select></td></tr><tr bgcolor="'.$config['site']['lightborder'].'"><td><b>Topic:</b></td><td><input type="text" value="'.htmlspecialchars($post_topic).'" name="topic" size="40" maxlength="60" /> (Optional)</td></tr> <tr bgcolor="'.$config['site']['darkborder'].'"><td valign="top"><b>Message:</b><font size="1"><br />You can use:<br />[player]Nick[/player]<br />[url=http://address.com/]Address Search - Find Email and Addresses @ Address.com[/url]<br />[img=http://images.com/images3.gif]<br />[code]Code[/code]<br />[b]<b>Text</b>[/b]<br />[i]<i>Text</i>[/i]<br />[u]<u>Text</u>[/u]<br />and smileys:<br />;) , :) , :D , :( , :rolleyes:<br />:cool: , :eek: , :o , :p</font></td><td><textarea rows="10" cols="60" name="text">'.htmlspecialchars($text).'</textarea><br />(Max. 15,000 letters)</td></tr> <tr bgcolor="'.$config['site']['lightborder'].'"><td valign="top">Options:</td><td><label><input type="checkbox" name="smile" value="1"'; if($smile == 1) $main_content .= ' checked="checked"'; $main_content .= '/>Disable Smileys in This Post </label></td></tr></table><center><input type="submit" value="Save Post" /></center></form>'; } } else $main_content .= '<br />You are not an author of this post.'; } else $main_content .= '<br />Post with ID '.$post_id.' doesn\'t exist.'; } else $main_content .= '<br />Your account is banned, deleted or you don\'t have any player with level '.$level_limit.' on your account. You can\'t post.'; } else $main_content .= '<br />Login first.'; } if($action == 'new_topic') { if($logged) { if(canPost($account_logged) || $group_id_of_acc_logged >= $group_not_blocked) { $players_from_account = $SQL->query("SELECT " . $SQL->tableName('players') . "." . $SQL->fieldName('name') . ", " . $SQL->tableName('players') . "." . $SQL->fieldName('id') . " FROM " . $SQL->tableName('players') . " WHERE " . $SQL->tableName('players') . "." . $SQL->fieldName('account_id') . " = ".(int) $account_logged->getId())->fetchAll(); $section_id = (int) $_REQUEST['section_id']; $main_content .= '<a href="?subtopic=forum">Boards</a> >> <a href="?subtopic=forum&action=show_board&id='.$section_id.'">'.$sections[$section_id].'</a> >> <b>Post new thread</b><br />'; if(isset($sections[$section_id])) { if($section_id == 1 && $group_id_of_acc_logged < $group_not_blocked) $errors[] = 'Only moderators and admins can post on news board.'; $quote = (int) $_REQUEST['quote']; $text = trim(codeLower($_REQUEST['text'])); $char_id = (int) $_REQUEST['char_id']; $post_topic = trim($_REQUEST['topic']); $smile = (int) $_REQUEST['smile']; $saved = false; if(isset($_REQUEST['save'])) { $lenght = 0; for($i = 0; $i <= strlen($post_topic); $i++) { if(ord($post_topic[$i]) >= 33 && ord($post_topic[$i]) <= 126) $lenght++; } if($lenght < 1 || strlen($post_topic) > 60) $errors[] = 'Too short or too long topic (short: '.$lenght.' long: '.strlen($post_topic).' letters). Minimum 1 letter, maximum 60 letters.'; $lenght = 0; for($i = 0; $i <= strlen($text); $i++) { if(ord($text[$i]) >= 33 && ord($text[$i]) <= 126) $lenght++; } if($lenght < 1 || strlen($text) > 15000) $errors[] = 'Too short or too long post (short: '.$lenght.' long: '.strlen($text).' letters). Minimum 1 letter, maximum 15000 letters.'; if($char_id == 0) $errors[] = 'Please select a character.'; $player_on_account == false; if(count($errors) == 0) { foreach($players_from_account as $player) if($char_id == $player['id']) $player_on_account = true; if(!$player_on_account) $errors[] = 'Player with selected ID '.$char_id.' doesn\'t exist or isn\'t on your account'; } if(count($errors) == 0) { $last_post = $account_logged->getCustomField('last_post'); if($last_post+$post_interval-time() > 0 && $group_id_of_acc_logged < $group_not_blocked) $errors[] = 'You can post one time per '.$post_interval.' seconds. Next post after '.($last_post+$post_interval-time()).' second(s).'; } if(count($errors) == 0) { $saved = true; $account_logged->set('last_post', time()); $account_logged->save(); $SQL->query("INSERT INTO " . $SQL->tableName('z_forum') . " (" . $SQL->fieldName('first_post') . " ," . $SQL->fieldName('last_post') . " ," . $SQL->fieldName('section') . " ," . $SQL->fieldName('replies') . " ," . $SQL->fieldName('views') . " ," . $SQL->fieldName('author_aid') . " ," . $SQL->fieldName('author_guid') . " ," . $SQL->fieldName('post_text') . " ," . $SQL->fieldName('post_topic') . " ," . $SQL->fieldName('post_smile') . " ," . $SQL->fieldName('post_date') . " ," . $SQL->fieldName('last_edit_aid') . " ," . $SQL->fieldName('edit_date') . ", " . $SQL->fieldName('post_ip') . ") VALUES ('0', '".time()."', '".(int) $section_id."', '0', '0', '".$account_logged->getId()."', '".(int) $char_id."', ".$SQL->quote($text).", ".$SQL->quote($post_topic).", '".(int) $smile."', '".time()."', '0', '0', '".$_SERVER['REMOTE_ADDR']."')"); $thread_id = $SQL->lastInsertId(); $SQL->query("UPDATE " . $SQL->tableName('z_forum') . " SET " . $SQL->fieldName('first_post') . "=".(int) $thread_id." WHERE " . $SQL->fieldName('id') . " = ".(int) $thread_id); header('Location: ?subtopic=forum&action=show_thread&id='.$thread_id); $main_content .= '<br />Thank you for posting.<br /><a href="?subtopic=forum&action=show_thread&id='.$thread_id.'">GO BACK TO LAST THREAD</a>'; } } if(!$saved) { if(count($errors) > 0) { $main_content .= '<font color="red" size="2"><b>Errors occured:</b>'; foreach($errors as $error) $main_content .= '<br />* '.$error; $main_content .= '</font><br />'; } $main_content .= '<form action="?" method="POST"><input type="hidden" name="action" value="new_topic" /><input type="hidden" name="section_id" value="'.$section_id.'" /><input type="hidden" name="subtopic" value="forum" /><input type="hidden" name="save" value="save" /><table width="100%"><tr bgcolor="'.$config['site']['vdarkborder'].'"><td colspan="2"><font color="white"><b>Post New Reply</b></font></td></tr><tr bgcolor="'.$config['site']['darkborder'].'"><td width="180"><b>Character:</b></td><td><select name="char_id"><option value="0">(Choose character)</option>'; foreach($players_from_account as $player) { $main_content .= '<option value="'.$player['id'].'"'; if($player['id'] == $char_id) $main_content .= ' selected="selected"'; $main_content .= '>'.$player['name'].'</option>'; } $main_content .= '</select></td></tr><tr bgcolor="'.$config['site']['lightborder'].'"><td><b>Topic:</b></td><td><input type="text" name="topic" value="'.htmlspecialchars($post_topic).'" size="40" maxlength="60" /> (Optional)</td></tr> <tr bgcolor="'.$config['site']['darkborder'].'"><td valign="top"><b>Message:</b><font size="1"><br />You can use:<br />[player]Nick[/player]<br />[url=http://address.com/]Address Search - Find Email and Addresses @ Address.com[/url]<br />[img=http://images.com/images3.gif]<br />[code]Code[/code]<br />[b]<b>Text</b>[/b]<br />[i]<i>Text</i>[/i]<br />[u]<u>Text</u>[/u]<br />and smileys:<br />;) , :) , :D , :( , :rolleyes:<br />:cool: , :eek: , :o , :p</font></td><td><textarea rows="10" cols="60" name="text">'.htmlspecialchars($text).'</textarea><br />(Max. 15,000 letters)</td></tr> <tr bgcolor="'.$config['site']['lightborder'].'"><td valign="top">Options:</td><td><label><input type="checkbox" name="smile" value="1"'; if($smile == 1) $main_content .= ' checked="checked"'; $main_content .= '/>Disable Smileys in This Post </label></td></tr></table><center><input type="submit" value="Post Thread" /></center></form>'; } } else $main_content .= 'Board with ID '.$board_id.' doesn\'t exist.'; } else $main_content .= 'Your account is banned, deleted or you don\'t have any player with level '.$level_limit.' on your account. You can\'t post.'; } else $main_content .= 'Login first.'; }
  9. infelizmente terminei de testar agora, o primeiro nao deu erro de compilação mas tb nao funcionou. o segundo deu esse log: TheForgottenServer build script- seems to speed things up ALOT. CCache: OK CCache binaries located in /usr/lib/ccache Building on 1 cores, using 2 processes make all-am make[1]: Entering directory `/root/src' g++ -DHAVE_CONFIG_H -I. -I/usr/include/libxml2 -I/usr/include/lua5.1 -O2 -fomit-frame-pointer -D__USE_MYSQL__ -D__ENABLE_SERVER_DIAGNOSTIC__ -D__ROOT_PERMISSION__ -D_THREAD_SAFE -D_REENTRANT -Wall -Wextra -Wno-strict-aliasing -Wno-unused-parameter -Wno-array-bounds -pthread -pipe -MT item.o -MD -MP -MF .deps/item.Tpo -c -o item.o item.cpp item.cpp: In static member function 'static std::string Item::getDescription(const ItemType&, int32_t, const Item*, int32_t, bool)': item.cpp:807:32: error: expected ':' before ')' token s << " " << (begin ? "with") << " magic level " << it.runeMagLevel; ^ item.cpp:807:32: error: expected primary-expression before ')' token make[1]: *** [item.o] Error 1 make[1]: Leaving directory `/root/src' make: *** [all] Error 2 EDIT ***************************************** problema resolvido substituindo a palavra "and" por "with". Obrigado @DiegoRulez, tava desde ontem revirando o ot todo e nao achava esse bendido rsrs. e a frase ficou correta: It can only be used with magic level 15 or higher.
  10. vou testar aqui daq a pouco e dou um retorno. muito obrigado. se nao for pedir muito, poderia sinalizar no codigo as alteraçoes que voce fez? gosto de entender como a coisa funciona rsrs mais uma vez obrigado.
  11. https://github.com/s3kk/tfs04 muito obrigado
  12. desculpe, foi coisa do meu navegador... realmente estava traduzido kkkk agora ta certo, editei la.
  13. //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include "const.h" #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include "spells.h" #include "tools.h" #include "house.h" #include "housetile.h" #include "combat.h" #include "monsters.h" #include "configmanager.h" #include "game.h" extern Game g_game; extern Spells* g_spells; extern Monsters g_monsters; extern ConfigManager g_config; Spells::Spells(): m_interface("Spell Interface") { m_interface.initState(); } ReturnValue Spells::onPlayerSay(Player* player, const std::string& words) { std::string reWords = words; trimString(reWords); InstantSpell* instantSpell = getInstantSpell(reWords); if(!instantSpell) return RET_NOTPOSSIBLE; size_t size = instantSpell->getWords().length(); std::string param = reWords.substr(size, reWords.length() - size), reParam = ""; if(instantSpell->getHasParam() && !param.empty() && param[0] == ' ') { size_t quote = param.find('"', 1); if(quote != std::string::npos) { size_t tmp = param.find('"', quote + 1); if(tmp == std::string::npos) tmp = param.length(); reParam = param.substr(quote + 1, tmp - quote - 1); } else if(param.find(' ', 1) == std::string::npos) reParam = param.substr(1, param.length()); trimString(reParam); } Position pos = player->getPosition(); if(!instantSpell->castInstant(player, reParam)) return RET_NEEDEXCHANGE; SpeakClasses type = SPEAK_SAY; if(g_config.getBool(ConfigManager::EMOTE_SPELLS)) type = SPEAK_MONSTER_SAY; if(!g_config.getBool(ConfigManager::SPELL_NAME_INSTEAD_WORDS)) return g_game.internalCreatureSay(player, type, reWords, player->isGhost()) ? RET_NOERROR : RET_NOTPOSSIBLE; std::string ret = instantSpell->getName(); if(param.length()) { trimString(param); size_t tmp = 0, rtmp = param.length(); if(param[0] == '"') tmp = 1; if(param[rtmp] == '"') rtmp -= 1; ret += ": " + param.substr(tmp, rtmp); } return g_game.internalCreatureSay(player, type, ret, player->isGhost(), NULL, &pos) ? RET_NOERROR : RET_NOTPOSSIBLE; } void Spells::clear() { for(RunesMap::iterator rit = runes.begin(); rit != runes.end(); ++rit) delete rit->second; runes.clear(); for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it) delete it->second; instants.clear(); m_interface.reInitState(); } Event* Spells::getEvent(const std::string& nodeName) { std::string tmpNodeName = asLowerCaseString(nodeName); if(tmpNodeName == "rune") return new RuneSpell(&m_interface); if(tmpNodeName == "instant") return new InstantSpell(&m_interface); if(tmpNodeName == "conjure") return new ConjureSpell(&m_interface); return NULL; } bool Spells::registerEvent(Event* event, xmlNodePtr, bool override) { if(InstantSpell* instant = dynamic_cast<InstantSpell*>(event)) { InstantsMap::iterator it = instants.find(instant->getWords()); if(it == instants.end()) { instants[instant->getWords()] = instant; return true; } if(override) { delete it->second; it->second = instant; return true; } std::clog << "[Warning - Spells::registerEvent] Duplicate registered instant spell with words: " << instant->getWords() << std::endl; return false; } if(RuneSpell* rune = dynamic_cast<RuneSpell*>(event)) { RunesMap::iterator it = runes.find(rune->getRuneItemId()); if(it == runes.end()) { runes[rune->getRuneItemId()] = rune; return true; } if(override) { delete it->second; it->second = rune; return true; } std::clog << "[Warning - Spells::registerEvent] Duplicate registered rune with id: " << rune->getRuneItemId() << std::endl; return false; } return false; } Spell* Spells::getSpellByName(const std::string& name) { Spell* spell; if((spell = getRuneSpellByName(name)) || (spell = getInstantSpellByName(name))) return spell; return NULL; } RuneSpell* Spells::getRuneSpell(uint32_t id) { RunesMap::iterator it = runes.find(id); if(it != runes.end()) return it->second; return NULL; } RuneSpell* Spells::getRuneSpellByName(const std::string& name) { for(RunesMap::iterator it = runes.begin(); it != runes.end(); ++it) { if(strcasecmp(it->second->getName().c_str(), name.c_str()) == 0) return it->second; } return NULL; } InstantSpell* Spells::getInstantSpell(const std::string& words) { InstantSpell* result = NULL; for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it) { InstantSpell* instantSpell = it->second; if(strncasecmp(instantSpell->getWords().c_str(), words.c_str(), instantSpell->getWords().length()) == 0) { if(!result || instantSpell->getWords().length() > result->getWords().length()) result = instantSpell; } } if(result && words.length() > result->getWords().length()) { std::string param = words.substr(result->getWords().length(), words.length()); if(param[0] != ' ' || (param.length() > 1 && (!result->getHasParam() || param.find(' ', 1) != std::string::npos) && param[1] != '"')) return NULL; } return result; } uint32_t Spells::getInstantSpellCount(const Player* player) { uint32_t count = 0; for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it) { if(it->second->canCast(player)) ++count; } return count; } InstantSpell* Spells::getInstantSpellByIndex(const Player* player, uint32_t index) { uint32_t count = 0; for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it) { InstantSpell* instantSpell = it->second; if(!instantSpell->canCast(player)) continue; if(count == index) return instantSpell; ++count; } return NULL; } InstantSpell* Spells::getInstantSpellByName(const std::string& name) { std::string tmpName = asLowerCaseString(name); for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it) { if(tmpName == asLowerCaseString(it->second->getName())) return it->second; } return NULL; } Position Spells::getCasterPosition(Creature* creature, Direction dir) { return getNextPosition(dir, creature->getPosition()); } bool BaseSpell::castSpell(Creature* creature) { if(!creature) return false; bool success = true; CreatureEventList castEvents = creature->getCreatureEvents(CREATURE_EVENT_CAST); for(CreatureEventList::iterator it = castEvents.begin(); it != castEvents.end(); ++it) { if(!(*it)->executeCast(creature) && success) success = false; } return success; } bool BaseSpell::castSpell(Creature* creature, Creature* target) { if(!creature || !target) return false; bool success = true; CreatureEventList castEvents = creature->getCreatureEvents(CREATURE_EVENT_CAST); for(CreatureEventList::iterator it = castEvents.begin(); it != castEvents.end(); ++it) { if(!(*it)->executeCast(creature, target) && success) success = false; } return success; } CombatSpell::CombatSpell(Combat* _combat, bool _needTarget, bool _needDirection) : Event(&g_spells->getInterface()) { combat =_combat; needTarget = _needTarget; needDirection = _needDirection; } CombatSpell::~CombatSpell() { if(combat) delete combat; } bool CombatSpell::loadScriptCombat() { if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); combat = env->getCombatObject(env->getLastCombatId()); env->resetCallback(); m_interface->releaseEnv(); } return combat != NULL; } bool CombatSpell::castSpell(Creature* creature) { if(!BaseSpell::castSpell(creature)) return false; if(isScripted()) { LuaVariant var; var.type = VARIANT_POSITION; if(needDirection) var.pos = Spells::getCasterPosition(creature, creature->getDirection()); else var.pos = creature->getPosition(); return executeCastSpell(creature, var); } Position pos; if(needDirection) pos = Spells::getCasterPosition(creature, creature->getDirection()); else pos = creature->getPosition(); combat->doCombat(creature, pos); return true; } bool CombatSpell::castSpell(Creature* creature, Creature* target) { if(!BaseSpell::castSpell(creature, target)) return false; if(isScripted()) { LuaVariant var; if(combat->hasArea()) { var.type = VARIANT_POSITION; if(needTarget) var.pos = target->getPosition(); else if(needDirection) var.pos = Spells::getCasterPosition(creature, creature->getDirection()); else var.pos = creature->getPosition(); } else { var.type = VARIANT_NUMBER; var.number = target->getID(); } return executeCastSpell(creature, var); } if(combat->hasArea()) { if(!needTarget) return castSpell(creature); combat->doCombat(creature, target->getPosition()); } else combat->doCombat(creature, target); return true; } bool CombatSpell::executeCastSpell(Creature* creature, const LuaVariant& var) { //onCastSpell(cid, var) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; env->streamVariant(scriptstream, "var", var); scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[60]; sprintf(desc, "onCastSpell - %s", creature->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); m_interface->pushVariant(L, var); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CombatSpell::executeCastSpell] Call stack overflow." << std::endl; return false; } } Spell::Spell() { level = 0; magLevel = 0; mana = 0; manaPercent = 0; soul = 0; range = -1; exhaustion = 1000; needTarget = false; needWeapon = false; selfTarget = false; blockingSolid = false; blockingCreature = false; enabled = true; premium = false; isAggressive = true; learnable = false; } bool Spell::configureSpell(xmlNodePtr p) { int32_t intValue; std::string strValue; if(readXMLString(p, "name", strValue)) { name = strValue; const char* reservedList[] = { "melee", "physical", "poison", "earth", "fire", "ice", "freeze", "energy", "drown", "death", "curse", "holy", "lifedrain", "manadrain", "healing", "speed", "outfit", "invisible", "drunk", "firefield", "poisonfield", "energyfield", "firecondition", "poisoncondition", "energycondition", "drowncondition", "freezecondition", "cursecondition" }; for(uint32_t i = 0; i < sizeof(reservedList) / sizeof(const char*); ++i) { if(!strcasecmp(reservedList[i], name.c_str())) { std::clog << "Error: [Spell::configureSpell] Spell is using a reserved name: " << reservedList[i] << std::endl; return false; } } } else { std::clog << "Error: [Spell::configureSpell] Spell without name." << std::endl; return false; } if(readXMLInteger(p, "lvl", intValue) || readXMLInteger(p, "level", intValue)) level = intValue; if(readXMLInteger(p, "maglv", intValue) || readXMLInteger(p, "magiclevel", intValue)) magLevel = intValue; if(readXMLInteger(p, "mana", intValue)) mana = intValue; if(readXMLInteger(p, "manapercent", intValue)) manaPercent = intValue; if(readXMLInteger(p, "soul", intValue)) soul = intValue; if(readXMLInteger(p, "exhaustion", intValue)) exhaustion = intValue; if(readXMLString(p, "enabled", strValue)) enabled = booleanString(strValue); if(readXMLString(p, "prem", strValue) || readXMLString(p, "premium", strValue)) premium = booleanString(strValue); if(readXMLString(p, "needtarget", strValue)) needTarget = booleanString(strValue); if(readXMLString(p, "needweapon", strValue)) needWeapon = booleanString(strValue); if(readXMLString(p, "selftarget", strValue)) selfTarget = booleanString(strValue); if(readXMLString(p, "needlearn", strValue)) learnable = booleanString(strValue); if(readXMLInteger(p, "range", intValue)) range = intValue; if(readXMLString(p, "blocking", strValue)) blockingCreature = blockingSolid = booleanString(strValue); if(readXMLString(p, "blocktype", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "all") blockingCreature = blockingSolid = true; else if(tmpStrValue == "solid") blockingSolid = true; else if(tmpStrValue == "creature") blockingCreature = true; else std::clog << "[Warning - Spell::configureSpell] Blocktype \"" <<strValue << "\" does not exist." << std::endl; } if(readXMLString(p, "aggressive", strValue)) isAggressive = booleanString(strValue); std::string error = ""; xmlNodePtr vocationNode = p->children; while(vocationNode) { if(!parseVocationNode(vocationNode, vocSpellMap, vocStringVec, error)) std::clog << "[Warning - Spell::configureSpell] " << error << std::endl; vocationNode = vocationNode->next; } return true; } bool Spell::checkSpell(Player* player) const { if(player->hasFlag(PlayerFlag_CannotUseSpells)) return false; if(player->hasFlag(PlayerFlag_IgnoreSpellCheck)) return true; if(!isEnabled()) return false; bool exhausted = false; if(isAggressive) { if(!player->hasFlag(PlayerFlag_IgnoreProtectionZone) && player->getZone() == ZONE_PROTECTION) { player->sendCancelMessage(RET_ACTIONNOTPERMITTEDINPROTECTIONZONE); return false; } if(player->hasCondition(CONDITION_EXHAUST, EXHAUST_COMBAT)) exhausted = true; } else if(player->hasCondition(CONDITION_EXHAUST, EXHAUST_HEALING)) exhausted = true; if(exhausted && !player->hasFlag(PlayerFlag_HasNoExhaustion)) { player->sendCancelMessage(RET_YOUAREEXHAUSTED); if(isInstant()) g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(isPremium() && !player->isPremium()) { player->sendCancelMessage(RET_YOUNEEDPREMIUMACCOUNT); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if((int32_t)player->getLevel() < level) { player->sendCancelMessage(RET_NOTENOUGHLEVEL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if((int32_t)player->getMagicLevel() < magLevel) { player->sendCancelMessage(RET_NOTENOUGHMAGICLEVEL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(player->getMana() < getManaCost(player) && !player->hasFlag(PlayerFlag_HasInfiniteMana)) { player->sendCancelMessage(RET_NOTENOUGHMANA); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(player->getSoul() < soul && !player->hasFlag(PlayerFlag_HasInfiniteSoul)) { player->sendCancelMessage(RET_NOTENOUGHSOUL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(isInstant() && isLearnable() && !player->hasLearnedInstantSpell(getName())) { player->sendCancelMessage(RET_YOUNEEDTOLEARNTHISSPELL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!vocSpellMap.empty()) { if(vocSpellMap.find(player->getVocationId()) == vocSpellMap.end()) { player->sendCancelMessage(RET_YOURVOCATIONCANNOTUSETHISSPELL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } } if(needWeapon) { switch(player->getWeaponType()) { case WEAPON_SWORD: case WEAPON_CLUB: case WEAPON_AXE: case WEAPON_FIST: break; default: { player->sendCancelMessage(RET_YOUNEEDAWEAPONTOUSETHISSPELL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } } } return true; } bool Spell::checkInstantSpell(Player* player, Creature* creature) { if(!checkSpell(player)) return false; const Position& toPos = creature->getPosition(); const Position& playerPos = player->getPosition(); if(playerPos.z > toPos.z) { player->sendCancelMessage(RET_FIRSTGOUPSTAIRS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(playerPos.z < toPos.z) { player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Tile* tile = g_game.getTile(toPos); if(!tile) { tile = new StaticTile(toPos.x, toPos.y, toPos.z); g_game.setTile(tile); } ReturnValue ret; if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR) { player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(blockingCreature && creature) { player->sendCancelMessage(RET_NOTENOUGHROOM); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(blockingSolid && tile->hasProperty(BLOCKSOLID)) { player->sendCancelMessage(RET_NOTENOUGHROOM); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!needTarget) { if(!isAggressive || player->getSkull() != SKULL_BLACK) return true; player->sendCancelMessage(RET_YOUMAYNOTCASTAREAONBLACKSKULL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!creature) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Player* targetPlayer = creature->getPlayer(); if(!isAggressive || !targetPlayer || Combat::isInPvpZone(player, targetPlayer) || player->getSkullType(targetPlayer) != SKULL_NONE) return true; if(player->getSecureMode() == SECUREMODE_ON) { player->sendCancelMessage(RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(player->getSkull() == SKULL_BLACK) { player->sendCancelMessage(RET_YOUMAYNOTATTACKTHISPLAYER); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } return true; } bool Spell::checkInstantSpell(Player* player, const Position& toPos) { if(!checkSpell(player)) return false; if(toPos.x == 0xFFFF) return true; const Position& playerPos = player->getPosition(); if(playerPos.z > toPos.z) { player->sendCancelMessage(RET_FIRSTGOUPSTAIRS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(playerPos.z < toPos.z) { player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Tile* tile = g_game.getTile(toPos); if(!tile) { tile = new StaticTile(toPos.x, toPos.y, toPos.z); g_game.setTile(tile); } ReturnValue ret; if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR) { player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(blockingCreature && tile->getTopVisibleCreature(player)) { player->sendCancelMessage(RET_NOTENOUGHROOM); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(blockingSolid && tile->hasProperty(BLOCKSOLID)) { player->sendCancelMessage(RET_NOTENOUGHROOM); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(player->getSkull() == SKULL_BLACK && isAggressive && range == -1) //-1 is (usually?) an area spell { player->sendCancelMessage(RET_YOUMAYNOTCASTAREAONBLACKSKULL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } return true; } bool Spell::checkRuneSpell(Player* player, const Position& toPos) { if(!checkSpell(player)) return false; if(toPos.x == 0xFFFF) return true; const Position& playerPos = player->getPosition(); if(playerPos.z > toPos.z) { player->sendCancelMessage(RET_FIRSTGOUPSTAIRS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(playerPos.z < toPos.z) { player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Tile* tile = g_game.getTile(toPos); if(!tile) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(range != -1 && !g_game.canThrowObjectTo(playerPos, toPos, true, range, range)) { player->sendCancelMessage(RET_DESTINATIONOUTOFREACH); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } ReturnValue ret; if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR) { player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Creature* targetCreature = tile->getTopVisibleCreature(player); if(blockingCreature && targetCreature) { player->sendCancelMessage(RET_NOTENOUGHROOM); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(blockingSolid && tile->hasProperty(BLOCKSOLID)) { player->sendCancelMessage(RET_NOTENOUGHROOM); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!needTarget) { if(!isAggressive || player->getSkull() != SKULL_BLACK) return true; player->sendCancelMessage(RET_YOUMAYNOTCASTAREAONBLACKSKULL); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!targetCreature) { player->sendCancelMessage(RET_CANONLYUSETHISRUNEONCREATURES); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Player* targetPlayer = targetCreature->getPlayer(); if(!isAggressive || !targetPlayer || Combat::isInPvpZone(player, targetPlayer) || player->getSkullType(targetPlayer) != SKULL_NONE) return true; if(player->getSecureMode() == SECUREMODE_ON) { player->sendCancelMessage(RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(player->getSkull() == SKULL_BLACK) { player->sendCancelMessage(RET_YOUMAYNOTATTACKTHISPLAYER); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } return true; } void Spell::postSpell(Player* player, bool finishedCast /*= true*/, bool payCost /*= true*/) const { if(finishedCast) { if(!player->hasFlag(PlayerFlag_HasNoExhaustion) && exhaustion > 0) player->addExhaust(exhaustion, isAggressive ? EXHAUST_COMBAT : EXHAUST_HEALING); if(isAggressive && !player->hasFlag(PlayerFlag_NotGainInFight)) player->addInFightTicks(false); } if(payCost) postSpell(player, (uint32_t)getManaCost(player), (uint32_t)getSoulCost()); } void Spell::postSpell(Player* player, uint32_t manaCost, uint32_t soulCost) const { if(manaCost > 0) { player->changeMana(-(int32_t)manaCost); if(!player->hasFlag(PlayerFlag_NotGainMana) && (player->getZone() != ZONE_HARDCORE || g_config.getBool(ConfigManager::PVPZONE_ADDMANASPENT))) player->addManaSpent(manaCost); } if(soulCost > 0) player->changeSoul(-(int32_t)soulCost); } int32_t Spell::getManaCost(const Player* player) const { if(player && manaPercent) return (int32_t)std::floor(double(player->getMaxMana() * manaPercent) / 100); return mana; } ReturnValue Spell::CreateIllusion(Creature* creature, const Outfit_t& outfit, int32_t time) { ConditionOutfit* outfitCondition = new ConditionOutfit(CONDITIONID_COMBAT, CONDITION_OUTFIT, time, false, 0); if(!outfitCondition) return RET_NOTPOSSIBLE; outfitCondition->addOutfit(outfit); creature->addCondition(outfitCondition); return RET_NOERROR; } ReturnValue Spell::CreateIllusion(Creature* creature, const std::string& name, int32_t time) { uint32_t mId = g_monsters.getIdByName(name); if(!mId) return RET_CREATUREDOESNOTEXIST; const MonsterType* mType = g_monsters.getMonsterType(mId); if(!mType) return RET_CREATUREDOESNOTEXIST; Player* player = creature->getPlayer(); if(player && !player->hasFlag(PlayerFlag_CanIllusionAll) && !mType->isIllusionable) return RET_NOTPOSSIBLE; return CreateIllusion(creature, mType->outfit, time); } ReturnValue Spell::CreateIllusion(Creature* creature, uint32_t itemId, int32_t time) { const ItemType& it = Item::items[itemId]; if(!it.id) return RET_NOTPOSSIBLE; Outfit_t outfit; outfit.lookTypeEx = itemId; return CreateIllusion(creature, outfit, time); } InstantSpell::InstantSpell(LuaInterface* _interface) : TalkAction(_interface) { needDirection = false; hasParam = false; checkLineOfSight = true; casterTargetOrDirection = false; limitRange = 0; function = NULL; } bool InstantSpell::configureEvent(xmlNodePtr p) { if(!Spell::configureSpell(p)) return false; if(!TalkAction::configureEvent(p)) return false; std::string strValue; if(readXMLString(p, "param", strValue) || readXMLString(p, "params", strValue)) hasParam = booleanString(strValue); if(readXMLString(p, "direction", strValue)) needDirection = booleanString(strValue); if(readXMLString(p, "casterTargetOrDirection", strValue)) casterTargetOrDirection = booleanString(strValue); if(readXMLString(p, "blockwalls", strValue)) checkLineOfSight = booleanString(strValue); int32_t intValue; if(readXMLInteger(p, "limitRange", intValue)) limitRange = intValue; return true; } bool InstantSpell::loadFunction(const std::string& functionName) { std::string tmpFunctionName = asLowerCaseString(functionName); if(tmpFunctionName == "summonmonster") function = SummonMonster; else if(tmpFunctionName == "searchplayer") { isAggressive = false; function = SearchPlayer; } else if(tmpFunctionName == "levitate") { isAggressive = false; function = Levitate; } else if(tmpFunctionName == "illusion") { isAggressive = false; function = Illusion; } else { std::clog << "[Warning - InstantSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; return false; } m_scripted = EVENT_SCRIPT_FALSE; return true; } bool InstantSpell::castInstant(Player* player, const std::string& param) { LuaVariant var; if(selfTarget) { var.type = VARIANT_NUMBER; var.number = player->getID(); if(!checkInstantSpell(player, player)) return false; } else if(needTarget || casterTargetOrDirection) { Creature* target = NULL; if(hasParam) { Player* targetPlayer = NULL; ReturnValue ret = g_game.getPlayerByNameWildcard(param, targetPlayer); target = targetPlayer; if(limitRange && target && !Position::areInRange(Position(limitRange, limitRange, 0), target->getPosition(), player->getPosition())) target = NULL; if((!target || target->getHealth() <= 0) && !casterTargetOrDirection) { player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } } else { target = player->getAttackedCreature(); if(limitRange && target && !Position::areInRange(Position(limitRange, limitRange, 0), target->getPosition(), player->getPosition())) target = NULL; if((!target || target->getHealth() <= 0) && !casterTargetOrDirection) { player->sendCancelMessage(RET_YOUCANONLYUSEITONCREATURES); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } } if(target) { bool canSee = player->canSeeCreature(target); if(!canSee || !canThrowSpell(player, target)) { player->sendCancelMessage(canSee ? RET_CREATUREISNOTREACHABLE : RET_PLAYERWITHTHISNAMEISNOTONLINE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } var.type = VARIANT_NUMBER; var.number = target->getID(); if(!checkInstantSpell(player, target)) return false; } else { var.type = VARIANT_POSITION; var.pos = Spells::getCasterPosition(player, player->getDirection()); if(!checkInstantSpell(player, var.pos)) return false; } } else if(hasParam) { var.type = VARIANT_STRING; var.text = param; if(!checkSpell(player)) return false; } else { var.type = VARIANT_POSITION; if(needDirection) var.pos = Spells::getCasterPosition(player, player->getDirection()); else var.pos = player->getPosition(); if(!checkInstantSpell(player, var.pos)) return false; } if(!internalCastSpell(player, var)) return false; Spell::postSpell(player); return true; } bool InstantSpell::canThrowSpell(const Creature* creature, const Creature* target) const { const Position& fromPos = creature->getPosition(); const Position& toPos = target->getPosition(); return (!(fromPos.z != toPos.z || (range == -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight)) || (range != -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight, range, range)))); } bool InstantSpell::castSpell(Creature* creature) { if(!BaseSpell::castSpell(creature)) return false; LuaVariant var; if(casterTargetOrDirection) { Creature* target = creature->getAttackedCreature(); if(target && target->getHealth() > 0) { if(!creature->canSeeCreature(target) || !canThrowSpell(creature, target)) return false; var.type = VARIANT_NUMBER; var.number = target->getID(); return internalCastSpell(creature, var); } return false; } if(needDirection) { var.type = VARIANT_POSITION; var.pos = Spells::getCasterPosition(creature, creature->getDirection()); } else { var.type = VARIANT_POSITION; var.pos = creature->getPosition(); } return internalCastSpell(creature, var); } bool InstantSpell::castSpell(Creature* creature, Creature* target) { if(!BaseSpell::castSpell(creature, target)) return false; if(!needTarget) return castSpell(creature); LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); return internalCastSpell(creature, var); } bool InstantSpell::internalCastSpell(Creature* creature, const LuaVariant& var) { if(isScripted()) return executeCastSpell(creature, var); return function ? function(this, creature, var.text) : false; } bool InstantSpell::executeCastSpell(Creature* creature, const LuaVariant& var) { //onCastSpell(cid, var) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; env->streamVariant(scriptstream, "var", var); scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[60]; sprintf(desc, "onCastSpell - %s", creature->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); m_interface->pushVariant(L, var); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - InstantSpell::executeCastSpell] Call stack overflow." << std::endl; return false; } } bool InstantSpell::SearchPlayer(const InstantSpell*, Creature* creature, const std::string& param) { Player* player = creature->getPlayer(); if(!player || player->isRemoved()) return false; Player* targetPlayer = NULL; ReturnValue ret = g_game.getPlayerByNameWildcard(param, targetPlayer); if(ret != RET_NOERROR || !targetPlayer || targetPlayer->isRemoved()) { player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(targetPlayer->hasCustomFlag(PlayerCustomFlag_NotSearchable) && !player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges)) { player->sendCancelMessage(RET_PLAYERWITHTHISNAMEISNOTONLINE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } std::stringstream ss; ss << targetPlayer->getName() << " " << g_game.getSearchString(player->getPosition(), targetPlayer->getPosition(), true, true) << "."; player->sendTextMessage(MSG_INFO_DESCR, ss.str().c_str()); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_BLUE); return true; } bool InstantSpell::SummonMonster(const InstantSpell* spell, Creature* creature, const std::string& param) { Player* player = creature->getPlayer(); if(!player) return false; MonsterType* mType = g_monsters.getMonsterType(param); if(!mType) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } int32_t manaCost = (int32_t)(mType->manaCost * g_config.getDouble(ConfigManager::RATE_MONSTER_MANA)); if(!player->hasFlag(PlayerFlag_CanSummonAll)) { if(player->getSkull() == SKULL_BLACK) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!mType->isSummonable) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(player->getMana() < manaCost) { player->sendCancelMessage(RET_NOTENOUGHMANA); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if((int32_t)player->getSummonCount() >= g_config.getNumber(ConfigManager::MAX_PLAYER_SUMMONS)) { player->sendCancel("You cannot summon more creatures."); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } } ReturnValue ret = g_game.placeSummon(creature, param); if(ret == RET_NOERROR) { spell->postSpell(player, (uint32_t)manaCost, (uint32_t)spell->getSoulCost()); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_BLUE); return true; } player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } bool InstantSpell::Levitate(const InstantSpell*, Creature* creature, const std::string& param) { Player* player = creature->getPlayer(); if(!player) return false; uint16_t floor = 7; ReturnValue ret = RET_NOERROR; const Position& position = creature->getPosition(); Position destination = Spells::getCasterPosition(creature, creature->getDirection()); std::string tmpParam = asLowerCaseString(param); if(tmpParam == "up") floor = 8; else if(tmpParam != "down") ret = RET_NOTPOSSIBLE; if(ret == RET_NOERROR) { ret = RET_NOTPOSSIBLE; if(position.z != floor) { Tile* tmpTile = NULL; if(floor != 7) { tmpTile = g_game.getTile(position.x, position.y, position.z - 1); destination.z--; } else { tmpTile = g_game.getTile(destination); destination.z++; } if(!tmpTile || (!tmpTile->ground && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID))) { Tile* tile = player->getTile(); tmpTile = g_game.getTile(destination); if(tile && tmpTile && tmpTile->ground && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID) && !tmpTile->floorChange() && tile->hasFlag(TILESTATE_HOUSE) == tmpTile->hasFlag(TILESTATE_HOUSE) && tile->hasFlag(TILESTATE_PROTECTIONZONE) == tmpTile->hasFlag(TILESTATE_PROTECTIONZONE)) ret = g_game.internalMoveCreature(NULL, player, tile, tmpTile, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE); } } } if(ret == RET_NOERROR) { g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_TELEPORT, player->isGhost()); return true; } player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF, player->isGhost()); return false; } bool InstantSpell::Illusion(const InstantSpell*, Creature* creature, const std::string& param) { Player* player = creature->getPlayer(); if(!player) return false; ReturnValue ret = CreateIllusion(creature, param, 60000); if(ret == RET_NOERROR) { g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED); return true; } player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return (ret == RET_NOERROR); } bool InstantSpell::canCast(const Player* player) const { if(player->hasFlag(PlayerFlag_CannotUseSpells)) return false; if(player->hasFlag(PlayerFlag_IgnoreSpellCheck) || (!isLearnable() && (vocSpellMap.empty() || vocSpellMap.find(player->getVocationId()) != vocSpellMap.end()))) return true; return player->hasLearnedInstantSpell(getName()); } ConjureSpell::ConjureSpell(LuaInterface* _interface): InstantSpell(_interface) { isAggressive = false; conjureId = 0; conjureCount = 1; conjureReagentId = 0; } bool ConjureSpell::configureEvent(xmlNodePtr p) { if(!InstantSpell::configureEvent(p)) return false; int32_t intValue; if(readXMLInteger(p, "conjureId", intValue)) conjureId = intValue; if(readXMLInteger(p, "conjureCount", intValue)) conjureCount = intValue; else if(conjureId != 0) { //load the default charge from items.xml const ItemType& it = Item::items[conjureId]; if(it.charges != 0) conjureCount = it.charges; } if(readXMLInteger(p, "reagentId", intValue)) conjureReagentId = intValue; return true; } bool ConjureSpell::loadFunction(const std::string& functionName) { std::string tmpFunctionName = asLowerCaseString(functionName); if(tmpFunctionName == "conjureitem" || tmpFunctionName == "conjurerune") function = ConjureItem; else { std::clog << "[Warning - ConjureSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; return false; } m_scripted = EVENT_SCRIPT_FALSE; return true; } ReturnValue ConjureSpell::internalConjureItem(Player* player, uint32_t conjureId, uint32_t conjureCount, bool transform/* = false*/, uint32_t reagentId/* = 0*/, slots_t slot/* = SLOT_WHEREVER*/, bool test/* = false*/) { if(!transform) { Item* newItem = Item::CreateItem(conjureId, conjureCount); if(!newItem) return RET_NOTPOSSIBLE; ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true); if(ret != RET_NOERROR) delete newItem; return ret; } if(!reagentId) return RET_NOTPOSSIBLE; Item* item = player->getInventoryItem(slot); if(item && item->getID() == reagentId) { if(item->isStackable() && item->getItemCount() != 1) return RET_YOUNEEDTOSPLITYOURSPEARS; if(test) return RET_NOERROR; Item* newItem = g_game.transformItem(item, conjureId, conjureCount); if(!newItem) return RET_NOTPOSSIBLE; g_game.startDecay(newItem); return RET_NOERROR; } return RET_YOUNEEDAMAGICITEMTOCASTSPELL; } bool ConjureSpell::ConjureItem(const ConjureSpell* spell, Creature* creature, const std::string&) { Player* player = creature->getPlayer(); if(!player) return false; if(!player->hasFlag(PlayerFlag_IgnoreSpellCheck) && player->getZone() == ZONE_HARDCORE) { player->sendCancelMessage(RET_CANNOTCONJUREITEMHERE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } ReturnValue result = RET_NOERROR; if(spell->getReagentId() != 0) { ReturnValue resLeft = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(), true, spell->getReagentId(), SLOT_LEFT, true); if(resLeft == RET_NOERROR) { resLeft = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(), true, spell->getReagentId(), SLOT_LEFT); if(resLeft == RET_NOERROR) spell->postSpell(player, false); } ReturnValue resRight = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(), true, spell->getReagentId(), SLOT_RIGHT, true); if(resRight == RET_NOERROR) { if(resLeft == RET_NOERROR && !spell->checkSpell(player)) return false; resRight = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(), true, spell->getReagentId(), SLOT_RIGHT); if(resRight == RET_NOERROR) spell->postSpell(player, false); } if(resLeft == RET_NOERROR || resRight == RET_NOERROR) { spell->postSpell(player, true, false); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED); return true; } result = resLeft; if((result == RET_NOERROR && resRight != RET_NOERROR) || (result == RET_YOUNEEDAMAGICITEMTOCASTSPELL && resRight == RET_YOUNEEDTOSPLITYOURSPEARS)) result = resRight; } else if(internalConjureItem(player, spell->getConjureId(), spell->getConjureCount()) == RET_NOERROR) { spell->postSpell(player); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED); return true; } if(result != RET_NOERROR) player->sendCancelMessage(result); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } bool ConjureSpell::castInstant(Player* player, const std::string& param) { if(!checkSpell(player)) return false; if(!isScripted()) return function ? function(this, player, param) : false; LuaVariant var; var.type = VARIANT_STRING; var.text = param; return executeCastSpell(player, var); } RuneSpell::RuneSpell(LuaInterface* _interface): Action(_interface) { runeId = 0; function = NULL; hasCharges = allowFarUse = true; } bool RuneSpell::configureEvent(xmlNodePtr p) { if(!Spell::configureSpell(p)) return false; if(!Action::configureEvent(p)) return false; int32_t intValue; if(readXMLInteger(p, "id", intValue)) runeId = intValue; else { std::clog << "Error: [RuneSpell::configureSpell] Rune spell without id." << std::endl; return false; } std::string strValue; if(readXMLString(p, "charges", strValue)) hasCharges = booleanString(strValue); ItemType& it = Item::items.getItemType(runeId); if(level && level != it.runeLevel) it.runeLevel = level; if(magLevel && magLevel != it.runeMagLevel) it.runeMagLevel = magLevel; it.vocationString = parseVocationString(vocStringVec); return true; } bool RuneSpell::loadFunction(const std::string& functionName) { std::string tmpFunctionName = asLowerCaseString(functionName); if(tmpFunctionName == "chameleon") function = Illusion; else if(tmpFunctionName == "convince") function = Convince; else { std::clog << "[Warning - RuneSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; return false; } m_scripted = EVENT_SCRIPT_FALSE; return true; } bool RuneSpell::Illusion(const RuneSpell*, Creature* creature, Item*, const Position&, const Position& posTo) { Player* player = creature->getPlayer(); if(!player) return false; Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_MOVE); if(!thing) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Item* illusionItem = thing->getItem(); if(!illusionItem || !illusionItem->isMoveable()) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } ReturnValue ret = CreateIllusion(creature, illusionItem->getID(), 60000); if(ret == RET_NOERROR) { g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED); return true; } player->sendCancelMessage(ret); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } bool RuneSpell::Convince(const RuneSpell* spell, Creature* creature, Item*, const Position&, const Position& posTo) { Player* player = creature->getPlayer(); if(!player) return false; if(!player->hasFlag(PlayerFlag_CanConvinceAll)) { if(player->getSkull() == SKULL_BLACK) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if((int32_t)player->getSummonCount() >= g_config.getNumber(ConfigManager::MAX_PLAYER_SUMMONS)) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } } Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_LOOK); if(!thing) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } Creature* convinceCreature = thing->getCreature(); if(!convinceCreature) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } int32_t manaCost = 0; if(Monster* monster = convinceCreature->getMonster()) manaCost = (int32_t)(monster->getManaCost() * g_config.getDouble(ConfigManager::RATE_MONSTER_MANA)); if(!player->hasFlag(PlayerFlag_HasInfiniteMana) && player->getMana() < manaCost) { player->sendCancelMessage(RET_NOTENOUGHMANA); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } if(!convinceCreature->convinceCreature(creature)) { player->sendCancelMessage(RET_NOTPOSSIBLE); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF); return false; } spell->postSpell(player, (uint32_t)manaCost, (uint32_t)spell->getSoulCost()); g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED); return true; } ReturnValue RuneSpell::canExecuteAction(const Player* player, const Position& toPos) { if(player->hasFlag(PlayerFlag_CannotUseSpells)) return RET_CANNOTUSETHISOBJECT; ReturnValue ret = Action::canExecuteAction(player, toPos); if(ret != RET_NOERROR) return ret; if(toPos.x == 0xFFFF) { if(needTarget) return RET_CANONLYUSETHISRUNEONCREATURES; if(!selfTarget) return RET_NOTENOUGHROOM; } return RET_NOERROR; } bool RuneSpell::executeUse(Player* player, Item* item, const PositionEx& posFrom, const PositionEx& posTo, bool, uint32_t creatureId) { if(!checkRuneSpell(player, posTo)) return false; bool result = false; if(isScripted()) { LuaVariant var; if(creatureId && needTarget) { var.type = VARIANT_NUMBER; var.number = creatureId; } else { var.type = VARIANT_POSITION; var.pos = posTo; } result = internalCastSpell(player, var); } else if(function) result = function(this, player, item, posFrom, posTo); if(result) { Spell::postSpell(player); if(hasCharges && item && g_config.getBool(ConfigManager::REMOVE_RUNE_CHARGES)) g_game.transformItem(item, item->getID(), std::max((int32_t)0, ((int32_t)item->getItemCount()) - 1)); } return result; } bool RuneSpell::castSpell(Creature* creature) { if(!BaseSpell::castSpell(creature)) return false; LuaVariant var; var.type = VARIANT_NUMBER; var.number = creature->getID(); return internalCastSpell(creature, var); } bool RuneSpell::castSpell(Creature* creature, Creature* target) { if(!BaseSpell::castSpell(creature, target)) return false; LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); return internalCastSpell(creature, var); } bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var) { return isScripted() ? executeCastSpell(creature, var) : false; } bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var) { //onCastSpell(cid, var) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; env->streamVariant(scriptstream, "var", var); scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[60]; sprintf(desc, "onCastSpell - %s", creature->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); m_interface->pushVariant(L, var); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - RuneSpell::executeCastSpell] Call stack overflow." << std::endl; return false; } }
  14. Boa noite pessoal, Eu estou modificando um ot a algum tempo e gostaria de por as runas por ML (o que eu ja fiz). Eu retirei o requerimento de level no spells/spells.xml e deixei apenas o mglvl das runas. Meu problema é que quando algum player da look nas runas aparece como por exemplo a sudden death: "It can only be used and magic level 15 or higher." Como removi o level a frase de look ficou sem sentido devido ao "and". Alguem sabe qual arquivo devo editar para trocar esse "and" por "with"? desde já agradeço!

Open Tibia Server

Quer aprender a criar seu próprio servidor de Tibia? Então está no lugar certo, aqui você encontrará milhares de tutorias, scripts, códigos, mapas e utilitários para que você possa fazer o seu próprio servidor de Tibia começando do zero.

Redes Sociais

Anuncie no Tibia King

Precisa de mais visibilidade em seus projetos? Quer fazer um plano publicitário para o seu servidor? Anuncie no Tibia King e faça sua divulgação, possuímos centenas de acessos simultâneos e milhares diários, com certeza será a sua solução!

×
×
  • Create New...