diff options
-rw-r--r-- | sql/updates/hotfixes/master/2019_08_24_00_hotfixes.sql | 10 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.cpp | 3 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.h | 2 | ||||
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.cpp | 393 | ||||
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2LoadInfo.h | 14 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 6 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 80 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 4 | ||||
-rw-r--r-- | src/server/game/Server/Packets/CharacterPackets.cpp | 6 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_debug.cpp | 69 |
13 files changed, 584 insertions, 9 deletions
diff --git a/sql/updates/hotfixes/master/2019_08_24_00_hotfixes.sql b/sql/updates/hotfixes/master/2019_08_24_00_hotfixes.sql new file mode 100644 index 00000000000..7604d377375 --- /dev/null +++ b/sql/updates/hotfixes/master/2019_08_24_00_hotfixes.sql @@ -0,0 +1,10 @@ +-- +-- Table structure for table `world_state_expression` +-- +DROP TABLE IF EXISTS `world_state_expression`; +CREATE TABLE `world_state_expression` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `Expression` text, + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index e93d72bfb08..5dcc28fd544 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -1090,6 +1090,9 @@ void HotfixDatabaseConnection::DoPrepareStatements() // WorldSafeLocs.db2 PrepareStatement(HOTFIX_SEL_WORLD_SAFE_LOCS, "SELECT ID, AreaName, LocX, LocY, LocZ, MapID, Facing FROM world_safe_locs ORDER BY ID DESC", CONNECTION_SYNCH); PREPARE_LOCALE_STMT(HOTFIX_SEL_WORLD_SAFE_LOCS, "SELECT ID, AreaName_lang FROM world_safe_locs_locale WHERE locale = ?", CONNECTION_SYNCH); + + // WorldStateExpression.db2 + PrepareStatement(HOTFIX_SEL_WORLD_STATE_EXPRESSION, "SELECT ID, Expression FROM world_state_expression ORDER BY ID DESC", CONNECTION_SYNCH); } HotfixDatabaseConnection::HotfixDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index e31704bebe7..18aa7c60cf7 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -572,6 +572,8 @@ enum HotfixDatabaseStatements : uint32 HOTFIX_SEL_WORLD_SAFE_LOCS, HOTFIX_SEL_WORLD_SAFE_LOCS_LOCALE, + HOTFIX_SEL_WORLD_STATE_EXPRESSION, + MAX_HOTFIXDATABASE_STATEMENTS }; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 37c2e980459..598c1000758 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -23,6 +23,7 @@ #include "DB2Stores.h" #include "GameEventMgr.h" #include "GameObject.h" +#include "GameTime.h" #include "Group.h" #include "InstanceScript.h" #include "Item.h" @@ -33,12 +34,14 @@ #include "PhasingHandler.h" #include "Player.h" #include "Pet.h" +#include "Realm.h" #include "ReputationMgr.h" #include "ScriptMgr.h" #include "SpellAuras.h" #include "SpellMgr.h" #include "World.h" #include "WorldSession.h" +#include <random> char const* const ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX] = { @@ -2771,7 +2774,17 @@ bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditio } // TODO: time condition - // TODO (or not): world state expression condition + + if (condition->WorldStateExpressionID) + { + WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(condition->WorldStateExpressionID); + if (!worldStateExpression) + return false; + + if (!IsPlayerMeetingExpression(player, worldStateExpression)) + return false; + } + // TODO: weather condition if (condition->Achievement[0]) @@ -2869,3 +2882,381 @@ bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditio return true; } + +ByteBuffer HexToBytes(const std::string& hex) +{ + ByteBuffer buffer; + buffer.resize(hex.length() / 2); + HexStrToByteArray(hex, buffer.contents()); + return buffer; +} + +static int32(* const WorldStateExpressionFunctions[WSE_FUNCTION_MAX])(Player const*, uint32, uint32) = +{ + // WSE_FUNCTION_NONE + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_RANDOM + [](Player const* /*player*/, uint32 arg1, uint32 arg2) -> int32 + { + return irand(std::min(arg1, arg2), std::max(arg1, arg2)); + }, + + // WSE_FUNCTION_MONTH + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return GameTime::GetDateAndTime()->tm_mon + 1; + }, + + // WSE_FUNCTION_DAY + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return GameTime::GetDateAndTime()->tm_mday + 1; + }, + + // WSE_FUNCTION_TIME_OF_DAY + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + tm const* localTime = GameTime::GetDateAndTime(); + return localTime->tm_hour * MINUTE + localTime->tm_min; + }, + + // WSE_FUNCTION_REGION + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return realm.Id.Region; + }, + + // WSE_FUNCTION_CLOCK_HOUR + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + uint32 currentHour = GameTime::GetDateAndTime()->tm_hour + 1; + return currentHour <= 12 ? (currentHour ? currentHour : 12) : currentHour - 12; + }, + + // WSE_FUNCTION_OLD_DIFFICULTY_ID + [](Player const* player, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(player->GetMap()->GetDifficultyID())) + return difficulty->OldEnumValue; + + return -1; + }, + + // WSE_FUNCTION_HOLIDAY_START + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_HOLIDAY_LEFT + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_HOLIDAY_ACTIVE + [](Player const* /*player*/, uint32 arg1, uint32 /*arg2*/) -> int32 + { + return int32(IsHolidayActive(HolidayIds(arg1))); + }, + + // WSE_FUNCTION_TIMER_CURRENT_TIME + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return GameTime::GetGameTime(); + }, + + // WSE_FUNCTION_WEEK_NUMBER + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + time_t now = GameTime::GetGameTime(); + uint32 raidOrigin = 1135695600; + if (Cfg_RegionsEntry const* region = sCfgRegionsStore.LookupEntry(realm.Id.Region)) + raidOrigin = region->Raidorigin; + + return (now - raidOrigin) / WEEK; + }, + + // WSE_FUNCTION_UNK13 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK14 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_DIFFICULTY_ID + [](Player const* player, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return player->GetMap()->GetDifficultyID(); + }, + + // WSE_FUNCTION_WAR_MODE_ACTIVE + [](Player const* player, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return player->HasPlayerFlag(PLAYER_FLAGS_WAR_MODE_ACTIVE); + }, + + // WSE_FUNCTION_UNK17 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK18 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK19 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK20 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK21 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_WORLD_STATE_EXPRESSION + [](Player const* player, uint32 arg1, uint32 /*arg2*/) -> int32 + { + if (WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(arg1)) + return ConditionMgr::IsPlayerMeetingExpression(player, worldStateExpression); + + return 0; + }, + + // WSE_FUNCTION_KEYSTONE_AFFIX + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK24 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK25 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK26 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK27 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_KEYSTONE_LEVEL + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK29 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK30 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK31 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK32 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_MERSENNE_RANDOM + [](Player const* /*player*/, uint32 arg1, uint32 arg2) -> int32 + { + if (arg1 == 1) + return 1; + + // init with predetermined seed + std::mt19937 mt(arg2 ? arg2 : 1); + return mt() % arg1 + 1; + }, + + // WSE_FUNCTION_UNK34 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK35 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UNK36 + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + + // WSE_FUNCTION_UI_WIDGET_DATA + [](Player const* /*player*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32 + { + return 0; + }, + +}; + +int32 EvalSingleValue(ByteBuffer& buffer, Player const* player) +{ + WorldStateExpressionValueType valueType = buffer.read<WorldStateExpressionValueType>(); + int32 value = 0; + + switch (valueType) + { + case WorldStateExpressionValueType::Constant: + { + value = buffer.read<int32>(); + break; + } + case WorldStateExpressionValueType::WorldState: + { + uint32 worldStateId = buffer.read<uint32>(); + value = sWorld->getWorldState(worldStateId); + break; + } + case WorldStateExpressionValueType::Function: + { + uint32 functionType = buffer.read<uint32>(); + int32 arg1 = EvalSingleValue(buffer, player); + int32 arg2 = EvalSingleValue(buffer, player); + + if (functionType >= WSE_FUNCTION_MAX) + return 0; + + value = WorldStateExpressionFunctions[functionType](player, arg1, arg2); + } + default: + break; + } + + return value; +} + +int32 EvalValue(ByteBuffer& buffer, Player const* player) +{ + int32 leftValue = EvalSingleValue(buffer, player); + + WorldStateExpressionOperatorType operatorType = buffer.read<WorldStateExpressionOperatorType>(); + if (operatorType == WorldStateExpressionOperatorType::None) + return leftValue; + + int32 rightValue = EvalSingleValue(buffer, player); + + switch (operatorType) + { + case WorldStateExpressionOperatorType::Sum: return leftValue + rightValue; + case WorldStateExpressionOperatorType::Substraction: return leftValue - rightValue; + case WorldStateExpressionOperatorType::Multiplication: return leftValue * rightValue; + case WorldStateExpressionOperatorType::Division: return !rightValue ? 0 : leftValue / rightValue; + case WorldStateExpressionOperatorType::Remainder: return !rightValue ? 0 : leftValue % rightValue; + default: + break; + } + + return leftValue; +} + +bool EvalRelOp(ByteBuffer& buffer, Player const* player) +{ + int32 leftValue = EvalValue(buffer, player); + + WorldStateExpressionComparisonType compareLogic = buffer.read<WorldStateExpressionComparisonType>(); + if (compareLogic == WorldStateExpressionComparisonType::None) + return leftValue != 0; + + int32 rightValue = EvalValue(buffer, player); + + switch (compareLogic) + { + case WorldStateExpressionComparisonType::Equal: return leftValue == rightValue; + case WorldStateExpressionComparisonType::NotEqual: return leftValue != rightValue; + case WorldStateExpressionComparisonType::Less: return leftValue < rightValue; + case WorldStateExpressionComparisonType::LessOrEqual: return leftValue <= rightValue; + case WorldStateExpressionComparisonType::Greater: return leftValue > rightValue; + case WorldStateExpressionComparisonType::GreaterOrEqual: return leftValue >= rightValue; + default: + break; + } + + return false; +} + +bool ConditionMgr::IsPlayerMeetingExpression(Player const* player, WorldStateExpressionEntry const* expression) +{ + ByteBuffer buffer = HexToBytes(expression->Expression); + if (buffer.empty()) + return false; + + bool enabled = buffer.read<bool>(); + if (!enabled) + return false; + + bool finalResult = EvalRelOp(buffer, player); + WorldStateExpressionLogic resultLogic = buffer.read<WorldStateExpressionLogic>(); + + while (resultLogic != WorldStateExpressionLogic::None) + { + bool secondResult = EvalRelOp(buffer, player); + + switch (resultLogic) + { + case WorldStateExpressionLogic::And: finalResult = finalResult && secondResult; break; + case WorldStateExpressionLogic::Or: finalResult = finalResult || secondResult; break; + case WorldStateExpressionLogic::Xor: finalResult = finalResult != secondResult; break; + default: + break; + } + + if (buffer.rpos() < buffer.size()) + break; + + resultLogic = buffer.read<WorldStateExpressionLogic>(); + } + + return finalResult; +} diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 618931fa2cd..eab6c09b16f 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -32,6 +32,7 @@ class WorldObject; class LootTemplate; struct Condition; struct PlayerConditionEntry; +struct WorldStateExpressionEntry; /*! Documentation on implementing a new ConditionType: Step 1: Check for the lowest free ID. Look for CONDITION_UNUSED_XX in the enum. @@ -286,6 +287,7 @@ class TC_GAME_API ConditionMgr bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player* player, Creature* vendor) const; static bool IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition); + static bool IsPlayerMeetingExpression(Player const* player, WorldStateExpressionEntry const* expression); struct ConditionTypeInfo { diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h index 7e5a4c66c71..63d1f7382ca 100644 --- a/src/server/game/DataStores/DB2LoadInfo.h +++ b/src/server/game/DataStores/DB2LoadInfo.h @@ -5558,4 +5558,18 @@ struct WorldSafeLocsLoadInfo } }; +struct WorldStateExpressionLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_STRING_NOT_LOCALIZED, "Expression" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, WorldStateExpressionMeta::Instance(), HOTFIX_SEL_WORLD_STATE_EXPRESSION); + return &loadInfo; + } +}; + #endif // DB2LoadInfo_h__ diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 6b5731d0bb9..9f933d962c3 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -275,6 +275,7 @@ DB2Storage<WMOAreaTableEntry> sWMOAreaTableStore("WMOAreaTable DB2Storage<WorldEffectEntry> sWorldEffectStore("WorldEffect.db2", WorldEffectLoadInfo::Instance()); DB2Storage<WorldMapOverlayEntry> sWorldMapOverlayStore("WorldMapOverlay.db2", WorldMapOverlayLoadInfo::Instance()); DB2Storage<WorldSafeLocsEntry> sWorldSafeLocsStore("WorldSafeLocs.db2", WorldSafeLocsLoadInfo::Instance()); +DB2Storage<WorldStateExpressionEntry> sWorldStateExpressionStore("WorldStateExpression.db2", WorldStateExpressionLoadInfo::Instance()); TaxiMask sTaxiNodesMask; TaxiMask sOldContinentsNodesMask; @@ -733,6 +734,7 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) LOAD_DB2(sWorldEffectStore); LOAD_DB2(sWorldMapOverlayStore); LOAD_DB2(sWorldSafeLocsStore); + LOAD_DB2(sWorldStateExpressionStore); #undef LOAD_DB2 diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 3d224c857cb..5fbe3b0737a 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -58,6 +58,7 @@ TC_GAME_API extern DB2Storage<BattlePetSpeciesEntry> sBattlePetSp TC_GAME_API extern DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore; TC_GAME_API extern DB2Storage<BattlemasterListEntry> sBattlemasterListStore; TC_GAME_API extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore; +TC_GAME_API extern DB2Storage<Cfg_RegionsEntry> sCfgRegionsStore; TC_GAME_API extern DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore; TC_GAME_API extern DB2Storage<CharTitlesEntry> sCharTitlesStore; TC_GAME_API extern DB2Storage<ChatChannelsEntry> sChatChannelsStore; @@ -210,6 +211,7 @@ TC_GAME_API extern DB2Storage<VehicleSeatEntry> sVehicleSeat TC_GAME_API extern DB2Storage<WorldEffectEntry> sWorldEffectStore; TC_GAME_API extern DB2Storage<WorldMapOverlayEntry> sWorldMapOverlayStore; TC_GAME_API extern DB2Storage<WorldSafeLocsEntry> sWorldSafeLocsStore; +TC_GAME_API extern DB2Storage<WorldStateExpressionEntry> sWorldStateExpressionStore; struct TaxiPathBySourceAndDestination { diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 71958a94791..a9dac88860e 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -3272,5 +3272,11 @@ struct WorldSafeLocsEntry float Facing; }; +struct WorldStateExpressionEntry +{ + uint32 ID; + char const* Expression; +}; + #pragma pack(pop) #endif diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index dd180cbdfd6..6bb6b4ebfa1 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -1177,4 +1177,84 @@ enum WorldMapTransformsFlags WORLD_MAP_TRANSFORMS_FLAG_DUNGEON = 0x04 }; +enum class WorldStateExpressionValueType : uint8 +{ + Constant = 1, + WorldState = 2, + Function = 3 +}; + +enum class WorldStateExpressionLogic : uint8 +{ + None = 0, + And = 1, + Or = 2, + Xor = 3, +}; + +enum class WorldStateExpressionComparisonType : uint8 +{ + None = 0, + Equal = 1, + NotEqual = 2, + Less = 3, + LessOrEqual = 4, + Greater = 5, + GreaterOrEqual = 6, +}; + +enum class WorldStateExpressionOperatorType : uint8 +{ + None = 0, + Sum = 1, + Substraction = 2, + Multiplication = 3, + Division = 4, + Remainder = 5, +}; + +enum WorldStateExpressionFunctions +{ + WSE_FUNCTION_NONE = 0, + WSE_FUNCTION_RANDOM, + WSE_FUNCTION_MONTH, + WSE_FUNCTION_DAY, + WSE_FUNCTION_TIME_OF_DAY, + WSE_FUNCTION_REGION, + WSE_FUNCTION_CLOCK_HOUR, + WSE_FUNCTION_OLD_DIFFICULTY_ID, + WSE_FUNCTION_HOLIDAY_START, + WSE_FUNCTION_HOLIDAY_LEFT, + WSE_FUNCTION_HOLIDAY_ACTIVE, + WSE_FUNCTION_TIMER_CURRENT_TIME, + WSE_FUNCTION_WEEK_NUMBER, + WSE_FUNCTION_UNK13, + WSE_FUNCTION_UNK14, + WSE_FUNCTION_DIFFICULTY_ID, + WSE_FUNCTION_WAR_MODE_ACTIVE, + WSE_FUNCTION_UNK17, + WSE_FUNCTION_UNK18, + WSE_FUNCTION_UNK19, + WSE_FUNCTION_UNK20, + WSE_FUNCTION_UNK21, + WSE_FUNCTION_WORLD_STATE_EXPRESSION, + WSE_FUNCTION_KEYSTONE_AFFIX, + WSE_FUNCTION_UNK24, + WSE_FUNCTION_UNK25, + WSE_FUNCTION_UNK26, + WSE_FUNCTION_UNK27, + WSE_FUNCTION_KEYSTONE_LEVEL, + WSE_FUNCTION_UNK29, + WSE_FUNCTION_UNK30, + WSE_FUNCTION_UNK31, + WSE_FUNCTION_UNK32, + WSE_FUNCTION_MERSENNE_RANDOM, + WSE_FUNCTION_UNK34, + WSE_FUNCTION_UNK35, + WSE_FUNCTION_UNK36, + WSE_FUNCTION_UI_WIDGET_DATA, + + WSE_FUNCTION_MAX, +}; + #endif diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ea3dc0021ca..879b7499e10 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -405,8 +405,8 @@ enum PlayerFlags PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards PLAYER_FLAGS_IN_PVP = 0x00000200, - PLAYER_FLAGS_HIDE_HELM = 0x00000400, - PLAYER_FLAGS_HIDE_CLOAK = 0x00000800, + PLAYER_FLAGS_WAR_MODE_ACTIVE = 0x00000400, + PLAYER_FLAGS_WAR_MODE_DESIRED = 0x00000800, PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000, diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index 1739ef13eb9..981ac12d226 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -67,12 +67,6 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel if (atLoginFlags & AT_LOGIN_RESURRECT) playerFlags &= ~PLAYER_FLAGS_GHOST; - if (playerFlags & PLAYER_FLAGS_HIDE_HELM) - Flags |= CHARACTER_FLAG_HIDE_HELM; - - if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) - Flags |= CHARACTER_FLAG_HIDE_CLOAK; - if (playerFlags & PLAYER_FLAGS_GHOST) Flags |= CHARACTER_FLAG_GHOST; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index edd69688e0e..e7b1db5060f 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -43,6 +43,7 @@ EndScriptData */ #include "RBAC.h" #include "SpellPackets.h" #include "Transport.h" +#include "World.h" #include "WorldSession.h" #include <fstream> #include <limits> @@ -102,6 +103,8 @@ public: { "raidreset", rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, false, &HandleDebugRaidResetCommand, "" }, { "neargraveyard", rbac::RBAC_PERM_COMMAND_NEARGRAVEYARD, false, &HandleDebugNearGraveyard, "" }, { "conversation" , rbac::RBAC_PERM_COMMAND_DEBUG_CONVERSATION, false, &HandleDebugConversationCommand, "" }, + { "worldstate" , rbac::RBAC_PERM_COMMAND_DEBUG, false, &HandleDebugWorldStateCommand, "" }, + { "wsexpression" , rbac::RBAC_PERM_COMMAND_DEBUG, false, &HandleDebugWSExpressionCommand, "" }, }; static std::vector<ChatCommand> commandTable = { @@ -1299,6 +1302,72 @@ public: return Conversation::CreateConversation(conversationEntry, target, *target, { target->GetGUID() }) != nullptr; } + + static bool HandleDebugWorldStateCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + char const* worldStateIdStr = strtok((char*)args, " "); + char const* valueStr = args ? strtok(nullptr, " ") : nullptr; + + if (!worldStateIdStr) + return false; + + Player* target = handler->getSelectedPlayerOrSelf(); + + if (!target) + { + handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 worldStateId = atoi(worldStateIdStr); + uint32 value = valueStr ? atoi(valueStr) : 0; + + if (value) + { + sWorld->setWorldState(worldStateId, value); + target->SendUpdateWorldState(worldStateId, value); + } + else + handler->PSendSysMessage("Worldstate %u actual value : %u", worldStateId, sWorld->getWorldState(worldStateId)); + + return true; + } + + static bool HandleDebugWSExpressionCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + char const* expressionIdStr = strtok((char*)args, " "); + + if (!expressionIdStr) + return false; + + uint32 expressionId = atoi(expressionIdStr); + Player* target = handler->getSelectedPlayerOrSelf(); + + if (!target) + { + handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); + handler->SetSentErrorMessage(true); + return false; + } + + WorldStateExpressionEntry const* wsExpressionEntry = sWorldStateExpressionStore.LookupEntry(expressionId); + if (!wsExpressionEntry) + return false; + + if (sConditionMgr->IsPlayerMeetingExpression(target, wsExpressionEntry)) + handler->PSendSysMessage("Expression %u meet", expressionId); + else + handler->PSendSysMessage("Expression %u not meet", expressionId); + + return true; + }; }; void AddSC_debug_commandscript() |