Jump to content

Party member count check for every map index


Recommended Posts

  • Active Member

Hey guys,

I'm trying to find a way how to change function below to check member pids on every map index, because it's checking party members count only on map where everyone of party is.

I know, I could use this function: ForEachOnlineMember, but I need to check party members count when they're offline too.

Why I need to do that? I need to remove party member from party when the party member change the empire.

File: questlua_party.cpp

Spoiler
ALUA(party_get_member_pids)
	{
		CQuestManager & q = CQuestManager::instance();
		LPCHARACTER ch = q.GetCurrentCharacterPtr();
		LPPARTY pParty = ch->GetParty();
		if (NULL == pParty)
		{
			return 0;
		}
		FPartyPIDCollector f;
		pParty->ForEachOnMapMember(f, ch->GetMapIndex());

		for (std::vector <DWORD>::iterator it = f.vecPIDs.begin(); it != f.vecPIDs.end(); it++)
		{
			lua_pushnumber(L, *it);
		}
		return f.vecPIDs.size();
	}

 

Anyone know the solution? I'll be really really glad for that!

Thanks for possible answers!

Sincerely,

ReFresh

Edited by ReFresh

I'll be always helpful! 👊 

Link to comment
Share on other sites

  • Premium
2 hours ago, WeedHex said:

party.cpp

DWORD CParty::GetMemberCount()
{
	return m_memberMap.size();
}

Is not that what you want?

party_get_member_count only returns the count of the members in your current map, and only if they're online, so no.

What he needs is a way of determining whether or not the player's party exists, even if the player itself is in a different map/core/channel. It's doable in Lua without having to add anything sourceside, albeit definitely tricky.

The suggestion to add a party.leave() function wouldn't work either, because the party instance from a different channel won't exist. So they could just change channel, change empire, and then return back to the original channel, pretty dirty. So it's better to prevent the empire change altogether instead.

 

This solution is for sure not optimal, but it works, without any bugs, and doesn't require any source changes.

So, let's start by making a simple quest:

quest get_party_data begin
    state start begin
        when login or logout begin
            local qf_name = "last_channel";
            local channel_id = pc.get_channel_id()
            -- We save the index of the last channel the player was in a party in.
            if (party.is_party() and pc.getqf(qf_name) == 0) then
                pc.setqf(qf_name, channel_id);

            -- if the player relogs back to the registered channel but with no party
            -- either it has been deleted or they got kicked, so we reset the qf.
            elseif (pc.getqf(qf_name) == channel_id and not party.is_party()) then
                pc.setqf(qf_name, 0);
            end -- if/elseif
        end -- when
    end -- state
end -- quest

 

Then, in our empire_change quest:

..
    ..
        -- add this somewhere within the main state..
        function IsPlayerInParty()
            local idx, qf = "get_party_data", "last_channel"
            -- if the player's current channel is the registered one, but with no party..
            -- ..it means the party was disbanded while the player was on the same channel..
            -- ..in which they joined it.
            if (pc.getf(idx, qf) == pc.get_channel_id() and not party.is_party()) then
                pc.setf(idx, qf, 0); -- we reset the qf right now so they won't need to relog in this case.
            end -- if
  
            -- If the registered channel qf is still active..
            -- ..it means the player has just changed core/ch, but the party still exists.
            return party.is_party() or pc.getf(idx, qf) > 0;
        end -- function

        -- ..and upon opening the empire change item, add this check:
        if (QUESTNAME.IsPlayerInParty()) then -- substitute QUESTNAME with the name of your empire change quest.
            return say_reward("Can't change empire, the player is in a party.");
        end -- if
    ..
..

Overall, if we really gotta be picky, the only unoptimal factor is that if the party disbands/the player gets kicked while they were in a different channel, then they'll need to relog back to the channel from which they joined the party in order to let the game know the party was disbanded, which is not even a factor considering the nature of the problem, cause unless they're precisely trying to reproduce the bug @ ReFresh mentioned in this topic, they won't even notice this little thing, which itself is not a bug, and still prevents them from performing the bug anyway.

Overall, it's not worth applying source changes to fix this little thing in my opinion, but anyone is welcome to propose a better solution.

This one still works well and without bugs if you can't be arsed implementing C++ things.

Edited by Syreldar
  • Metin2 Dev 2
  • Good 1

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Active Member

@ SyreldarThanks for your answer. I wanted to do something like this:

Spoiler
		function party_member_counting()
		
			local pids = {party.get_member_pids()}
			local player_count = 0

			for i, pid in pids do
				player_count = player_count + 1
			end

			return player_count
		end

 

And then in empire change process:

Spoiler
				if party.is_party() then
					
					local party_member_count = change_empire.party_member_counting()

					if party_member_count == 2 then

						party.delete_party()
					end

					if party_member_count >= 3 then

						if party.is_leader() then
							party.delete_party()
						
						elseif not party.is_leader() then
							party.leave_party()
						end
					end
				end

 

But after you said, there are more things which can be passed by just a channel change, it will probably require many source changes. So in this case it's better use what you wrote, because I don't have a c++ knowledge to change things like this in source. So thanks anyway. But would be nice, if someone could provide us a c++ part to make this thing working like I wrote.

Edited by ReFresh

I'll be always helpful! 👊 

Link to comment
Share on other sites

  • Premium
10 minutes ago, ReFresh said:

@ SyreldarThanks for your answer. I wanted to do something like this:

  Reveal hidden contents
		function party_member_counting()
		
			local pids = {party.get_member_pids()}
			local player_count = 0

			for i, pid in pids do
				player_count = player_count + 1
			end

			return player_count
		end

 

And then in empire change process:

  Reveal hidden contents
				if party.is_party() then
					
					local party_member_count = change_empire.party_member_counting()

					if party_member_count == 2 then

						party.delete_party()
					end

					if party_member_count >= 3 then

						if party.is_leader() then
							party.delete_party()
						
						elseif not party.is_leader() then
							party.leave_party()
						end
					end
				end

 

But after you said, there are more things which can be passed by just a channel change, it will probably require many source changes. So in this case it's better use what you wrote, because I don't have a c++ knowledge to change things like this in source. So thanks anyway. But would be nice, if someone could provide us a c++ part to make this thing working like I wrote.

? My quest works like you want. (Don't allow empire change if you're in a group, and supports different map/core/channel)

Doesn't rly get better than this. C++ work would be pointless.

Also the 'quest' you tried to write makes no sense whatsoever.

Edited by Syreldar

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Active Member

@ Syreldar Yes, there is no better solution by Lua, but I was talking about the leaving the group or destroying group trough channels automatically, but it will be a little bit complicated to make something like that in C++. So I'll stay with what you wrote.

I'll be always helpful! 👊 

Link to comment
Share on other sites

  • 2 months later...
  • Forum Moderator

Guys, why are you always using quest flags? It's been 8 years since the source first appeared; we should avoid them because they're highly toxic; let's not use the database for everything when we already have everything in C++, it just needs to be properly accessed.

 

uc?id=1QDs4rFWMHLwJQZqOQhahQJciqjsxn_1Z

This is the hidden content, please

  • party.h

This is the hidden content, please

How-To-Use:

if party.is_party() then
	local party_member_table = {party.party_get_all_member_pids()}
	local party_member_count = table.getn(party_member_table)
	
	-- Debug
	local party_member_string = table.concat(party_member_table, ", ")
	say(string.format("Party members: count(%d), pids(%s)", party_member_count, party_member_string))
end

 

Edited by VegaS™
  • Metin2 Dev 16
  • Good 1
  • Love 2
Link to comment
Share on other sites

  • Premium

 

3 hours ago, VegaS™ said:

Guys, why are you always using quest flags? It's been 8 years since the source first appeared; we should avoid them because they're highly toxic; let's not use the database for everything when we already have everything in C++, it just needs to be properly accessed.

 

This is the hidden content, please

 

Hidden Content

 

	int party_get_all_member_pids(lua_State* L)
	{
		auto ch = CQuestManager::instance().GetCurrentCharacterPtr();
		if (!ch)
			return 0;

		auto pParty = ch->GetParty();
		if (!pParty)
			return 0;

		const auto& memberMap = pParty->GetPartyMembers();
		for (const auto& it : memberMap)
			lua_pushnumber(L, it.first);

		return static_cast<int>(memberMap.size());
	}

	{ "party_get_all_member_pids",		party_get_all_member_pids	},

 

    • questlua_party.cpp

 

  • party.h

 

Hidden Content

 

	public:
		const TMemberMap& GetPartyMembers() const
		{
			return m_memberMap;
		}

 

 

How-To-Use:

if party.is_party() then
	local party_member_table = {party.party_get_all_member_pids()}
	local party_member_count = table.getn(party_member_table)
	
	-- Debug
	local party_member_string = table.concat(party_member_table, ", ")
	say(string.format("Party members: count(%d), pids(%s)", party_member_count, party_member_string))
end

 

You can speak in the singular... 😂

Link to comment
Share on other sites

  • Premium
8 hours ago, VegaS™ said:

Guys, why are you always using quest flags? It's been 8 years since the source first appeared; we should avoid them because they're highly toxic; let's not use the database for everything when we already have everything in C++, it just needs to be properly accessed.

 

This is the hidden content, please

 

Hidden Content

 

	int party_get_all_member_pids(lua_State* L)
	{
		auto ch = CQuestManager::instance().GetCurrentCharacterPtr();
		if (!ch)
			return 0;

		auto pParty = ch->GetParty();
		if (!pParty)
			return 0;

		const auto& memberMap = pParty->GetPartyMembers();
		for (const auto& it : memberMap)
			lua_pushnumber(L, it.first);

		return static_cast<int>(memberMap.size());
	}

	{ "party_get_all_member_pids",		party_get_all_member_pids	},

 

    • questlua_party.cpp

 

  • party.h

 

Hidden Content

 

	public:
		const TMemberMap& GetPartyMembers() const
		{
			return m_memberMap;
		}

 

 

How-To-Use:

if party.is_party() then
	local party_member_table = {party.party_get_all_member_pids()}
	local party_member_count = table.getn(party_member_table)
	
	-- Debug
	local party_member_string = table.concat(party_member_table, ", ")
	say(string.format("Party members: count(%d), pids(%s)", party_member_count, party_member_string))
end

 

Good. That fixes the first part of the issue: The party member pids not being taken into account for characters in different cores/channels.

However, that still won't do, it requires more work: Your solution assumes that the party stays valid through channels, but as I previously stated, when a group member logins in a different one they will be without a party in that channel, parties are channel-exclusive.

Screenshots for reference: t8xbjmL.jpeg

KzTZ25p.jpeg

 

This means that they can just change channel, do whatever they want while eluding the party checks, then log back in the old one. With my solution they can't, because a flag stays valid between different channels.

Also, I have already stated that my solution was suboptimal, I simply shared my own approach while being informative about it.

That said, I believe your take towards questflags is a bit of a stretch: the game is built to handle hundreds of thousands of them active and get info on them at the same time with negligible impact on the server.

Edited by Metin2 Dev
Core X - External 2 Internal
  • Good 1

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Forum Moderator
23 minutes ago, Syreldar said:

Good. That fixes the first part of the issue: The party member pids not being taken into account for characters in different cores/channels.

However, that still won't do, it requires more work: Your solution assumes that the party stays valid through channels, but as I previously stated, when a group member logins in a different one they will be without a party in that channel, parties are channel-exclusive.

I wrote that at 7 a.m., and I had mostly read the main post, which was about how he wanted that specific function; I had not considered the 'changing empire quest logic,' my mistake.

  • Love 2
Link to comment
Share on other sites

12 hours ago, VegaS™ said:

Guys, why are you always using quest flags? It's been 8 years since the source first appeared; we should avoid them because they're highly toxic; let's not use the database for everything when we already have everything in C++, it just needs to be properly accessed.

 

This is the hidden content, please

Hidden Content

 

	int party_get_all_member_pids(lua_State* L)
	{
		auto ch = CQuestManager::instance().GetCurrentCharacterPtr();
		if (!ch)
			return 0;

		auto pParty = ch->GetParty();
		if (!pParty)
			return 0;

		const auto& memberMap = pParty->GetPartyMembers();
		for (const auto& it : memberMap)
			lua_pushnumber(L, it.first);

		return static_cast<int>(memberMap.size());
	}

	{ "party_get_all_member_pids",		party_get_all_member_pids	},

 

    • questlua_party.cpp

 

  • party.h
Hidden Content

 

	public:
		const TMemberMap& GetPartyMembers() const
		{
			return m_memberMap;
		}

 

 

How-To-Use:

if party.is_party() then
	local party_member_table = {party.party_get_all_member_pids()}
	local party_member_count = table.getn(party_member_table)
	
	-- Debug
	local party_member_string = table.concat(party_member_table, ", ")
	say(string.format("Party members: count(%d), pids(%s)", party_member_count, party_member_string))
end

 

What's auto& 's meaning exactly?I just read this..

automatically detects and assigns a data type to the variable with which it is used

Why are you using the address symbol? &

(I know only C that's why i am asking about address symbol)

 

Edited by dotMatryx
  • Metin2 Dev 1
Link to comment
Share on other sites

  • Forum Moderator
7 minutes ago, dotMatryx said:

What's auto& 's meaning exactly?I just read this..

automatically detects and assigns a data type to the variable with which it is used

Why are you using the address symbol? &

(I know only C that's why i am asking about address symbol)

 

https://stackoverflow.com/questions/26541920/is-it-a-good-practice-to-use-const-auto-in-a-range-for-to-process-the-element

uc?id=1rKoEe-TnRRdGoMxhQw2oWp4nX1_UEgdh

Edited by VegaS™
  • Love 1
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.