Modcraft - The community dedicated to quality WoW modding!

Wrath of the Lich King Modding => Serverside Modding => Topic started by: bizzlesnaff on July 04, 2015, 03:15:45 am

Title: [SOLVED] [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 04, 2015, 03:15:45 am
Hey guys,

I try today to set the pvp stat of every player to ffa, when they entered a specific map (9999)
So...I searched some time and, yeah, thats what i tried out..

Code: [Select]
#include "ScriptPCH.h"

class OnMapEnter : public PlayerScript
{
public:
OnMapEnter() : PlayerScript("OnMapEnter") {}

void OnPlayerEnterMap(Map* map, Player* player)
{

if (player->GetMapId() == 9999)
player->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}

};

void AddSC_OnMapEnter()
{
new OnMapEnter();
}

I can compile it, but ingame it didn't work...
Someone an idea ;)?
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Kaev on July 04, 2015, 09:27:31 am
Did you add it to the ScriptLoader? Don't just say yes, look in the file.  I thought i already addes scripts there, but never did.. :P
If yes: Does the Script trigger at all? Print out a message before changing the flag for testing.
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 04, 2015, 02:48:04 pm
void AddSC_OnMapEnter(); and AddSC_OnMapEnter();, yes it's in the scriptloader ;)

I'm not quit sure, if I understand the second part. Do you mean I should print out some text, if someone enter the map?

Edit:
tried also to write something like :
Code: [Select]
if (player->GetMapId() == 9999)
player->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
return (true);
but it's always an error, when i write "return true", and just "return" doesn't change anything..
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 04, 2015, 04:27:26 pm
OnPlayerEnterMap is not a hook.

If you look in ScriptMgr.cpp you see that OnPlayerEnterMap triggers the hook OnMapChanged, which is what you should be using as well.
C++ has this great new keyword "override" and I recommend using it.
It makes sure the function actually overrides a virtual function like it is supposed to.


Code: [Select]
#include "ScriptPCH.h"

class OnMapEnter : public PlayerScript
{
public:
    OnMapEnter() : PlayerScript("OnMapEnter") { }

    void OnMapChanged(Player* player) override
    {
        if (player->GetMapId() == 9999)
            player->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
    }

};

void AddSC_OnMapEnter()
{
    new OnMapEnter();
}

By adding prints Kaev meant that you should add code that outputs something to the worldserver console or elsewhere so you can see that the code actually runs.
For example
Code: [Select]
printf("Does this appear in console?n");

If the code above still does not work, it might be that the flags are reverted back after the hook runs.
Many hooks actually execute BEFORE the event actually happens.
You can make a function trigger after the event by using a timed event with 0 as the delay so it will execute "as soon as possible".
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 04, 2015, 07:13:52 pm
I used the code now, and added just this:
Code: [Select]
printf("FFA worked?n");
In the console it appears (sadly everytime any player change the map) not only if a player join my map.
But as you said it doesn't work.
I really don't like to leach code, but can u explain me how this should work?
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 04, 2015, 09:02:32 pm
Most likely (did not check) the player enter map hook runs before updatezone function is called for the player.
In that function call the pvp flags are set again.

Incase you want to have the pvp flag on even though the player changes zones, you might want to use the update zone hook.

For the timed event, See how BasicEvent is used.

It goes about like this:

Code: [Select]
class MyEvent : public BasicEvent
{
MyEvent(Player* player) : player {}
    bool Execute(uint32, uin64)
{
// my code to do on timed event
return true;
}
Player* player;
};

player->m_events->ScheduleEvent(new MyEvent(player), player->m_events->CalculateTime(0));

Wrote that from memory so dont expect it to work without edits.
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 05, 2015, 02:05:02 am
Okay, I searched some time arround copied many things and worked...something...out :D

Code: [Select]
#include "ScriptPCH.h"


#include "ScriptPCH.h"

enum Enums
{
FIRST_TELEDELAY = 1000,

};

struct Event
{
uint8 Events;
};
static std::map<uint32, Event> _events;

class Teleport : public BasicEvent
{
public:
Teleport(Player* player) : _Plr(player) {}

bool Execute(uint64 /*time*/, uint32 /*diff*/)
{
uint32 pEvent;
pEvent = _Plr->GetGUID();

switch (_events[pEvent].Events)
{
case 0: // First Teleport
if (_Plr->GetMapId() == 9999)
_Plr->SetPvP(true);
_Plr->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
_events[pEvent].Events = 1;
break;

}
return true;
}
Player* _Plr;
};

class OnMapEnter : public PlayerScript
{
public:
OnMapEnter() : PlayerScript("OnMapEnter") {}

void OnChangeMap(Player* player)
{
if (player->GetMapId() == 9999)
player->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
printf("FFA worked?n");
player->m_Events.AddEvent(new Teleport(player), player->m_Events.CalculateTime(FIRST_TELEDELAY));
}
};

void AddSC_OnMapEnter()
{
new OnMapEnter();
}



Take most of the code from a teleport script or something..
But...I've made any mistake...the server crashs, when I entered the area with an playerchar. The "FFA worked?" is still printed in the console..
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 05, 2015, 08:23:06 am
Hmm, dont see a reason for it to crash.
Only that it has a thread safety issue.

Removed some of the useless code:
Code: [Select]
#include "ScriptPCH.h"

enum Enums
{
    FIRST_TELEDELAY = 1000,
};

class Teleport : public BasicEvent
{
public:
    Teleport(Player* player) : _Plr(player) { }

    bool Execute(uint64 /*time*/, uint32 /*diff*/)
    {
        if (_Plr->GetMapId() == 9999)
        {
            printf("Executing timed eventn");
            _Plr->SetPvP(true);
            _Plr->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
        }

        return true;
    }
    Player* _Plr;
};

class OnMapEnter : public PlayerScript
{
public:
    OnMapEnter() : PlayerScript("OnMapEnter") { }

    void OnChangeMap(Player* player)
    {
        if (player->GetMapId() == 9999)
        {
            printf("Adding timed eventn");
            player->m_Events.AddEvent(new Teleport(player), player->m_Events.CalculateTime(FIRST_TELEDELAY));
        }
    }
};

void AddSC_OnMapEnter()
{
    new OnMapEnter();
}



Maybe you should try build in debug mode and or run it under a debugger?
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 05, 2015, 04:03:21 pm
I'll try that. But for now I take the code you write, and the good thing is...the server don't crash any longer, when I join my map..:D Bad thing is, that there is nothing more in the console...:(
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Ascathos on July 05, 2015, 05:42:43 pm
I haven't used TimedEvents.
I assume you have to effectively call Execute()

Code: [Select]
enum Enums
{
    FIRST_TELEDELAY = 1 * IN_MILLISECONDS
};

class Teleport : public BasicEvent
{
public:
    Teleport(Player* player) : _Plr(player) { }

    bool Teleport::Execute(uint64 /*time*/, uint32 /*diff*/)
    {
        if (_Plr->GetMapId() == 9999)
        {
            printf("Executing timed eventn");
            _Plr->SetPvP(true);
            _Plr->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
        }

        return true;
    }

private:
    Player* _Plr;
};

class OnMapEnter : public PlayerScript
{
public:
    OnMapEnter() : PlayerScript("OnMapEnter") { }

    void OnChangeMap(Player* player)
    {
        if (player->GetMapId() == 9999)
        {
            printf("Adding timed eventn");
            Teleport* tele = new Teleport(player);
            player->m_Events.AddEvent(tele, player->m_Events.CalculateTime(FIRST_TELEDELAY));
        }
    }
};

Does this work ?
I based it off BattlegroundQueue
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 05, 2015, 06:13:24 pm
No, nothing happened. And also nothing print out in the console..
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 06, 2015, 12:42:26 pm
Try use the override keyword.
In this case you happened to write the OnMapChanged hook wrong in the new script of yours as well.
Correct the hook name to OnMapChanged and it should start triggering again.
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 06, 2015, 03:32:09 pm
Okay..I've no Idea whats going on..:D First..it work. The player is ffa flaged, but only if he don't move. If he start walking he lose the ffa flag and get just pvp flaged...that's so weird..:(

edit:
I've tried to disable this part:
Code: [Select]
printf("Executing timed eventn");

// disabled to prevent a new pvp flag
//_Plr->SetPvP(true);  

_Plr->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);

Yeah...it also not work...the player is now, after he start moving, unflaged..:(
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 06, 2015, 03:47:53 pm
Try using this hook instead.
https://github.com/TrinityCore/TrinityC ... #L766-L767 (https://github.com/TrinityCore/TrinityCore/blob/6.x/src/server/game/Scripting/ScriptMgr.h#L766-L767" onclick="window.open(this.href);return false;)

The FFA flags are updated on zone update, which might trigger when you start moving (makes you change the zone specific channels and stuff):
You still need the timed event since the hook triggers before the flag setting etc work is done by core normal code.
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 06, 2015, 04:16:50 pm
I did anything wrong, I'm sure..

Code: [Select]

class OnMapEnter : public PlayerScript
{
public:
OnMapEnter() : PlayerScript("OnMapEnter") { }

void OnUpdateZone(Player* player, uint32, uint32)
{
if (player->GetMapId() == 9999)
{
printf("UPDATE ZONEn");
Teleport* tele = new Teleport(player);
player->m_Events.AddEvent(tele, player->m_Events.CalculateTime(FIRST_TELEDELAY));
}

}
};

That's not working.:(

edit:

this is working, but only in one zone..if I change the zone, the player is just pvp flaged..

Code: [Select]
class OnMapEnter : public PlayerScript
{
public:
OnMapEnter() : PlayerScript("OnMapEnter") { }

void OnUpdateZone(Player* player, uint32, uint32)
{
if (player->GetMapId() == 9999)
{
printf("UPDATEZONEn");
Teleport* tele = new Teleport(player);
player->m_Events.AddEvent(tele, player->m_Events.CalculateTime(FIRST_TELEDELAY));
}

}
void OnMapChanged(Player* player)
{
if (player->GetMapId() == 9999)
{
printf("ONMAPCHANGEn");
Teleport* tele = new Teleport(player);
player->m_Events.AddEvent(tele, player->m_Events.CalculateTime(FIRST_TELEDELAY));
}
}
};

sec. edit:

The "UPDATE ZONE" print, never appears in the console..:/
Title: Re: [C++] Set PvP FFA when player enter map
Post by: schlumpf on July 06, 2015, 04:27:40 pm
Please try that override thing. It can probably help a lot.
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 06, 2015, 04:39:40 pm
Quote from: "schlumpf"
Please try that override thing. It can probably help a lot.

ah...forget it last time ;(

But now the flag changed when I leave buildings, or enter them...that's not possible...the map have no vmap or mmap..

edit:
with "override" nothing changed...I also lost the ffa flag when I leave a zone, instead I get pvp flaged..:(
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 07, 2015, 08:28:08 pm
little...push ;(?

I've tried it now with an dbc solution, but my map have the area flag 0, and I can't change this. And anytime player enter now any building (house etc.) they get ffa flaged..

[attachment=0:1s00pqfm]WoWScrnShot_070715_202711.jpg[/attachment:1s00pqfm]


edit:

I don't know why, but at any point of my map I've the zone and area Id 0, but if i move on the map the area names  appears..thats so..strange
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 09, 2015, 12:11:03 pm
As said on TC forums, this works for me on non custom maps.
Hmm .. I guess the naming of the event and such could be changed though ..

Code: [Select]
#include "ScriptPCH.h"

class Teleport : public BasicEvent
{
public:
    Teleport(Player* player) : _player(player)
    {
        player->m_Events.AddEvent(this, player->m_Events.CalculateTime(0));
    }

    bool Execute(uint64 /*time*/, uint32 /*diff*/)
    {
        printf("TIME EVENTn");
        _player->pvpInfo.IsInFFAPvPArea = true;
        _player->UpdatePvPState(true);
        return true;
    }

    Player* _player;
};

class OnMapEnter : public PlayerScript
{
public:
    OnMapEnter() : PlayerScript("OnMapEnter") { }

    void OnUpdateZone(Player* player, uint32 /*newZone*/, uint32 /*newArea*/) override
    {
        if (player->GetMapId() == 1)
        {
            printf("UPDATE ZONE!n");
            new Teleport(player);
        }
    }

    void OnMapChanged(Player * player) override
    {
        if (player->GetMapId() == 1)
        {
            printf("UPDATE MAP!n");
            new Teleport(player);
        }
    }
};

void AddSC_OnMapEnter()
{
    new OnMapEnter();
}
Title: Re: [C++] Set PvP FFA when player enter map
Post by: bizzlesnaff on July 09, 2015, 03:18:31 pm
Well..First THANK YOU! :D This is the first script, which change anything constantly :D

To answer your question from TC forum. DBC editing ist not possible, because my custom map is just a copy of outland, and I don't like to change the "reald" outlands ;)
So..the strange thing is, with your script I'm ffa flaged..except in orgrimmar, stormwind etc. :D
But thats no problem..try it now on my map..:)

edit:
worked awesome on my custom map! (well..shattrath...is...yeah..still sanctury..but thats no problem)

Thank you very much rochet!
Title: Re: [C++] Set PvP FFA when player enter map
Post by: Rochet2 on July 09, 2015, 03:31:43 pm
Quote from: "bizzlesnaff"
So..the strange thing is, with your script I'm ffa flaged..except in orgrimmar, stormwind etc. :D

Its not so strange because that is how the FFA code works by default as well.
On FFA pvp realms the cities are not  FFA PVP either. And the stuff there is using the existing system.

.. I think.

If you want to disable the sanctuary stuff etc as well, setting the info to the pvpinfo should be enough before calling the update I think...