Core/DataStores: Implemented WorldStateExpression

This commit is contained in:
Traesh
2018-10-23 16:20:45 +02:00
committed by Shauren
parent 11674e2721
commit 548d79bb06
13 changed files with 584 additions and 9 deletions

View File

@@ -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;

View File

@@ -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)

View File

@@ -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
};

View File

@@ -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;
}

View File

@@ -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
{

View File

@@ -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__

View File

@@ -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

View File

@@ -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
{

View File

@@ -3272,5 +3272,11 @@ struct WorldSafeLocsEntry
float Facing;
};
struct WorldStateExpressionEntry
{
uint32 ID;
char const* Expression;
};
#pragma pack(pop)
#endif

View File

@@ -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

View File

@@ -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,

View File

@@ -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;

View File

@@ -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()