How do you equate a player faction to an NPC faction (eg: Stormwind)?

I’m trying to find a way to pick an NPC, based on faction (eg: Stormwind, Ironforge) and class, to use as a mail sender but I can’t seem to get the player’s faction to equate to their home city (and thereby an NPC faction).

For example:

According to FactionTemplate, 12 is Stormwind and the following SQL returns “Lord Grayson Shadowbreaker” when querying for a max level Paladin trainer:

SELECT * FROM creature_template WHERE faction=12 AND trainer_class=2 AND subname <> ‘’ ORDER BY maxlevel DESC LIMIT 1;

The problem is that Player->GetFactionTemplate()->faction returns 1 which is "Player, Human " so plugging that into the prepared statement below results in no rows.

SELECT * FROM creature_template WHERE faction= ? AND trainer_class= ? AND subname <> ‘’ ORDER BY maxlevel DESC LIMIT 1;

I can’t use the value in GetFactionTemplate()->hostileMask because it returns 12 for all Alliance Players and I want to use the highest level trainer from the player’s home city (eg: Dwarf = Ironforge, Elf = Darnassus, etc.)

So essentially what I want to do is if the player is a Nightelf Hunter then pick a trainer from Darnassus, if they’re a Dwarf Hunter, pick a trainer from Ironforge, if they’re a Draenei Hunter pick a trainer from Exodar, etc. etc…

Thanks!

I think there is not a general way to solve this because: Human is different from Stormwind, Dwarf from Ironforge, and so on…

So I think you need to evaluate each case.

Example:

FactionTemplateEntry const* playerFaction = GetFactionTemplateEntry();

if(playerFaction == HUMAN)
    npcFaction = STORMWIND;
 

Yes, I had considered that but I was hoping to find a way to write it so it didn’t need to be modified for new expansions (eg: 335 has no Worgen / Goblins so the script would need to be modified for other branches).

I think I’ll end up going with using the player as a sender for now just to get the script finished. Since it’s mainly cosmetic it can be fine-tuned later.

We have this old and ugly code: https://github.com/TrinityCore/TrinityCore/blob/master/src/server/game/AuctionHouse/AuctionHouseMgr.cpp#L376-L403

I was considering writing a function that performed a conversion like that but as I mentioned there’s no way to automatically include new starting cities in future expansions.

It’s too bad that FactionTemplate.dbc didn’t include a HomeCity field which would match one of the NPC factions (eg: 12 for Stormwind).

Ok, I think I’ve found something that will work…

ChrRaces.dbc has a reference to CinematicCamera.dbc which has XYZ coords of the ending cinematic sequence. I can use this data to pick the class trainer from the starting zone:

– Select Human Paladin trainer based on opening cinematic end position

SELECT * FROM
creature_template
WHERE
trainer_class=2
AND
gossip_menu_id > 0
AND
subname <> ‘’
AND
entry IN (
SELECT id FROM
creature
WHERE
(position_x BETWEEN (-8945.52 - 500) AND (-8945.52 + 500))
AND
(position_y BETWEEN (-118.76 - 500) AND (-118.76 + 500))
AND
(position_z BETWEEN (82.931 - 500) AND (82.931 + 500))
);

Note: The + - 500 is necessary because some races start closer to their trainer than others.

Note: I thought I saw something in the core like GetNearestNpc(x, y, z) but no luck.

Anyway, CinematicCameraEntry isn’t implemented so I guess I’ve got work to do… Could someone give me an overview of how DBCfmt works?

CinematicCameraEntry is commented out but if I wanted to implement that, I understand I need to define the format but I can only guess that i=integer, f=float, s=string but how would I skip a field such as “filename” which is an unknown size string?

If I want the following:

struct CinematicCameraEntry
{
uint32 id;
// char* filename;
// uint32 soundid;
float end_x;
float end_y;
float end_z;
float orientation;
}

I would think defining the format like: “nxxffff” but that probably isn’t the proper number of bytes.

Thanks!

Looks like through trial and error I got it right (well it at least shows the first record in the debugger). Will see how it goes…