Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions config.lua.dist
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
-- Crystal Server Configuration

-- MySQL
mysqlHost = "127.0.0.1"
mysqlUser = "root"
mysqlPass = "root"
mysqlDatabase = "crystalserver"
mysqlPort = 3306
mysqlSock = ""
passwordType = "sha1"
mysqlDatabaseBackup = false

-- Core settings
-- If you want to use the global datapack folder, put "data-global"
-- if you want use Crystal Server map, put "data-crystal"
Expand Down Expand Up @@ -334,13 +344,6 @@ minTownIdToBankTransferFromMain = 4
stashMoving = false
stashManageAmount = 100000

-- Special tiles and Free Town
-- NOTE: Special tiles and free town ID are independent.
-- NOTE: Set toggleSpecialTiles to true if you want to use the system.
-- NOTE: freeTownId = 8 is Thais city.
freeTownId = 8
toggleSpecialTiles = false

-- Cosmetics
-- NOTE: enableSupportOutfit enable GODS and GMS to select support outfit (gamemaster, customer support or community manager)
enableSupportOutfit = true
Expand Down Expand Up @@ -468,16 +471,6 @@ premiumToCreateMarketOffer = true
checkExpiredMarketOffersEachMinutes = 60
maxMarketOffersAtATimePerPlayer = 100

-- MySQL
mysqlHost = "127.0.0.1"
mysqlUser = "root"
mysqlPass = "root"
mysqlDatabase = "crystalserver"
mysqlPort = 3306
mysqlSock = ""
passwordType = "sha1"
mysqlDatabaseBackup = false

-- NOTE: memoryConst: This is the memory cost for the Argon2 hash algorithm. It specifies the amount of memory that the algorithm will use when calculating a hash.
--The memory cost is measured in units of KiB (1024 bytes). A higher memory cost makes the algorithm more resistant to brute-force and hash-table attacks, but also consumes more memory.
-- NOTE: temporaryConst: This is the time cost for the Argon2 hash algorithm. It specifies the amount of computational time that the algorithm will spend when calculating a hash.
Expand All @@ -498,7 +491,6 @@ resetSessionsOnStartup = false
-- NOTE: disableLegacyRaids: set to true to disable legacy XML raids
-- NOTE: logPlayersStatements will log all player statements.
allowChangeOutfit = true
freePremium = false
kickIdlePlayerAfterMinutes = 15
maxMessageBuffer = 4
allowWalkthrough = true
Expand All @@ -525,6 +517,15 @@ maxElementalResistance = 200
maxDamageReflection = 200
logPlayersStatements = false

-- Premium
-- Comma-separated list of towns treated as free for non-premium players
-- NOTE: "Ab'Dendriel,Carlin,Kazordoon,Thais,Venore,Rookgaard,Dawnport,Dawnport Tutorial,Island of Destiny,Karmia"
-- NOTE: freePremium: set to true to give all players premium status
-- NOTE: freeTownName: set the town name where non-premium players will be teleported when trying to login in premium areas
freePremium = false
freeTownName = "Thais"
freeTowns = "Ab'Dendriel,Carlin,Kazordoon,Thais,Venore,Rookgaard,Dawnport,Dawnport Tutorial,Island of Destiny,Karmia"

-- Chain system
-- NOTE: combatChainDelay: set to minimum 50 miliseconds
-- NOTE: chainSystemModifyMagic will increase power of wands and rods based on player magic level
Expand Down
33 changes: 0 additions & 33 deletions data-global/scripts/creaturescripts/others/login.lua

This file was deleted.

8 changes: 0 additions & 8 deletions data/XML/specialtiles.xml

This file was deleted.

2 changes: 2 additions & 0 deletions src/config/config_enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ enum ConfigKey_t : uint16_t {
LEAVE_PARTY_ON_DEATH,
TOGGLE_SPECIAL_TILES,
FREE_TOWN_ID,
FREE_TOWN_NAME,
FREE_TOWNS,
UI_ACTIONS_DELAY_INTERVAL,
MARKET_ACTIONS_DELAY_INTERVAL,
IMBUEMENT_ACTIONS_DELAY_INTERVAL,
Expand Down
4 changes: 2 additions & 2 deletions src/config/configmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ bool ConfigManager::load() {
loadBoolConfig(L, UNLOCK_ALL_MOUNTS, "unlockAllMounts", false);
loadBoolConfig(L, UNLOCK_ALL_FAMILIARS, "unlockAllFamiliars", false);
loadBoolConfig(L, LEAVE_PARTY_ON_DEATH, "leavePartyOnDeath", false);
loadBoolConfig(L, TOGGLE_SPECIAL_TILES, "toggleSpecialTiles", false);
loadBoolConfig(L, TOGGLE_GUILDHALL_NEED_GUILD, "toggleGuildHallNeedGuild", true);
loadBoolConfig(L, TOGGLE_MAX_CONNECTIONS_BY_IP, "toggleMaxConnectionsByIP", false);
loadBoolConfig(L, TOGGLE_GUILD_WARS, "toggleGuildWars", false);
Expand Down Expand Up @@ -401,7 +400,6 @@ bool ConfigManager::load() {
loadIntConfig(L, ROOK_SLOT_AMMO, "rookSlotAmmo", 0);
loadIntConfig(L, DAYS_TO_CLOSE_BID, "daysToCloseBid", 7);
loadIntConfig(L, ANIMUS_MASTERY_MONSTERS_TO_INCREASE_XP_MULTIPLIER, "animusMasteryMonstersToIncreaseXpMultiplier", 10);
loadIntConfig(L, FREE_TOWN_ID, "freeTownId", 8);
loadIntConfig(L, UI_ACTIONS_DELAY_INTERVAL, "uiActionsDelay", 1000);
loadIntConfig(L, MARKET_ACTIONS_DELAY_INTERVAL, "marketActionsDelay", 1000);
loadIntConfig(L, IMBUEMENT_ACTIONS_DELAY_INTERVAL, "imbueActionsDelay", 1000);
Expand Down Expand Up @@ -429,10 +427,12 @@ bool ConfigManager::load() {
loadStringConfig(L, SERVER_MOTD, "serverMotd", "");
loadStringConfig(L, SERVER_NAME, "serverName", "");
loadStringConfig(L, STORE_IMAGES_URL, "coinImagesURL", "");
loadStringConfig(L, FREE_TOWNS, "freeTowns", "");
loadStringConfig(L, TIBIADROME_CONCOCTION_TICK_TYPE, "tibiadromeConcoctionTickType", "online");
loadStringConfig(L, URL, "url", "");
loadStringConfig(L, WORLD_TYPE, "worldType", "pvp");
loadStringConfig(L, LOGLEVEL, "logLevel", "info");
loadStringConfig(L, FREE_TOWN_NAME, "freeTownName", "Thais");

loadLuaOTCFeatures(L);

Expand Down
2 changes: 1 addition & 1 deletion src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11255,7 +11255,7 @@ void Player::onCreatureAppear(const std::shared_ptr<Creature> &creature, bool is
}

g_game().changePlayerSpeed(static_self_cast<Player>(), 0);
g_game().checkSpecialTiles(static_self_cast<Player>());
g_game().checkFreeTown(static_self_cast<Player>());
IOLoginData::updateOnlineStatus(guid, true);
}
}
Expand Down
1 change: 0 additions & 1 deletion src/crystalserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,6 @@ void CrystalServer::loadModules() {
g_ioBosstiary().loadBoostedBoss();
g_ioprey().initializeTaskHuntOptions();
g_game().logCyclopediaStats();
g_game().loadSpecialTiles();
}

void CrystalServer::modulesLoadHelper(bool loaded, std::string moduleName) {
Expand Down
99 changes: 43 additions & 56 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1600,12 +1600,6 @@ ReturnValue Game::internalMoveCreature(const std::shared_ptr<Creature> &creature
Position destPos = getNextPosition(direction, currentPos);
const auto &player = creature->getPlayer();

// special tiles
if (player && isSpecialTile(destPos) && !player->isPremium()) {
player->sendCancelWalk();
return RETURNVALUE_YOUNEEDPREMIUMACCOUNT;
}

bool diagonalMovement = (direction & DIRECTION_DIAGONAL_MASK) != 0;
if (player && !diagonalMovement) {
// try go up
Expand Down Expand Up @@ -11754,73 +11748,66 @@ bool Game::processBankAuction(std::shared_ptr<Player> player, const std::shared_
return true;
}

void Game::loadSpecialTiles() {
if (!g_configManager().getBoolean(TOGGLE_SPECIAL_TILES)) {
void Game::checkFreeTown(const std::shared_ptr<Player> &player) {
if (!player || player->isPremium() || player->isVip()) {
return;
}

pugi::xml_document doc;
const std::string folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/specialtiles.xml";
const pugi::xml_parse_result result = doc.load_file(folder.c_str());

if (!result) {
printXMLError(__FUNCTION__, folder, result);
const auto &freeTownsStr = g_configManager().getString(FREE_TOWNS);
if (freeTownsStr.empty()) {
return;
}

specialTiles.clear();

pugi::xml_node root = doc.child("specialtiles");

for (pugi::xml_node tileNode : root.children("tile")) {
int x = tileNode.attribute("x").as_int();
int y = tileNode.attribute("y").as_int();
int z = tileNode.attribute("z").as_int();
specialTiles.insert(Position(x, y, z));
auto freeTowns = explodeString(freeTownsStr, ",");
for (auto &name : freeTowns) {
trimString(name);
}

for (pugi::xml_node tilesNode : root.children("tiles")) {
int fromX = tilesNode.attribute("fromX").as_int();
int fromY = tilesNode.attribute("fromY").as_int();
int fromZ = tilesNode.attribute("fromZ").as_int();
int toX = tilesNode.attribute("toX").as_int();
int toY = tilesNode.attribute("toY").as_int();

for (int x = fromX; x <= toX; ++x) {
for (int y = fromY; y <= toY; ++y) {
specialTiles.insert(Position(x, y, fromZ));
}
}
const auto &currentTown = player->getTown();
if (!currentTown) {
return;
}

g_logger().info("Loaded {} special tiles from Special Tiles System", specialTiles.size());
}

bool Game::isSpecialTile(const Position &pos) const {
return specialTiles.find(pos) != specialTiles.end();
}

void Game::checkSpecialTiles(const std::shared_ptr<Player> &player) {
if (!player || player->isPremium() || player->isVip()) {
const auto &currentTownName = currentTown->getName();
const bool isInFreeArea = std::ranges::find(freeTowns, currentTownName) != freeTowns.end();
if (isInFreeArea) {
return;
}

const auto freeTownId = g_configManager().getNumber(FREE_TOWN_ID);
const auto &freeTown = g_game().map.towns.getTown(freeTownId);
if (!freeTown) {
const auto freeTownName = g_configManager().getString(FREE_TOWN_NAME);
auto defaultTown = g_game().map.towns.getTown(freeTownName);
if (!defaultTown) {
return;
}

const auto &playerPos = player->getPosition();
const auto freeTownTemplePosition = freeTown->getTemplePosition();
if (isSpecialTile(playerPos)) {
player->sendTextMessage(MESSAGE_ADMINISTRATOR, "Your premium has expired. You are being teleported to a free town.");
Position freeTemplePosition(freeTownTemplePosition);
internalTeleport(player, freeTemplePosition, false);
player->loginPosition = freeTownTemplePosition;
player->setTown(freeTown);
g_saveManager().savePlayer(player);
const auto &templePos = defaultTown->getTemplePosition();
internalTeleport(player, Position(templePos), false);
player->setTown(defaultTown);
player->sendTextMessage(MESSAGE_FAILURE, "Your premium time has expired!");

Outfit_t outfit = player->getDefaultOutfit();
if (player->getSex() == PLAYERSEX_MALE) {
outfit.lookType = 128;
} else {
outfit.lookType = 136;
}
outfit.lookHead = 114;
outfit.lookBody = 120;
outfit.lookLegs = 132;
outfit.lookFeet = 115;
outfit.lookAddons = 0;
player->setDefaultOutfit(outfit);
internalCreatureChangeOutfit(player, outfit);

const auto house = g_game().map.houses.getHouseByPlayerId(player->getGUID());
if (house) {
house->setOwner(0, true, player);
transferHouseItemsToDepot();
player->sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "You have lost your house because you are no longer a premium account.");
player->sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "Your items from the house have been sent to your inbox.");
}

g_saveManager().savePlayer(player);
}

bool Game::isSwimmingPool(const std::shared_ptr<Item> &item, const std::shared_ptr<Tile> &tile, bool checkProtection) const {
Expand Down
4 changes: 1 addition & 3 deletions src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,7 @@ class Game {
return playersRecord;
}

void loadSpecialTiles();
bool isSpecialTile(const Position &pos) const;
void checkSpecialTiles(const std::shared_ptr<Player> &player);
void checkFreeTown(const std::shared_ptr<Player> &player);

bool isSwimmingPool(const std::shared_ptr<Item> &item, const std::shared_ptr<Tile> &tile, bool checkProtection) const;
void createIllusion(const std::shared_ptr<Player> &player, const Outfit_t &outfit, int32_t time);
Expand Down
Loading