Player in defined area?

Hello again!

I have a new problem with c++ and my math skills. I have a new table with this structure

id int(10) NOT NULL AUTO_INCREMENT
point_mapid smallint(5) DEFAULT NULL
point_1_x float DEFAULT ‘0’
point_1_y float DEFAULT ‘0’
point_2_x float DEFAULT ‘0’
point_2_y float DEFAULT ‘0’
point_3_x float DEFAULT ‘0’
point_3_y float DEFAULT ‘0’
point_4_x float DEFAULT ‘0’
point_4_y float DEFAULT ‘0’

and this data:

‘1’, ‘0’, ‘-9253.11’, ‘355.97’, ‘-9264.71’, ‘370.3’, ‘-9292.29’, ‘347.97’, ‘-9277.21’, ‘332.27’
‘2’, ‘0’, ‘-9280.16’, ‘317.92’, ‘-9287.36’, ‘325.82’, ‘-9293.8’, ‘319.94’, ‘-9287.89’, ‘312.09’

This points create ingame a rectangle around my little house:

http://www11.pic-upload.de/17.06.14/owbpnvnknmy.jpg

Now i want to find out “Is the player in my area?”. I try to create a new function which return the id from the correct entry in the database:

static uint32 AktuellesHaus(float player_x, float player_y, uint32 player_mapid)
{
//Get all entrys which are on the players map
QueryResult getEntrys = WorldDatabase.PQuery(“SELECT point_1_x, point_2_x, point_3_x, point_4_x, point_1_y, point_2_y, point_3_y, point_4_y, point_mapid, id FROM my_table WHERE point_mapid = %u”, player_mapid);

bool found = false;
uint32 entryid = 0;

//no entrys then return 0
if(!getEntrys)
{
	return entryid;
}

//check all entrys
do
{
	Field* fields  = getEntrys->Fetch();		
	float minValueX = fields[0].GetFloat();
	float maxValueX = fields[0].GetFloat();
	float minValueY = fields[4].GetFloat();
	float maxValueY = fields[4].GetFloat();
	uint32 i	   = 0;

	//get the lowest/highest X value from all point coords
	for(i=0; i<4; i++)
	{
		if(minValueX > fields[i].GetFloat())
		{
			minValueX = fields[i].GetFloat();
		}
		
		if(maxValueX < fields[i].GetFloat())
		{
			maxValueX = fields[i].GetFloat();
		}
	}

	//get the lowest/highest Y value from all point coords
	for(i=4; i<8; i++)
	{
		if(minValueY > fields[i].GetFloat())
		{
			minValueY = fields[i].GetFloat();
		}
		
		if(maxValueY < fields[i].GetFloat())
		{
			maxValueY = fields[i].GetFloat();
		}
	}

	bool inXCoord = false;
	bool inYCoord = false;

	//check x value
	float resultminValueX = minValueX - player_x;
	float resultmaxValueX = maxValueX - player_x;
	
	if(resultminValueX < 0 && resultmaxValueX > 0)
	{
		inXCoord = true;
	}

	//check y value
	float resultminValueY = minValueY - player_y;
	float resultmaxValueY = maxValueY - player_y;
	
	if(resultminValueY < 0 && resultmaxValueY > 0)
	{
		inYCoord = true;
	}

	if(inXCoord && inYCoord && player_mapid == fields[8].GetUInt32())
	{
		found = true;
		entry = fields[9].GetUInt32();
	}
//crawl all entrys or break if found an correct entry
} while(getEntrys->NextRow() || found == false);

//return entry
return entry;

}

So it works very rough, because the check is inexact. My character can stand 4 feets next to the red line (screenshot). In the screenshot the function tells that my character is in the area with ID 1, but he is not in the area. So everyone an better idea to check it?

The second problem is, that the core crash if i call the function 10 times in 5 secs.

Parranoia did the math some year ago:
http://pastebin.com/SMxSP7t9

Source: http://emudevs.com/showthread.php/409-Custom-Sanctuary-PvP-Zone

(the math was used lot longer before that release though)

Another solution would be to make everything a bit simpler.
Lets say the rectangle is really a rectangle and not defined by random points that look about like a rectangle.

Then, as the rectangle is possibly a bit rotated, you need to get / know the rotation amount.

Then do coordinate rotation for the player position point (google something about this to find the math … c++ rotate around point)

then you can easily check the x and y axis differences.


| |
___________ o
so just check that the dot x is between the side X coords and Y coords.

Thanks to Foe, jamey, alex who talked with me about this 6 months ago ::stuck_out_tongue_winking_eye:

Sadly I deleted the code earlier today, so Im not going to remake it atm : |

Crashlog would help with the crash …

And shouldnt possibly query stuff from DB.

The “Peacekeeper” script looks good. Here the crash log:

Revision: TrinityCore rev. 0c2f5340cc3f+ 2013-12-31 20:08:11 +0100 (master branch) (Win32, Release)
Date 17:6:2014. Time 22:59
//=====================================================
*** Hardware ***
Processor: Intel(R) Xeon(R) CPU E5645 @ 2.40GHz
Number Of Processors: 2
Physical Memory: 2097152 KB (Available: 2097152 KB)
Commit Charge Limit: 4194303 KB

*** Operation System ***
Windows Server 2008 R2 Server 4.0 (Version 6.1, Build 7600)

//=====================================================
Exception code: C0000005 ACCESS_VIOLATION
Fault address: 017A1621 01:003C0621 C:UsersAdministratorDesktopServerworldserver.exe

Registers:
EAX:1BAF7278
EBX:264DF901
ECX:00000000
EDX:000001AE
ESI:1BAF7278
EDI:264DF9BC
CS:EIP:0023:017A1621
SS:ESP:002B:264DF840 EBP:00000000
DS:002B ES:002B FS:0053 GS:002B
Flags:00010246

Call stack:
Address Frame Function SourceFile

Local Variables And Parameters

Call stack:
Address Frame Function SourceFile

Global Variables
‘??4_Init_locks@std@@QAEAAV01@ABV01@@Z

The problem is that i must fetch the coordinates and the id from the database…

Why cant you already have them fetched?

Im pretty sure they are used very frequently, so it would be better to be in memory all the time anyways.

Save them somewhere on server startup …

Crash log needs a debug build.

Cant exactly get anything useful from release log.

Ah the best way will be that i load all my id and point coords at the core startup. Right? Uff… lets try to find out how i can doing this. Is it complicated to “add” a new table to the startup sequence?

You can just make a ServerScript and use the OnStartup hook.

or was it WorldScript…

You can also use the the constructor of your script class you use now for your script.

Then just do the SQL query at that point and store it to a vector or map or array or something.

I try to realise my idea with the Peacekeeper script and execute the command on the class constructor.

By the way. Thanks Rochet. You help me everytime! /emoticons/default_smile.png

/edit

It call the constructer/class only one time, is that correct?

Mhm is it possible to save the database entrys in Point structs and this structs in an array like this:

AllPoints[0] = static const Point V[] {{‘-9253.11’, ‘355.97’}, {‘-9264.71’, ‘370.3’}, {‘-9292.29’, ‘347.97’}, {‘-9277.21’, ‘332.27’}}
AllPoints[1] = static const Point V[] {{‘-9280.16’, ‘317.92’}, {‘-9287.36’, ‘325.82’}, {‘-9293.8’, ‘319.94’}, {‘-9287.89’, ‘312.09’}}

Okay i try to realise it with a vector:

#include “ScriptMgr.h”
#include “GameEventMgr.h”
#include “ObjectMgr.h”
#include “PoolMgr.h”
#include “MapManager.h”
#include “Chat.h”
#include “Language.h”
#include “Player.h”
#include “Opcodes.h”
#include

std::vector MyDataVector;

class test_commandscript : public CommandScript
{
public:
test_commandscript() : CommandScript(“test_commandscript”)
{
QueryResult getData = WorldDatabase.PQuery(“SELECT id, point_mapid, point_1_x, point_1_y, point_2_x, point_2_y, point_3_x, point_3_y, point_4_x, point_4_y FROM data_table ORDER BY ID ASC”);

	if(getData)
	{	
		do
		{
			Field* field = getData->Fetch();
			MyDataVector.push_back(field[0].GetFloat());
			MyDataVector.push_back(field[1].GetFloat());
			MyDataVector.push_back(field[2].GetFloat());
			MyDataVector.push_back(field[3].GetFloat());
			MyDataVector.push_back(field[4].GetFloat());
			MyDataVector.push_back(field[5].GetFloat());
			MyDataVector.push_back(field[6].GetFloat());
			MyDataVector.push_back(field[7].GetFloat());
			MyDataVector.push_back(field[8].GetFloat());
			MyDataVector.push_back(field[9].GetFloat());
		} while(getData->NextRow());
	}
}

static bool HandleModifyPlayerMyTestCommand(ChatHandler* handler, char const* /args/)
{
Player* player = handler->GetSession()->GetPlayer();

int j = 0;
for (int j=0; j < MyDataVector.size(); j++)
{
	handler->PSendSysMessage(TESTSTRING, MyDataVector[j]);
}	
return true;

}

My database entrys:

‘1’, ‘0’, ‘-9253.11’, ‘355.97’, ‘-9264.71’, ‘370.3’, ‘-9292.29’, ‘347.97’, ‘-9277.21’, ‘332.27’
‘2’, ‘0’, ‘-9280.16’, ‘317.92’, ‘-9287.36’, ‘325.82’, ‘-9293.8’, ‘319.94’, ‘-9287.89’, ‘312.09’

If i execute the ingame command i get this result:

Test: 0

Test: 0

Test: 536870912

Test: 536870912

Test: 3758096384

Test: 3221225472

Test: 536870912

Test: 536870912

Test: 3758096384

Test: 3758096384

Test: 0

Test: 0

etc.

Why i get this crazy values?

I’m assuming that you are getting memory location data, rather than contents, seems you need to be more specific just what you are asking it to print…

Ah yes. Next problem! /emoticons/default_smile.png

I use the “Peacekeeper” script. How i can delete/free this struct array?

static const Point V[] = { {4513.935f, -4256.359f}, {4510.568f, -4236.598f}, {4490.970f, -4249.030f}, {4489.567f, -4194.844f}, {4513.935f, -4256.359f} };

I try

delete[] &V;

but that do not work.

Leave the & out.