Questie

Questie

116M Downloads

[3.0] Yet another core rewrite?

AeroScripts opened this issue Β· 14 comments

commented

Maybe it's what is best at this point.

Again.

commented

How about a database rewrite along with that? Would gladly help. It's confusing A.F. right now.

For example, is there a reason for using hashes instead of quest ID's to uniquely identifiy quests? Or for having quest information spread over so many tables (apart from how functions call them)? Also the DB seems to ignore some important information from the server data like ExclusiveGroup-field, but not sure on this.

On a sidenote, is it correct that Questie.lua and PrettyFrames.lua are unused right now (except for testcommands)? And thanks for the graphic btw.

commented

Well, the way it is currently built makes lookups easier and faster because you can call by keys. Keys are unique, so you end up with low data redundancy.

And last but not least, hashes are a necessity. You can generate the hash using the same algorithm ingame as you did previously "out of game", using the same parameters (questlevel, objective text, questname etc), thus generating an id. Obviously vanilla doesn't actuzally let the user access a quest id in any way whatsoever. So creating your own is the way to go. But hashes themselves differ from server to server and stock mangos, because none of them have the exact same strings for all quests. So there's a levenshtein lookup involved finding the closest possible result by iterating all quests.

But yes, some data is ignored mostly due to the inability to easily access it ingame and use it for lookups.

commented

It might not be a bad idea to store the actual data with the quest id as the key though, just to standardize things. Then have a hash->questid table.

commented

In other words, the hash sums in your database have been generated from mangoszero DB data which is also obtainable ingame through script commands (like objectiveText from GetQuestLogQuestText()), and these hashs are compared against those generated ingame (using QuestieLevLookup-table), yes? The hash is not used for performance reasons (quest ID's are integers as well, if that's what @Schaka meant by key calls) but for identification across different servers?

Anyway, if you are in for a data-restructuring I could do that, because I already have a python script that converts such data from a mangos-style database to lua. Should be an easy rework of the in-/output from there (output is kind of what's in WHDB (or shaguquest) addon right now, but based on NPC/object ID's). I just need to understand your DB-structure first. But in general a wowhead-ish DB structure would be helpful for devs as well as bug reporters, because it matches what happens in the core as well as what users find on the popular DB websites.

One point I'm really unsure about though is why you didn't extract exact NPC/object spawns (and waypoints) but just a few for each template... Is this performance related, and if so, is it due to table lookup time or number of created frames?

commented

Do you have a way to convert mangoszero world coordinates to 2d world coordinates? Thats the one thing I've had trouble with, I actually went through and made a macro to .go to every location and take note of the map coordinate LOL

Not exactly the most efficient but it was easy at the time. Anyway, any help is appreciated there certainly is need for some database cleaning. Not starting on things right away though.

commented

We started out with the QuestHelper 2.4.3 DB and converted it to something we could use with the 1.12.1 client, which is why we don't have ALL NPC spawns. That, and because we wanted to avoid cluttering, both for performance reasons (mostly minimap) and because creating area sprites for spawns was on the roadmap but not doable within a reasoable amount of time.

And yes, you understood correctly. Hashes are generated from mangoszero data, using data that is easily available ingame. They are then matched against ingame generated hashes using the same algorithm (Adler32). Due to differences on pretty much every server, with what seems like at least 10% of quests, we also implemented a levenshtein lookup to find whichever string (out of ALL quests) is closest to the one you have picked up ingame.

Such a loop can take from 10 to 30ms. Sometimes you have 20 quests and it will have to loop for 5 or 6 of them. During that period of time, your client completely freezes. Which is why we currently cache hashes with the ingame-obtained parameters as the key in a table.

Iterations are incredibly slow on larger tables. I have to admit, I haven't looked at the ShaguQuest data structure, but unless it is attempting to emulate a relational database using a key/value store, I don't think it is what we are looking for - not if performance is what we aim for.

commented

Im working on ripping db.vanillagamings.org data instead of using mangos, first rip will be slow but the data will be much more reliable than the mangos data, and we also get coordinates in a good format without the converting if you wanna se my VERY MUCH WIP code look here C#

http://pastebin.com/P14F7CxT
Not even added this stuff to VS this is all written freehand at work so.
This will create a lua table that uses WoWs own internal ID system, there will be a lookup table HASH -> QuestID and rest of the work will be done in WoWID form not our hash system,
Also theorizing that we should use the Quest title to get a subset out of all quests and run levenshtein over that subset instead, example The Peoples Militia has like 6 quests with the same title, but running levenshtein over those 6 is super fast.

commented

Thanks for all the info guys, much appreciated πŸ‘

@AeroScripts Yes I found a way to calculate the exact coordinates based on this. From there I just had to exchange the TBC borders with the classic borders (found in some file of the game client). Btw. some astrolabe borders are off, but I haven't gotten around to figuring out how the offsets were made yet.

@Schaka I experienced this freezing problem too, but only when comparing tables against each other, for example to check if a position was marked for two or more quests/items/NPCs. Otherwise I experienced no performance problems, not even when displaying more than 400 notes at the same time. But I was using a modified WHDB version, so I just passed coordinates to cartographer without knowing how it puts them on the map internally... Current NPC data looks like this (divide by 100 and it matches your coordinate format):

npcData =
{
    [3] =
    {
        ['name'] = 'Flesh Eater',
        ['level'] = '24 - 25',
        ['hp'] = '661 - 710',
        ['zone'] = 10,
        ['zones'] =
        {
            [10] = {{25.06, 38.2},{25.37, 36.04},{25.69, 34.45},{23.81, 39.21},{22.81, 39.09},{22.04, 32.62},{21.7, 38.3},{22.2, 36.96},{25.37, 39.03},},
            [40] = {{81.72, 43.04},{81.95, 41.37},{82.2, 40.14},{80.75, 43.82},{79.98, 43.72},{79.39, 38.73},{79.12, 43.11},{79.5, 42.08},{81.95, 43.68},},
        },
    },
}

(Note that I had problems identifying the right zone, so I just calculated for every zone possible, i.e. you could see notes in Durotar while viewing the Barrens map (example) - found a way to solve that for future extracts though)

@Logonz I did the very same thing, writing a crawler for online DBs that is. πŸ˜† At least until I figured out there are several open source server projects - I agree that mangos is outdated though, I used cmangos and classicdb since it was the best I could find and is still actively being worked on (it's also the core Kronos was based on). I did code a identification by questname, although after reading your explanations I'd now rather put the other data in a key based table. Looks like this atm:

qData = 
{
    ['Alliance'] =
    {
        ['The People\'s Militia'] =
        {
            ['IDs'] =
            {
                [12] = {'Gryan Stoutmantle wants you to kill 15 Defias Trappers and 15 Defias Smugglers then return to him on Sentinel Hill.', someOtherData},
                [13] = {'Gryan Stoutmantle wants you to kill 15 Defias Pillagers and 15 Defias Looters and return to him on Sentinel Hill.', someOtherData},
                [14] = {'Gryan Stoutmantle wants you to kill 15 Defias Highwaymen, 5 Defias Pathstalkers and 5 Defias Knuckledusters then return to him on Sentinel Hill.', someOtherData},
            },
        },
    },
}

However there are some quests which can't be identified uniquely by objectiveText, but most of these can be identified by one, or a combination of, other field(s) (e.g. requiredRace or start/end-NPC/object/item, but I think you alreay check some of them). I can upload my addon repository sometime over the weekend, if you want to take a look at it, but it's "VERY MUCH WIP" as well. πŸ˜„

Btw. the main reason I'd rather help improving your addon is your fancy ass note frame system (being displayed on the world map, map addon independent, etc). Great work!

commented

Haha i wrote the note system from a TBC converted Astrolabe without documentation :D Acually pretty proud of it!

Im probably the one whos going to break it out, going to make a "handynotes" clone for vanilla so other addons can use it as well.

commented

@Muehe If you look into the branch you see the new database has been made :)

commented

Nice work man, only had time to take a peek into the DB structure yet. Looks much more readable πŸ˜„ What's with the string-keys though? That was kind of my point. Now:

DB_Creatures={
['2437']={
    ID = 2437,
    Name = 'Keeper Bel\'varil',
    Locations = {
        {C=2,Z=12,X=61.5,Y=20.93},
    },
},
['6766']={
    ID = 6766,
    Name = 'Ravenholdt Guard',
    Locations = {
        {C=2,Z=12,X=77.24,Y=20.1},{C=2,Z=12,X=77.74,Y=20.05},{C=2,Z=12,X=83.46,Y=18.05},{C=2,Z=12,X=82.81,Y=17.89},{C=2,Z=12,X=83.74,Y=17.66},{C=2,Z=12,X=82.87,Y=17.31},{C=2,Z=12,X=80.59,Y=16.76},{C=2,Z=12,X=80.12,Y=15.69},{C=2,Z=12,X=80.96,Y=13.03},
    },
},
}

Instead, write a comment to explain the structure and use integers as keys:

--[[
General table structure:
DB_Creatures={
    [WoWHeadNPC_ID]={
        Name,
        Locations={
            {continent, zone, position_x, position_y},
        },
    },
}
]]--

DB_Creatures={
[2437]={'Keeper Bel\'varil', {{2,12,61.5,20.93}}},
[6766]={'Ravenholdt Guard', {{2,12,77.24,20.1},{2,12,77.74,20.05},{2,12,83.46,18.05},{2,12,82.81,17.89},{2,12,83.74,17.66},{2,12,82.87,17.31},{2,12,80.59,16.76},{2,12,80.12,15.69},{2,12,80.96,13.03}}}
}

As I said before, I'm not that Lua savvy, but from a quick read in http://www.lua.org/gems/sample.pdf (pages 19 ff. (PDF: 5 ff.)) it seems doing this could save some lookup time. A developer always knows the order his data is stored in anyway, so he can name it when he uses it in functions/classes, or use global variables for that matter:

-- pseudo code
DBname = 1;
DBlocations = 2;
DBcontinent = 1;
DBzone = 2;
DBx = 3;
DBy = 4;

creatureID = GetCreatureID(NameOrSomething); -- searches NPC ID, returns nil if not found
if (creatureID) then
    for i, location in pairs(DB_Creatures[creatureID][DBlocations]) do
        AddNote(location[DBzone], location[DBx], location[DBy], commentsEtc);
    end
end

Also you don't need to go into the table to compare the ID you are using in the code (once you have uniquely identified your NPC/object/quest) but just use it directly as the key. Or is there some purpose to storing it as string-key and integer-variable?

Furthermore I think zone IDs are unique (not sure, see note), so maybe continent variable isn't needed either. (Note: this may damage portability to other languages)

Anyway, nice work so far πŸ‘ Will check back when I have had more time to read source and test ingame.

commented

Okay, where to start, please post the code for DB coords -> ingame coords πŸ‘

Ofc mobs are going to be Numeric keys, must have been tired, but i can just regenerate it super Quick so no problems.

The NPCid is acually wows internal one, has nothing to do with wowhead,

As i wrote in Another issue im probably going to do a NPC lookup table, which is [C][Z]['NPCNAME'] = NPCID to save the lookup time when mousing over an NPC, as we know where all NPCs are we have no problems generating a good list, i have yet decided if im going to do this at startup, or pregenerate the list.

DB_NPCLookup = {
    [CID] = {
        [ZID] = {
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
        },
        [ZID] = {
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
        },
    },
    [CID] = {
        [ZID] = {
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
        },      
        [ZID] = {
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
            [NPCNAME] = NPCID,
        },
    },
}

We've have previous performance issues with mouseover tooltip stuff, so i think this will save a lot of performance.

Also zoneIds does not exist in vanilla, retail have them and the db.vanillagaming.org IDs are their own internal ones, so yo uget it by doing (Not exact but) GetCurrentContinent() and GetCurrentZone()
And if you look into the DB_Zones you can see that Zones go from 1-XX on both continents, ofc i could just generate a key with MATHZ (Maybe string it C..Z and then make it numeric which would create a Unique ID.

commented

Like I said before this code below doesn't calculate the correct zone, but just every zone a NPC/object can be seen from. There is a solution for gameobjects to be found here, but it has to be adjusted in order to work for creatures as well and you need to change the core and DB to apply it.

Zone borders are taken from WorldMapArea.dbc, which is stored in an mpq file of the client. There are tools in the cmangos source to extract these files.

The calculateCoords-function at the end should give you the zones and zone coordinates of one individual from the creature or gameobject tables. Also added the mysql-function, but you'll have to create your own pymysql cursor of course. I'll upload the full (python) script sometime soonβ„’, once I have stripped my mysql logins etc. Btw. I already uploaded my addon, most of the data can be found therein and is already converted. Just a little bit outdated though, like 8 month old or something.

"""


######################################
Data Definitions
######################################


"""

mapBorders = [('1', 'Dun Morogh', '0', '1802.08325195313', '-3122.91650390625', '-3877.08325195313', '-7160.41650390625'),
              ('3', 'Badlands', '0', '-2079.16650390625', '-4566.66650390625', '-5889.5830078125', '-7547.91650390625'),
              ('4', 'Blasted Lands', '0', '-1241.66662597656', '-4591.66650390625', '-10566.666015625', '-12800'),
              ('8', 'Swamp of Sorrows', '0', '-2222.91650390625', '-4516.66650390625', '-9620.8330078125', '-11150'),
              ('10', 'Duskwood', '0', '833.333312988281', '-1866.66662597656', '-9716.666015625', '-11516.666015625'),
              ('11', 'Wetlands', '0', '-389.583312988281', '-4525', '-2147.91650390625', '-4904.16650390625'),
              ('12', 'Elwynn Forest', '0', '1535.41662597656', '-1935.41662597656', '-7939.5830078125', '-10254.166015625'),
              ('28', 'Western Plaguelands', '0', '416.666656494141', '-3883.33325195313', '3366.66650390625', '499.999969482422'),
              ('33', 'Stranglethorn Vale', '0', '2220.83325195313', '-4160.41650390625', '-11168.75', '-15422.916015625'),
              ('36', 'Alterac Mountains', '0', '783.333312988281', '-2016.66662597656', '1500', '-366.666656494141'),
              ('38', 'Loch Modan', '0', '-1993.74987792969', '-4752.0830078125', '-4487.5', '-6327.0830078125'),
              ('40', 'Westfall', '0', '3016.66650390625', '-483.333312988281', '-9400', '-11733.3330078125'),
              ('41', 'Deadwind Pass', '0', '-833.333312988281', '-3333.33325195313', '-9866.666015625', '-11533.3330078125'),
              ('44', 'Redridge Mountains', '0', '-1570.83325195313', '-3741.66650390625', '-8575', '-10022.916015625'),
              ('45', 'Arathi Highlands', '0', '-866.666625976563', '-4466.66650390625', '-133.33332824707', '-2533.33325195313'),
              ('46', 'Burning Steppes', '0', '-266.666656494141', '-3195.83325195313', '-7031.24951171875', '-8983.3330078125'),
              ('47', 'The Hinterlands', '0', '-1575', '-5425', '1466.66662597656', '-1100'),
              ('51', 'Searing Gorge', '0', '-322.916656494141', '-2554.16650390625', '-6100', '-7587.49951171875'),
              ('85', 'Tirisfal Glades', '0', '3033.33325195313', '-1485.41662597656', '3837.49975585938', '824.999938964844'),
              ('130', 'Silverpine Forest', '0', '3449.99975585938', '-750', '1666.66662597656', '-1133.33325195313'),
              ('139', 'Eastern Plaguelands', '0', '-2185.41650390625', '-6056.25', '3799.99975585938', '1218.75'),
              ('267', 'Hillsbrad Foothills', '0', '1066.66662597656', '-2133.33325195313', '400', '-1733.33325195313'),
              ('1497', 'Undercity', '0', '873.192626953125', '-86.1824035644531', '1877.9453125', '1237.84118652344'),
              ('1519', 'Stormwind City', '0', '1380.97143554688', '36.7006301879883', '-8278.8505859375', '-9175.205078125'),
              ('1537', 'Ironforge', '0', '-713.591369628906', '-1504.21643066406', '-4569.2412109375', '-5096.845703125'),
              ('14', 'Durotar', '1', '-1962.49987792969', '-7249.99951171875', '1808.33325195313', '-1716.66662597656'),
              ('15', 'Dustwallow Marsh', '1', '-974.999938964844', '-6225', '-2033.33325195313', '-5533.3330078125'),
              ('16', 'Azshara', '1', '-3277.08325195313', '-8347.916015625', '5341.66650390625', '1960.41662597656'),
              ('17', 'The Barrens', '1', '2622.91650390625', '-7510.41650390625', '1612.49987792969', '-5143.75'),
              ('141', 'Teldrassil', '1', '3814.58325195313', '-1277.08325195313', '11831.25', '8437.5'),
              ('148', 'Darkshore', '1', '2941.66650390625', '-3608.33325195313', '8333.3330078125', '3966.66650390625'),
              ('215', 'Mulgore', '1', '2047.91662597656', '-3089.58325195313', '-272.916656494141', '-3697.91650390625'),
              ('331', 'Ashenvale', '1', '1699.99987792969', '-4066.66650390625', '4672.91650390625', '829.166625976563'),
              ('357', 'Feralas', '1', '5441.66650390625', '-1508.33325195313', '-2366.66650390625', '-6999.99951171875'),
              ('361', 'Felwood', '1', '1641.66662597656', '-4108.3330078125', '7133.3330078125', '3299.99975585938'),
              ('400', 'Thousand Needles', '1', '-433.333312988281', '-4833.3330078125', '-3966.66650390625', '-6899.99951171875'),
              ('405', 'Desolace', '1', '4233.3330078125', '-262.5', '452.083312988281', '-2545.83325195313'),
              ('406', 'Stonetalon Mountains', '1', '3245.83325195313', '-1637.49987792969', '2916.66650390625', '-339.583312988281'),
              ('440', 'Tanaris', '1', '-218.749984741211', '-7118.74951171875', '-5875', '-10475'),
              ('490', "Un'Goro Crater", '1', '533.333312988281', '-3166.66650390625', '-5966.66650390625', '-8433.3330078125'),
              ('493', 'Moonglade', '1', '-1381.25', '-3689.58325195313', '8491.666015625', '6952.0830078125'),
              ('618', 'Winterspring', '1', '-316.666656494141', '-7416.66650390625', '8533.3330078125', '3799.99975585938'),
              ('1377', 'Silithus', '1', '2537.5', '-945.833984375', '-5958.333984375', '-8281.25'),
              ('1637', 'Orgrimmar', '1', '-3680.60107421875', '-5083.20556640625', '2273.87719726563', '1338.46057128906'),
              ('1638', 'Thunder Bluff', '1', '516.666625976563', '-527.083312988281', '-849.999938964844', '-1545.83325195313'),
              ('1657', 'Darnassus', '1', '2938.36279296875', '1880.02954101563', '10238.31640625', '9532.5869140625')]
instanceIds = [('209', 'Shadowfang Keep', '33'),
               ('491', 'Razorfen Kraul', '47'),
               ('717', 'Stormwind Stockade', '34'),
               ('718', 'Wailing Caverns', '43'),
               ('719', 'Blackfathom Deeps', '48'),
               ('721', 'Gnomeregan', '90'),
               ('722', 'Razorfen Downs', '129'),
               ('796', 'Scarlet Monastery', '189'),
               ('1176', "Zul'Farrak", '209'),
               ('1337', 'Uldaman', '70'),
               ('1477', 'Sunken Temple', '109'),
               ('1581', 'The Deadmines', '36'),
               ('1583', 'Blackrock Spire', '229'),
               ('1585', 'Blackrock Depths', '230'),
               ('1977', "Zul'Gurub", '309'),
               ('2017', 'Stratholme', '329'),
               ('2057', 'Scholomance', '289'),
               ('2100', 'Maraudon', '349'),
               ('2159', "Onyxia's Lair", '249'),
               ('2257', 'Deeprun Tram', '369'),
               ('2437', 'Ragefire Chasm', '389'),
               ('2557', 'Dire Maul', '429'),
               ('2677', 'Blackwing Lair', '469'),
               ('2717', 'Molten Core', '409'),
               ('3428', "Ahn'Qiraj", '531'),
               ('3429', "Ruins of Ahn'Qiraj", '509'),
               ('3456', 'Naxxramas', '533'),
               ('2917', 'Horde PVP Barracks', '450'),
               ('2918', 'Alliance PVP Barracks', '449'),
               ('2597', 'Alterac Valley', '30'),
               ('3277', 'Warsong Gulch', '489'),
               ('3358', 'Arathi Basin', '529')
               #('209', 'Shadowfang Keep', '33', '4500', '300', '1133.333', '-1666.667'),
               #('491', 'Razorfen Kraul', '47', '2766.667', '966.6666', '2733.333', '1533.333'),
               #('722', 'Razorfen Downs', '129', '2766.667', '-633.3333', '3266.667', '999.9999'),
               #('796', 'Scarlet Monastery', '189', '1508.333', '-800', '1918.75', '379.166'),
               #('1176', "Zul'Farrak", '209', '1625', '241.6667', '2052.083', '1129.167'),
               #('1581', 'The Deadmines', '36', '1966.667', '-3033.333', '1133.333', '-2200'),
               #('1977', "Zul'Gurub", '309', '-693.75', '-2570.833', '-11308.33', '-12560.42'),
               #('2017', 'Stratholme', '329', '-1766.667', '-5166.667', '4333.333', '2066.667'),
               #('2057', 'Scholomance', '289', '633.3333', '-1166.667', '600', '-600'),
               #('2597', 'Alterac Valley', '30', '1781.24987792969', '-2456.25', '1085.41662597656', '-1739.58325195313'),
               #('2677', 'Blackwing Lair', '469', '633.3333', '-2766.667', '-6333.333', '-8600'),
               #('3277', 'Warsong Gulch', '489', '2041.66662597656', '895.833312988281', '1627.08325195313', '862.499938964844'),
               #('3358', 'Arathi Basin', '529', '1858.33325195313', '102.08332824707', '1508.33325195313', '337.5'),
               #('3428', "Ahn'Qiraj", '531', '3033.333', '1233.333', '-7933.333', '-9133.333'),
               #('3429', "Ruins of Ahn'Qiraj", '509', '3035.417', '522.9166', '-8233.333', '-9908.333')
               ]
continentBorders = [('5', 'Eastern Kingdoms', '0', '16000', '-19199.900390625', '7466.60009765625', '-16000'),
                    ('6', 'Kalimdor', '1', '17066.599609375', '-19733.2109375', '12799.900390625', '-11733.2998046875')]

validZoneList = [1, 3, 4, 8, 10, 11, 12, 14, 15, 16, 17, 28, 33, 36, 38, 40, 41, 44, 45, 46, 47, 51, 85, 130, 139, 141, 148, 215, 267, 331, 357, 361, 400, 405, 406, 440, 490, 493, 618, 1377, 1497, 1519, 1537, 1637, 1638, 1657]
zoneLevelList = [(1, 1, 10),
                 (3, 35, 45),
                 (4, 45, 55),
                 (8, 35, 45),
                 (10, 18, 30),
                 (11, 20, 30),
                 (12, 1, 10),
                 (14, 1, 10),
                 (15, 35, 45),
                 (16, 45, 55),
                 (17, 10, 25),
                 (28, 51, 58),
                 (33, 30, 45),
                 (36, 30, 40),
                 (38, 10, 20),
                 (40, 10, 20),
                 (41, 55, 60),
                 (44, 15, 25),
                 (45, 30, 40),
                 (46, 50, 58),
                 (47, 40, 50),
                 (51, 45, 50),
                 (85, 1, 10),
                 (130, 10, 20),
                 (139, 53, 60),
                 (141, 1, 10),
                 (148, 10, 20),
                 (215, 1, 10),
                 (267, 20, 30),
                 (331, 18, 30),
                 (357, 40, 50),
                 (361, 48, 55),
                 (400, 25, 35),
                 (405, 30, 40),
                 (406, 15, 27),
                 (440, 40, 50),
                 (490, 48, 55),
                 (493, 55, 60),
                 (618, 53, 60),
                 (1377, 55, 60),
                 (1497, 1, 60),
                 (1519, 1, 60),
                 (1537, 1, 60),
                 (1637, 1, 60),
                 (1638, 1, 60),
                 (1657, 1, 60)]

"""


######################################
NPC funtions
######################################


"""

def calculateCoords(mapId, x, y):
    zones=[]
    for mapSet in mapBorders:
        zone = int(mapSet[0])
        mId = int(mapSet[2])
        x1 = float(mapSet[5])
        x2 = float(mapSet[6])
        y1 = float(mapSet[3])
        y2 = float(mapSet[4])
        if (mapId == mId) and (x < x1) and (x > x2) and (y < y1) and (y > y2):
            xCoord = round(abs((x-x1)/(x2-x1)*100), 2)
            yCoord = round(abs((y-y1)/(y2-y1)*100), 2)
            z = [zone, yCoord, xCoord]
            zones.append(z)

    for instance in instanceIds:
        zoneId = int(instance[0])
        mapID = int(instance[2])
        if (mapId == mapID):
            z = [zoneId, -1, -1]
            zones.append(z)
    """
    for continent in continentBorders:
        cId = int(continent[2])
        if (mapId == cId):
            zone = int(continent[0])
            x1 = float(continent[5])
            x2 = float(continent[6])
            y1 = float(continent[3])
            y2 = float(continent[4])
            xCoord = round(abs((x-x1)/(x2-x1)*100), 2)
            yCoord = round(abs((y-y1)/(y2-y1)*100), 2)
            z = [zone, yCoord, xCoord]
            zones.append(z)
    """
    if zones != []:
        return zones
    else:
        return False

def getNPCTables(cursor):
    print("Selecting MySQL tables...")
    cursor.execute("SELECT entry, name, minlevel, maxlevel, minlevelhealth, maxlevelhealth, rank FROM creature_template")
    npc_tpl = []
    for a in cursor.fetchall():
        npc_tpl.append(a)
    cursor.execute("SELECT id, map, position_x, position_y, guid FROM creature")
    npc = []
    for a in cursor.fetchall():
        npc.append(a)
    cursor.execute("SELECT * FROM creature_questrelation")
    npc_start = []
    for a in cursor.fetchall():
        npc_start.append(a)
    cursor.execute("SELECT * FROM creature_involvedrelation")
    npc_end = []
    for a in cursor.fetchall():
        npc_end.append(a)
    cursor.execute("SELECT point, id, position_x, position_y FROM creature_movement")
    npc_mov = []
    for a in cursor.fetchall():
        npc_mov.append(a)
    """
    cursor.execute("SELECT point, entry, position_x, position_y FROM creature_movement_template")
    npc_mov_tpl = []
    for a in cursor.fetchall():
        npc_mov_tpl.append(a)
    """

    return npc_tpl, npc, npc_start, npc_end, npc_mov