INTRODUCTION & PROBLEM
Hello, i am sharing this fix for a vulnerability that i examined after seeing a topic on a foreign forum that included the explanation and solution of a friend who discovered this problem, and then decided that it required a detailed control on the server src side. If i need to briefly talk about the vulnerability, let me quote from the friend who wrote the first topic that mentioned this problem;
Bitte melden Sie sich an, um dieses Bild zu sehen.
WHAT DID WE CHANGE?
In the original topic, this problem was solved via Client Src, but this is a very unhealthy method, because bypassing a control on the Clientside can sometimes be much easier than you think, so i created a more robust fix for this, it does not only include Bouquet, but also all marriage items and items such as Fishing Rod/Pickaxe are controlled on the serverside, after this fix, cheats using this method will not work anymore.
HOW TO DO?
Let's start, first open the "char.cpp" file from Game Src.
- // Find;
- bool CHARACTER::CanMove() const
- // Add ABOVE;
- (If you have; C++17 and above support then use this)
- // START OF DevFix 129
- bool CHARACTER::IsPCAbleToAttack() const
- {
- if (!IsPC())
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> Only PCs able to use this function! %s Try to use this!", GetName());
- return false;
- }
- // Wedding Item Vnums. - [MT2Dev Note]
- constexpr int BOUQUET_VNUM_MIN = 50201;
- constexpr int BOUQUET_VNUM_MAX = 50204;
- constexpr int WEDDING_S_VNUM_MIN = 11901;
- constexpr int WEDDING_S_VNUM_MAX = 11904;
- constexpr int WEDDING_D_VNUM_MIN = 11911;
- constexpr int WEDDING_D_VNUM_MAX = 11914;
- // If PC try to attack while wearing rod or pick, return false. - [MT2Dev Note]
- if (const auto Wear_Weapon = GetWear (WEAR_WEAPON))
- {
- if (Wear_Weapon->GetType() == ITEM_ROD || Wear_Weapon->GetType() == ITEM_PICK)
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> %s tried to attack with pick/rod!", GetName());
- return false;
- }
- }
- // If PC try to attack while wearing bouquet, return false. - [MT2Dev Note]
- if (const auto Part_Weapon = GetWear (PART_WEAPON))
- {
- if (Part_Weapon->GetVnum() >= BOUQUET_VNUM_MIN && Part_Weapon->GetVnum() <= BOUQUET_VNUM_MAX)
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> %s tried to attack with bouquet!", GetName());
- return false;
- }
- }
- // If PC try to attack while wearing wedding suit/dresses, return false. - [MT2Dev Note]
- if (const auto Part_Body = GetWear (PART_MAIN))
- {
- if ((Part_Body->GetVnum() >= WEDDING_S_VNUM_MIN && Part_Body->GetVnum() <= WEDDING_S_VNUM_MAX) ||
- (Part_Body->GetVnum() >= WEDDING_D_VNUM_MIN && Part_Body->GetVnum() <= WEDDING_D_VNUM_MAX))
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> %s tried to attack while wearing marriage suit/dress!", GetName());
- return false;
- }
- }
- return true;
- }
- // END OF DevFix 129
- (If you need old version support then use this)
- // START OF DevFix 129
- bool CHARACTER::IsPCAbleToAttack() const
- {
- if (!IsPC())
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> Only PCs able to use this function! %s Try to use this!", GetName());
- return false;
- }
- const auto Wear_Weapon = GetWear (WEAR_WEAPON);
- const auto Part_Weapon = GetWear (PART_WEAPON);
- const auto Part_Body = GetWear (PART_MAIN);
- // If PC try to attack while wearing rod or pick, return false. - [MT2Dev Note]
- if (Wear_Weapon && (Wear_Weapon->GetType() == ITEM_ROD || Wear_Weapon->GetType() == ITEM_PICK))
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> %s tried to attack with pick/rod!", GetName());
- return false;
- }
- // If PC try to attack while wearing bouquet, return false. - [MT2Dev Note]
- if (Part_Weapon && (Part_Weapon->GetVnum() >= 50201 && Part_Weapon->GetVnum() <= 50204)) // Bouquet vnums hard-coded in here.. - [MT2Dev Note]
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> %s tried to attack with bouquet!", GetName());
- return false;
- }
- // If PC try to attack while wearing wedding suit/dresses, return false. - [MT2Dev Note]
- if (Part_Body && ((Part_Body->GetVnum() >= 11901 && Part_Body->GetVnum() <= 11904) ||
- (Part_Body->GetVnum() >= 11911 && Part_Body->GetVnum() <= 11914))) // Suit/dress vnums hard-coded in here.. - [MT2Dev Note]
- {
- sys_log (2, "<CHARACTER::IsPCAbleToAttack> %s tried to attack while wearing marriage suit/dress!", GetName());
- return false;
- }
- return true;
- }
- // END OF DevFix 129
Then open "char.h"
Lastly open "char_battle.cpp"
- // bool CHARACTER::Attack (LPCHARACTER pkVictim, BYTE bType) FIND AT THE TOP IN FUNCTION;
- if (!CanMove())
- {
- return false;
- }
- // ADD BELOW;
- // START OF DevFix 129
- if (IsPC() && !IsPCAbleToAttack())
- {
- if (test_server)
- {
- ChatPacket (CHAT_TYPE_INFO, "<Control> Cannot attack while wearing this equipments!");
- }
- return false;
- }
- // END OF DevFix 129
- // bool CHARACTER::Damage (LPCHARACTER pAttacker, int dam, EDamageType type) FIND AT THE TOP IN FUNCTION;
- if (DAMAGE_TYPE_MAGIC == type)
- {
- dam = (int) ((float) dam * (100 + (pAttacker->GetPoint (POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint (POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f);
- }
- // ADD ABOVE (MIND: Inside the func!);
- // START OF DevFix 129
- if (pAttacker && pAttacker->IsPC() && !pAttacker->IsPCAbleToAttack())
- {
- SendDamagePacket (pAttacker, 0, DAMAGE_BLOCK);
- return false;
- }
- // END OF DevFix 129
Best regards, MT2Dev.