Modcraft - The community dedicated to quality WoW modding!

Wrath of the Lich King Modding => Miscellaneous => Topic started by: Nupper on August 06, 2016, 09:26:23 pm

Title: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 06, 2016, 09:26:23 pm
I found code for a third Dungeon Difficulty in the client i was woundering how i could enable it on trinitycore.

Code: [Select]
DUNGEON_DIFFICULTY3 = "Epic (Unused)";
Code: [Select]
UnitPopupButtons["DUNGEON_DIFFICULTY3"] = { text = DUNGEON_DIFFICULTY3, dist = 0 };
I managed to make it visable in-game but atm the button is a dud (I renamed it to Mythic) :)
(http://i66.tinypic.com/adexaa.jpg)
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 06, 2016, 11:21:22 pm
In worldserver.conf, I enabled network debug logging by setting this value:
Code: [Select]
Logger.network=2,Console Server
With this, any time the server runs WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData) (in gameHandlersMiscHandlers.cpp), it prints some debug info in the worldserver console. Then I used /run SetDungeonDifficulty(#). It worked for values of 1 and 2 (normal and heroic), but it didn't seem to send anything to the server with a difficulty value of 3.

That means you probably need to use AIO to send a request to set dungeon difficulty to 3. Hopefully you don't need to otherwise mess with the client to fix the unused difficulty. TrinityCore should be able to set your difficulty to 3 if it receives the request. You'll also need to increment the MAX_DUNGEON_DIFFICULTY constant. Not sure what else you'd need.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 06, 2016, 11:34:01 pm
Quote from: "Grymskvll"
In worldserver.conf, I enabled network debug logging by setting this value:
Code: [Select]
Logger.network=2,Console Server
With this, any time the server runs WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData) (in gameHandlersMiscHandlers.cpp), it prints some debug info in the worldserver console. Then I used /run SetDungeonDifficulty(#). It worked for values of 1 and 2 (normal and heroic), but it didn't seem to send anything to the server with a difficulty value of 3.

That means you probably need to use AIO to send a request to set dungeon difficulty to 3. Hopefully you don't need to otherwise mess with the client to fix the unused difficulty. TrinityCore should be able to set your difficulty to 3 if it receives the request. You'll also need to increment the MAX_DUNGEON_DIFFICULTY constant. Not sure what else you'd need.

Its a new discovery i think why make something for something unused...if you know what i mean i doubt trinity would have anything related to a third Difficulty.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 06, 2016, 11:40:33 pm
Right, but if you wanted to make the button work, you would need to add a way to send the request to change the difficulty (using AIO, probably).

I don't know how dungeon difficulties themselves are implemented.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 06, 2016, 11:47:45 pm
Quote from: "Grymskvll"
Right, but if you wanted to make the button work, you would need to add a way to send the request to change the difficulty (using AIO, probably).

I don't know how dungeon difficulties themselves are implemented.

Yeah a part from the UnitPop.lua i cannot find anything else so far.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: schlumpf on August 07, 2016, 12:54:17 am
https://wowdev.wiki/DB/Difficulty (https://wowdev.wiki/DB/Difficulty" onclick="window.open(this.href);return false;)?
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 07, 2016, 01:26:30 am
Quote from: "schlumpf"
https://wowdev.wiki/DB/Difficulty?
EPIC Dungeon difficulty was unused in wrath
trying to figure how to add it...
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 07, 2016, 03:48:11 am
Quote from: "schlumpf"
https://wowdev.wiki/DB/Difficulty?

On that note, I guess you'd have to add epic difficulty entries in MapDifficulty.dbc.

From what I gather, TrinityCore gets creature stats from the world.creature_template (https://trinitycore.atlassian.net/wiki/display/tc/creature_template#creature_template-difficulty_entry_1-3) database. I'm guessing that you would put a reference to an epic difficulty version of the creature in difficulty_entry_2 of the normal mode creature entry. At least, that's how it's done for raids.

So you would need to create new epic version entries in creature_template for each creature in each dungeon that you want to have an epic difficulty setting, and then reference those new epic versions in difficulty_entry_2 of the normal version.

Of course, that's not all you'd need to do to make the difficulty work.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 07, 2016, 05:56:00 pm
Quote from: "Grymskvll"
You'll also need to increment the MAX_DUNGEON_DIFFICULTY constant. Not sure what else you'd need.

Oops nevermind that, it's not needed at all.

I tried adding an Eluna playermethod for setting dungeon difficulty (so that the button would work), and it worked... but with a major flaw. The client's difficulty doesn't get updated until you relog. I guess you would either have to send some kind of difficulty mode update from the server to the client, or else modify Wow.exe so that it accepts 3 as a valid SetDungeonDifficulty setting.

Edit: oops, just realized that the core has Player::SendDungeonDifficulty built in. After all, it has to update group members' dungeon difficulty when the party leader sets it.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 08, 2016, 03:15:00 am
I'm stuck. I've managed to set dungeon difficulty to Epic from the interface and create an empty Epic difficulty instance, but I can't figure out how to spawn creatures. The earliest function I can find that's called when instance creatures are spawned is Creature::LoadCreatureFromDB, but none of the places that call that function are called when you create a dungeon instance... So what the hell is calling Creature::LoadCreatureFromDB???

If you want to try debugging, here's what I did to enable the Epic dungeon difficulty:

Look up the Map entry you want to have an Epic difficulty in Map.dbc (https://wowdev.wiki/Map.dbc), then in MapDifficulty.dbc (https://wowdev.wiki/DB/MapDifficulty), create a new entry for your Map ID with the difficulty field set to 2 (Epic).

This step wont work since there's something missing, but it will be required if someone figures it out. In your mysql world.creature_template, copy entries for all the heroic versions for creatures in that Map, but change the name to have a "(2)" at the end, just like how heroic versions have "(1)".
Make sure the new Epic entries you make have nothing in the "difficulty_entry_#" fields.
In all the normal mode entries in creature_template, add a reference to the new entry you made in difficulty_entry_2

In WorldSession.h, add this below "void HandleSetDungeonDifficultyOpcode(WorldPacket& recvData);":
Code: [Select]
void HandleSetDungeonDifficulty(Difficulty mode);

In MiscHandler.cpp, add:
Code: [Select]
void WorldSession::HandleSetDungeonDifficulty(Difficulty mode)
{
TC_LOG_DEBUG("network", "MSG_SET_DUNGEON_DIFFICULTY");

if (mode >= MAX_DUNGEON_DIFFICULTY)
{
TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUID().GetCounter(), mode);
return;
}

if (Difficulty(mode) == _player->GetDungeonDifficulty())
return;

// cannot reset while in an instance
Map* map = _player->FindMap();
if (map && map->IsDungeon())
{
TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!",
_player->GetName().c_str(), _player->GetGUID().GetCounter());
return;
}

Group* group = _player->GetGroup();
if (group)
{
if (group->IsLeader(_player->GetGUID()))
{
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* groupGuy = itr->GetSource();
if (!groupGuy)
continue;

if (!groupGuy->IsInMap(groupGuy))
return;

if (groupGuy->GetMap()->IsNonRaidDungeon())
{
TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!",
_player->GetGUID().GetCounter(), groupGuy->GetName().c_str(), groupGuy->GetGUID().GetCounter());
return;
}
}
// the difficulty is set even if the instances can't be reset
//_player->SendDungeonDifficulty(true);
group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player);
group->SetDungeonDifficulty(Difficulty(mode));
}
}
else
{
_player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false);
_player->SetDungeonDifficulty(Difficulty(mode));
}
}

In Eluna's PlayerMethods.h, add:
Code: [Select]
/**
* Sets the [Player]s dungeon difficulty to the specified value
*
* @param uint32 difficulty
*/
int SetDungeonDifficulty(Eluna* /*E*/, lua_State* L, Player* player)
{
Difficulty difficulty = (Difficulty)Eluna::CHECKVAL<uint32>(L, 2, 0);

WorldSession* session = player->GetSession();
session->HandleSetDungeonDifficulty(difficulty);

bool isInGroup = (player->GetGroup() != 0);
player->SendDungeonDifficulty(isInGroup);

return 0;
}

In Eluna's LuaFunctions.cpp, in "ElunaRegister<Player> PlayerMethods[]" add:
Code: [Select]
{ "SetDungeonDifficulty", &LuaPlayer::SetDungeonDifficulty },

And add this AIO script to your server's lua_scripts folder:
Code: [Select]
local AIO = AIO or require("AIO")
AIO.AddAddon()

if AIO.IsServer() then
-- TrinityCore: starting from 0=normal, 1=heroic, 2=epic
local MAX_DUNGEON_DIFFICULTY = 3

function HandlePlayerSetDungeonDifficulty(player, msg)
-- difficulties start at 0 in TrinityCore, 1 in client
msg = tonumber(msg) - 1
if msg >= 0 and msg < MAX_DUNGEON_DIFFICULTY then
player:SetDungeonDifficulty(msg)
end
end
AIO.RegisterEvent("SetDungeonDifficulty", HandlePlayerSetDungeonDifficulty)

return
end


UnitPopupButtons["DUNGEON_DIFFICULTY3"] = { text = DUNGEON_DIFFICULTY3, dist = 0 };
UnitPopupMenus["DUNGEON_DIFFICULTY"] = { "DUNGEON_DIFFICULTY1", "DUNGEON_DIFFICULTY2", "DUNGEON_DIFFICULTY3" };
DUNGEON_DIFFICULTY_5PLAYER_EPIC = "5 Player (Epic)";

function SetDungeonDifficultyCustom(difficulty)
AIO.Msg():Add("SetDungeonDifficulty", difficulty):Send()
end


origSetDungeonDifficulty = SetDungeonDifficulty
SetDungeonDifficulty = function(...)
local difficulty = ...
if difficulty < 3 then
origSetDungeonDifficulty(difficulty)
else
SetDungeonDifficultyCustom(difficulty)
end
end

Apologies if there's any errors, I made some last minute changes as I was copying the code.

Edit: forgot to mention that if you want to try to add a new difficulty, you should try to add a heroic mode to a dungeon that normally doesn't have one first. That doesn't (or at least shouldn't) require the core mods and AIO script above, it should only require mysql database and DBC edits as far as I understand, but I can't even get that to work.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 08, 2016, 11:11:48 pm
Holy shit, all the above DOES work, I just made the mistake of thinking that the server would spawn the Epic versions of creatures if there are Epic entries in world.creature_template, which is NOT the case! But the world.creature_template IS needed for automatically spawning the right version. What I did was enter an Epic instance, used ".npc add [NORMAL world.creature_template entry]", and the server automatically grabs the Epic version (referenced in "difficulty_entry_3" of the normal version of the creature_template).

What's the sane way to copy over all monster spawns from a normal dungeon? From what I understand, they're stored in world.creature
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 08, 2016, 11:46:07 pm
Quote from: "Grymskvll"
What's the sane way to copy over all monster spawns from a normal dungeon? From what I understand, they're stored in world.creature

In world.creature, the spawnMask (https://trinitycore.atlassian.net/wiki/display/tc/creature#creature-spawnMask) column determines which difficulties a creature will spawn on. So if you want to make every creature in a Map spawn for every difficulty, you can just set the spawnMask to 15 ("Spawned in all versions of maps").

To set this spawnMask for all creatures in a specific map, you can use this mysql statement (AT YOUR OWN RISK):
Code: [Select]
UPDATE world.creature SET spawnMask=15 WHERE map=[map ID];
Replace [map ID] with the map you want to change. You still need to add Epic difficulty entries for each creature_template in the dungeon. Otherwise it uses the heroic or normal version as fallback.

As far as I know, that leaves just two imperfections:
-the dungeon portal becomes invisible when you set difficulty to to Epic. If anyone has an idea how the game picks its instance portal models, please let me know
-the little dungeon difficulty indicator when you're inside a dungeon (in the top-right, next to the minimap) just displays "0". Odds are there's no blp for an Epic difficulty (like the skull flag for Heroic), so you probably need to do some interface modding, which wouldn't be an issue since you need to use an AIO script to make the difficulty selection menu work anyway. I'm a little dismayed that I couldn't even get the indicator to show "5", though, even with a modified client-side MapDifficulty.dbc
-game objects don't seem to be spawning, gotta figure out how that stuff works (like the web door in Azjol-Nerub)
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 09, 2016, 09:43:29 am
Quote from: "Grymskvll"
Quote from: "Grymskvll"
What's the sane way to copy over all monster spawns from a normal dungeon? From what I understand, they're stored in world.creature

In world.creature, the spawnMask (https://trinitycore.atlassian.net/wiki/display/tc/creature#creature-spawnMask) column determines which difficulties a creature will spawn on. So if you want to make every creature in a Map spawn for every difficulty, you can just set the spawnMask to 15 ("Spawned in all versions of maps").

To set this spawnMask for all creatures in a specific map, you can use this mysql statement (AT YOUR OWN RISK):
Code: [Select]
UPDATE world.creature SET spawnMask=15 WHERE map=[map ID];
Replace [map ID] with the map you want to change. You still need to add Epic difficulty entries for each creature_template in the dungeon. Otherwise it uses the heroic or normal version as fallback.

As far as I know, that leaves just two imperfections:
-the dungeon portal becomes invisible when you set difficulty to to Epic. If anyone has an idea how the game picks its instance portal models, please let me know
-the little dungeon difficulty indicator when you're inside a dungeon (in the top-right, next to the minimap) just displays "0". Odds are there's no blp for an Epic difficulty (like the skull flag for Heroic), so you probably need to do some interface modding, which wouldn't be an issue since you need to use an AIO script to make the difficulty selection menu work anyway. I'm a little dismayed that I couldn't even get the indicator to show "5", though, even with a modified client-side MapDifficulty.dbc
-game objects don't seem to be spawning, gotta figure out how that stuff works (like the web door in Azjol-Nerub)
I am sure over time theses issues can be resolved :)
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 09, 2016, 10:36:22 pm
To fix gameobjects, you need to set the spawnMask just like we did with creatures:
Code: [Select]
UPDATE world.gameobject SET spawnMask=15 WHERE map=[map ID];

For some reason, the maxplayers and difficultystring values in MapDifficulty.dbc don't get checked for newly created rows, and I can't figure out why. I'm guessing there's something missing in Map.dbc or something. I made a hacky workaround by hooking GetInstanceInfo(). It'll work for 5 man Epic dungeons.

Also I kind of completely neglected Epic raids. Unfortunately, Epic raids would need some more in-depth modding, since in world.creature_template, difficulty_entry_# only goes up to 3, meaning you can have up to 4 difficulty versions including the base. All 4 of these versions are already used by raids for N10, N25, H10 and H25. It could be as simple as adding more columns to the table, I don't know. Other than that you'd need to add another Eluna method (SetRaidDifficulty), get some AIO communication akin to the one I wrote for SetDungeonDifficulty, and add some extra conditions in the hooked GetInstanceInfo() to check for raid and difficulty so that maxplayers and difficultystring returned by it are correct, maybe mess with some core constants, add the necessary client strings, mess with the minimap indicator (more on that below).

Also, for some reason MiniMapInstanceDifficulty_OnEvent can't be overwritten in an AIO script properly. The modified version will just exist side by side with the original, and events will call the original instead of our modified version. That's not a huge problem, since you can just supply a modified Minimap.lua (where the function resides) in a custom patch, which would be necessary if you want Epic difficulty to have a different minimap indicator blp anyway. Speaking of which, I made an Epic difficulty instance banner, it's included in the patch below, along with a modified Minimap.lua

Preview (new epic banner on the right):
(https://i.imgur.com/uWFrMv4.png)

Looking at the banner now, I probably should've reduced the emblem's alpha a tiny bit. Oh well! The attached file also contains the Photoshop document for that image, as well as an updated AIO script.

So right now the issues are:
-invisible instance portal when you select Epic dungeon difficulty (no idea how this works)
-no Epic raid support
-hacky GetInstanceInfo() mod instead of properly loading maxplayers and the difficultystring from MapDifficulty.dbc

Mirror: https://a.fluntcaps.me/nywray.zip
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 09, 2016, 10:55:17 pm
Quote from: "Grymskvll"
To fix gameobjects, you need to set the spawnMask just like we did with creatures:
Code: [Select]
SELECT * FROM world.gameobject WHERE map=[map ID];

For some reason, the maxplayers and difficultystring values in MapDifficulty.dbc don't get checked for newly created rows, and I can't figure out why. I'm guessing there's something missing in Map.dbc or something. I made a hacky workaround by hooking GetInstanceInfo(). It'll work for 5 man Epic dungeons.

Also I kind of completely neglected Epic raids. Unfortunately, Epic raids would need some more in-depth modding, since in world.creature_template, difficulty_entry_# only goes up to 3, meaning you can have up to 4 difficulty versions including the base. All 4 of these versions are already used by raids for N10, N25, H10 and H25. It could be as simple as adding more columns to the table, I don't know. Other than that you'd need to add another Eluna method (SetRaidDifficulty), get some AIO communication akin to the one I wrote for SetDungeonDifficulty, and add some extra conditions in the hooked GetInstanceInfo() to check for raid and difficulty so that maxplayers and difficultystring returned by it are correct, maybe mess with some core constants, add the necessary client strings, mess with the minimap indicator (more on that below).

Also, for some reason MiniMapInstanceDifficulty_OnEvent can't be overwritten in an AIO script properly. The modified version will just exist side by side with the original, and events will call the original instead of our modified version. That's not a huge problem, since you can just supply a modified Minimap.lua (where the function resides) in a custom patch, which would be necessary if you want Epic difficulty to have a different minimap indicator blp anyway. Speaking of which, I made an Epic difficulty instance banner, it's included in the patch below, along with a modified Minimap.lua

Preview (new epic banner on the right):
(https://i.imgur.com/uWFrMv4.png)

Looking at the banner now, I probably should've reduced the emblem's alpha a tiny bit. Oh well! The attached file also contains the Photoshop document for that image, as well as an updated AIO script.

So right now the issues are:
-invisible instance portal when you select Epic dungeon difficulty (no idea how this works)
-no Epic raid support
-hacky GetInstanceInfo() mod instead of properly loading maxplayers and the difficultystring from MapDifficulty.dbc

Mirror: https://a.fluntcaps.me/nywray.zip

Gameobject_Template
Code: [Select]
GAMEOBJECT_TYPE_DUNGEONDIFFICULTY = 31

    data0: mapID (From Map.dbc)
    data1: difficulty

     

     

0 5 man normal, 10 man normal
1 5 man heroic, 25 normal
2 5 Man Epic (Possibily), 10 man heroic
3 25 man heroic
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 09, 2016, 11:02:23 pm
Quote from: "Nupper"

Gameobject_Template
Code: [Select]
GAMEOBJECT_TYPE_DUNGEONDIFFICULTY = 31

    data0: mapID (From Map.dbc)
    data1: difficulty

     

     

0 5 man normal, 10 man normal
1 5 man heroic, 25 normal
2 5 Man Epic (Possibily), 10 man heroic
3 25 man heroic


Sorry, I copied the wrong line. I updated my post to fix it.
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 09, 2016, 11:23:31 pm
Quote from: "Grymskvll"
Quote from: "Nupper"

Gameobject_Template
Code: [Select]
GAMEOBJECT_TYPE_DUNGEONDIFFICULTY = 31

    data0: mapID (From Map.dbc)
    data1: difficulty

     

     

0 5 man normal, 10 man normal
1 5 man heroic, 25 normal
2 5 Man Epic (Possibily), 10 man heroic
3 25 man heroic


Sorry, I copied the wrong line. I updated my post to fix it.

I Renamed it to Mythic
(http://i67.tinypic.com/a2uf47.jpg)
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 09, 2016, 11:49:20 pm
Additional Known Issues

Welcome message displays Heroic

Code: [Select]
Welcome to [Dungeon name] (5 Player (Heroic)). Instance locks are scheduled to expire in [Time Remaining]instead of
Code: [Select]
Welcome to [Dungeon name] (5 Player (Epic)). Instance locks are scheduled to expire in [Time Remaining]
Fixed issue with Instance Portals
When making a new portal 5-man Epic = Data1: 2
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 10, 2016, 12:05:01 am
Quote from: "Nupper"
Additional Known Issues

Welcome message displays Heroic

Code: [Select]
Welcome to [Dungeon name] (5 Player (Heroic)). Instance locks are scheduled to expire in [Time Remaining]instead of
Code: [Select]
Welcome to [Dungeon name] (5 Player (Epic)). Instance locks are scheduled to expire in [Time Remaining]

You need to change the last field in MapDifficulty.dbc to "DUNGEON_DIFFICULTY_5PLAYER_EPIC"


Edit: Oh, I get it! Sorry, I completely misinterpreted an earlier post. So to fix invisible portals, see this post: http://modcraft.io/viewtopic.php?p=56547#p56547 (it refers to the mysql world.gameobject_template table)
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 10, 2016, 12:08:38 am
Quote from: "Grymskvll"
Quote from: "Nupper"
Additional Known Issues

Welcome message displays Heroic

Code: [Select]
Welcome to [Dungeon name] (5 Player (Heroic)). Instance locks are scheduled to expire in [Time Remaining]instead of
Code: [Select]
Welcome to [Dungeon name] (5 Player (Epic)). Instance locks are scheduled to expire in [Time Remaining]

You need to change the last field in MapDifficulty.dbc to "DUNGEON_DIFFICULTY_5PLAYER_EPIC"

Quote
Fixed issue with Instance Portals
When making a new portal 5-man Epic = Data1: 2

Could you elaborate?
(http://i67.tinypic.com/v33h4g.jpg)
Mythic Mode (Epic) Instance portal
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 10, 2016, 12:13:46 am
Sorry, I misinterpreted your earlier post  :D
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 10, 2016, 09:51:28 am
Quote from: "Grymskvll"
Sorry, I misinterpreted your earlier post  :D
i assume the spawn Masks would follow suit...
0
   

Not spawned

1
   

Spawned only in 10-man-normal versions of maps (includes maps without a heroic mode)

2
   

Spawned only in 25-man-normal versions of maps (or heroics Dungeons)

4
   

Spawned only in 10-man heroic versions of maps (or Epic Dungeons (Untested))

8
   

Spawned only in 25-man-heroic versions of maps

15
   

Spawned in all versions of maps
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Grymskvll on August 24, 2016, 08:47:00 pm
To add a custom tooltip line for Epic difficulty items, you need to make some changes to Wow.exe (or alternatively do some Lua tooltip modding).

This is for WotLK 3.3.5 12340

Backup your Wow.exe.

Also, this probably requires that you've already patched Wow.exe to load custom interface files.

Open up notepad and copy this over:
Code: [Select]
OFFSET_1 =
OFFSET_2 =
OFFSET_3 =
OFFSET_4 =
OFFSET_5 =
OFFSET_6 =

Open Wow.exe in OllyDbg.
Right click, search for -> All referenced strings
In the strings window, hit ctrl+f and find "ITEM_HEROIC".
Double click it and it'll take you to something that looks like this (the addresses might be slightly different):
Code: [Select]
00627BA3      F641 18 08               TEST BYTE PTR DS:[ECX+18],08
00627BA7      74 24                    JE SHORT 00627BCD
00627BA9  |> /56                       PUSH ESI
00627BAA  |. |6A FF                    PUSH -1
00627BAC  |. |68 4866A200              PUSH OFFSET 00A26648         ; ASCII "ITEM_HEROIC"
00627BB1  |> |E8 8A211F00              CALL 00819D40
00627BB6  |. |83C4 0C                  ADD ESP,0C
00627BB9  |. |56                       PUSH ESI
00627BBA  |. |68 402DAD00              PUSH OFFSET 00AD2D40
00627BBF  |. |68 402DAD00              PUSH OFFSET 00AD2D40
00627BC4  |> |56                       PUSH ESI
00627BC5  |. |50                       PUSH EAX
00627BC6  |> |8BCF                     MOV ECX,EDI
00627BC8  |. |E8 F382FFFF              CALL 0061FEC0              ; Wow.0061FEC0
00627BCD  |> |3975 F0                  CMP DWORD PTR SS:[EBP-10],ESI
Right click the first "PUSH ESI" line (2 higher than the line with the ASCII comment), Edit->Copy address
Paste the address after OFFSET_1 in Notepad
Do the same for "CALL 00819D40" as OFFSET_2
Do the same for "CMP DWORD PTR SS:[EBP-10],ESI" as OFFSET_3

Now scroll to the bottom where you just see a bunch of lines that say "DB 00" (you can press Page Up/Down to advance one page at a time).
Pick a nice empty spot with 60 empty bytes. I chose 009DE3C0
Write down the address you choose as OFFSET_4
Calculate OFFSET_4 + 0x13 (http://www.miniwebtool.com/hex-calculator/), write it down as OFFSET_5.
Calculate OFFSET_4 + 0x24, write it down as OFFSET_6
Starting at your OFFSET_4, enter these lines, replacing OFFSET_# with your addresses:
Code: [Select]
TEST BYTE PTR DS:[ECX+18],01
JE SHORT OFFSET_5
PUSH ESI
PUSH -1
PUSH OFFSET_6
JMP OFFSET_2
TEST BYTE PTR DS:[ECX+18],08
JE OFFSET_3
JMP OFFSET_1

Press ctrl+G and go to OFFSET_6.
Right click the highlighted line, go to Edit -> Binary edit
Put your cursor at the leftmost place in the HEX field, right click and paste this (make sure "Keep size" is UNCHECKED):
Code: [Select]
49 54 45 4D 5F 48 45 52 4F 49 43 5F 45 50 49 43
5F 43 55 53 54 4F 4D 00 00 00 00

This will turn into ASCII "ITEM_HEROIC_EPIC_CUSTOM", which will be the name of our global Lua variable that holds the string we want to show in the tooltip.

Select all the red lines, right click -> Edit -> Copy to executable.
Don't close the popup, minimize it or drag it to the side so you can still find it.

Go back to the main window.
Press ctrl+G and go to OFFSET_1.
Select the two lines above it that say "TEST..." and "JE SHORT..."
Right click, Edit->Fill with NOPs
Then, with the red NOP lines still selected press space to edit them to:
Code: [Select]
JMP OFFSET_4
NOP

Select these 2 red lines, right click -> Edit -> Copy to executable.

Now go to the popup from before, right click -> Save to file...
Choose a name you'll recognize, like Wow_tooltip_test.exe.
Close OllyDbg.

Next you just need to add a string for ITEM_HEROIC_EPIC_CUSTOM to GlobalStrings.lua

Extract the most up-to-date GobalStrings.lua from your game archives (or if you've already modified it, grab your modified one).
Open GlobalStrings.lua, search for "ITEM_HEROIC_EPIC".
Under it, add this line, replacing the string with whatever you like
Code: [Select]
ITEM_HEROIC_EPIC_CUSTOM = "Epic Dungeon loot";

Save and pack into a custom MPQ or load it straight from WowInterfaceFrameXML

Finally, to create an item with this new tooltip line, set the 0x01 flag for the item in world.item_template.
If you're changing an existing item, remember to delete your client cache (WowcacheWDB).

If you don't know how to change the flag properly, take the old "flags" value from your world.item_template item row, convert to hex, add 0x01, convert back to decimal and enter it back into your database.

A warning is due, though. The 0x01 flag isn't used and its purpose is unknown, but it's possible that it will interfere with something. If the mod works but it crashes at a (random?) point, or has some other weird behavior, let me know. If this happens and you want to try to fix it, check documentation for the "flags" field in world.item_template and see which other flags are unused. You'll need to modify the condition we added for the 0x01 flag and update item flags.

Here's the result:
(https://i.imgur.com/E8LFsEt.jpg)
Title: Re: [QUESTION:Wrath]  New Dungeon Difficulty
Post by: Nupper on August 27, 2016, 02:02:07 am
ITEM_HEROIC_EPIC is already in Exe...if i can find the flags for it its easy :P