• This is a read only backup of the old Emudevs forum. If you want to have anything removed, please message me on Discord: KittyKaev

[SOLVED] Solo Dungeon

Status
Not open for further replies.

ExonatioN

Noble Member
Hey guys..
My question is: Is there a way to lets say, edit RFC (5 mans dungeon low level), to a one mans instance, what I MEAN IS: So only one guy can enter it, and not possible that more can enter it, so if there's 2 in group and one already entered it, it says "There's too many in already".

Thanks, if it's possible, how, and where? Core? DBC editing? If so, please explain how.
Extra question: Is the possible to make the dungeon based on their stats or would that be a too hard and big script? Thanks.
 

Mathex

Respected Member
Hmm, I don't think this is possible because Blizzard only included 5 man, 10 man and 25 man and therefore you must script it in C++. Make a trigger when they enter Ragefire Chasm, add the to an array or what you'd like and then if they're in group with anyone in the array when entering send the message and teleport them out or display an error. I'm aware that this is a hack-fix but that's what would work at least.
 

ExonatioN

Noble Member
Hmm... that would maybe work out, maybe i should try that if there's no other ways to do it. Thanks Mathex :)
 

Tommy

Founder
If you open the Map.cpp file (src/server/game/Maps/Map.cpp), look for:

zhptkR6.png


That checks to see if a player 'Can Enter' an instance.


I don't get your extra question. Do you want to limit dungeons based on players stats?
 

ExonatioN

Noble Member
Because I never done something as this, then i might need some extra assistance, i now searched for that line and found:

Code:
bool InstanceMap::CanEnter (Player *player)
{
    if (player->GetMapRef().getTarget() == this)
    {
        sLog->outError("InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
        ASSERT(false);
        return false;
    }


What's my next step? Thanks.. xD.
To be honest, I have mostly been doing basic core edits, spell fixes, spell procs, custom scripts and that stuff. Spell functions and yeah..
 

Tommy

Founder
Well, the function is quite big; however, it is pretty easy to understand.

Here is what you want: Only one player to enter a dungeon, without a group. (Solo)

Handling that would require some minor tweaks. Who knows, they could be handling it in another spot too, never know until we find out! Anyway, you see the:


Code:
    if (player->isGameMaster())

        return Map::CanEnter(player);
You could easily check to see if the player is not a GM and do the same like they did. For example:

Code:
    if (!player->isGameMaster())

        return Map::CanEnter(player);

So, instead of battling the rest of the code, you could do that. Or, to make it better, check to see if the player is in a group, if so, don't let them continue:

Code:
    if (!player->isGameMaster() && !player->GetGroup())

        return Map::CanEnter(player);

"!player->GetGroup()" checks if the player isn't in a group. Well, it tries to get the group, but if it can't the player isn't in a group.


I don't know if I would see this as a hacky fix or not, seeing I don't know if this is the only place to handle such solotivity!
 

ExonatioN

Noble Member
Thanks a lot Tommy! To make sure, if i want this done in RFC, then I'll be adding if (!player->isGameMaster() && !player->GetGroup())

return Map::CanEnter(player); to that instance .cpp, is that correct, if so any clue exactly where? I have a feeling i have to do it in map.cpp but then it will make it all a 1 mans instance.


I mean yes i could add it in map.cpp but then it would make it 1 man with all instances or? (As said above)


I have tried adding that line to the maps.cpp and when i enter RFC i get this error (on worldserver - NO CRASH)


InstanceMap::SEtResetSchedule: cannot turn schedule on, there is no save information for instance <map [id: 89, name: Ragefire Chasml, instance id: 1>

Looking forward to your reply, thanks!
 
Last edited:

Tommy

Founder
Thanks a lot Tommy! To make sure, if i want this done in RFC, then I'll be adding if (!player->isGameMaster() && !player->GetGroup())

return Map::CanEnter(player); to that instance .cpp, is that correct, if so any clue exactly where? I have a feeling i have to do it in map.cpp but then it will make it all a 1 mans instance.


I mean yes i could add it in map.cpp but then it would make it 1 man with all instances or? (As said above)


I have tried adding that line to the maps.cpp and when i enter RFC i get this error (on worldserver - NO CRASH)


InstanceMap::SEtResetSchedule: cannot turn schedule on, there is no save information for instance <map [id: 89, name: Ragefire Chasml, instance id: 1>

Looking forward to your reply, thanks!

You should just changed the function like I explained without using 'Map::CanEnter(player)' anywhere. Lemme run it and see what happens.


Works just fine for me without any errors (in console).

https://github.com/Arkania/ArkCORE/blob/master/src/server/game/Maps/Map.cpp

Line (2203-2260):

Code:
bool InstanceMap::CanEnter (Player *player)
{
    if (player->GetMapRef().getTarget() == this)
    {
        sLog->outError("InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
        ASSERT(false);
        return false;
    }


    // allow GM's to enter
    if (!player->isGameMaster() && !player->GetGroup())

        return Map::CanEnter(player);


    // cannot enter if the instance is full (player cap), GMs don't count
    uint32 maxPlayers = GetMaxPlayers();
    if (GetPlayersCountExceptGMs() >= maxPlayers)
    {
        sLog->outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
        player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
        return false;
    }


    // cannot enter while an encounter is in progress on raids
    /*Group *pGroup = player->GetGroup();
     if (!player->isGameMaster() && pGroup && pGroup->InCombatToInstance(GetInstanceId()) && player->GetMapId() != GetId())*/
    if (IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress())
    {
        player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT);
        return false;
    }


    // cannot enter if instance is in use by another party/soloer that have a
    // permanent save in the same instance id


    PlayerList const &playerList = GetPlayers();


    if (!playerList.isEmpty())
        for (PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i)
            if (Player *iPlayer = i->getSource())
            {
                if (iPlayer->isGameMaster())          // bypass GMs
                    continue;
                if (!player->GetGroup())          // player has not group and there is someone inside, deny entry
                {
                    player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
                    return false;
                }
                // player inside instance has no group or his groups is different to entering player's one, deny entry
                if (!iPlayer->GetGroup() || iPlayer->GetGroup() != player->GetGroup())
                {
                    player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
                    return false;
                }
                break;
            }


    return Map::CanEnter(player);
}


However, this doesn't pertain to raids. Let me fine the raid code.


---------------------------------------------------------------

Okay, after a brief search through trinity_strings and tracking down the language data type, I found where the raid group is handled.

Inside of MapManager.cpp, look on line 152. You should find:

ngsWqdb.png


Or nearby anyway.

After that, scroll down until you see:

Code:
    Group* group = player->GetGroup();
    if (entry->IsRaid())
    {
        // can only enter in a raid group
        if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID))

        {
            // probably there must be special opcode, because client has this string constant in GlobalStrings.lua
            // TODO: this is not a good place to send the message
            player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetArkCoreString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName);
            sLog->outDebug(LOG_FILTER_MAPS, "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName(), mapName);
            return false;
        }
    }

Actually, there lies a configuration setting!

Code:
!sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID)


The configuration setting:

Code:
#
#    Instance.IgnoreRaid
#        Description: Ignore raid group requirement when entering instances.
#        Default:     0 - (Disabled)
#                     1 - (Enabled)

Instance.IgnoreRaid = 0


There you go!
 

ExonatioN

Noble Member
Thanks once again, Tommy. I'm on the phone and about to go to the bed. I will try it later, and give results!
 

ExonatioN

Noble Member
I'm currently first trying with the dungeons. I really appreciate this, i really do.


EDIT: I added a if (!player->GetGroup())
sLog->outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), player->GetName());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false;



Now when i enter i get to the start zone (which is fine) BUT it happens on all dungeons, and i only need it on RFC. Thanks!


To clear it out fast: When I enter every dungeon I will get to the start zone (If i'm in a group) And i only need it in RFC.
 
Last edited:

Rochet2

Moderator / Eluna Dev
Oh no you cant.
Hmm ..

Cant you get the mapID and check if it is the right one and if not, dont do anything?
You can get a lot of info from the map.
 
Last edited:

Tommy

Founder
I'm currently first trying with the dungeons. I really appreciate this, i really do.


EDIT: I added a if (!player->GetGroup())
sLog->outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), player->GetName());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false;



Now when i enter i get to the start zone (which is fine) BUT it happens on all dungeons, and i only need it on RFC. Thanks!


To clear it out fast: When I enter every dungeon I will get to the start zone (If i'm in a group) And i only need it in RFC.

If you only need it in RFC, do this:
Code:
    if (player->isGameMaster() || GetId() == 389 && !player->GetGroup())

        return Map::CanEnter(player);
 

ExonatioN

Noble Member
Hmm... There's something weird going on, you sure that it's the right code.

It some kind of only works for me if i use
Code:
if (player->isGameMaster() || GetId() == 389 && !player->GetGroup())

        return Map::CanEnter(player); 
sLog->outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), player->GetName());
		player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
                    return false;

AND that will make it a one mans instance in all instances, so that might not work correctly.

If i use if (player->isGameMaster() || GetId() == 389 && !player->GetGroup())

return Map::CanEnter(player); Then nothing happens at all.
 
Status
Not open for further replies.
Top