• This is a read only backup of the old Emudevs forum. If you want to have anything removed, please message me on Discord: KittyKaev

[SOLVED] Help me code something

Status
Not open for further replies.

Black Ace

Insane Member
Hey people

I want to code a system that counts pve kills and rewards the player .

like 10 kills - a title .

But I have no idea where to start and what to do cause I'm not familiar with such stuff.

Would appreciate help . thanks in advance :choupi:
 

Rochet2

Moderator / Eluna Dev
The base logic could be that on PvE kill, you increase the kill count and then check if it is enough for a reward.
The kills need to be saved somewhere, so if they are not in the player class, you need to possibly erase them on logout.


Use PlayerScript hook here:
https://github.com/TrinityCore/Trin...rc/server/game/Scripting/ScriptMgr.h#L694L695
Additionally you might want to use the player logout hook to erase the data from the map saved for the player if you go with that.

Here is an example of how to use a script class.
This will use GameObjectScript and OnGossipHello hook, so you need to replace that with PlayerScript and the hook function that you need
https://github.com/TrinityCore/Trin...rver/scripts/Examples/example_misc.cpp#L61L82

To add the script to your TC follow this:
http://collab.kpsn.org/display/tc/How-to_CustomScript

The difficult part is to store the kills.
It will either need a variable in the Player class or it will require you to make an RW hashmap.
Usually a normal map would be alright though, but its not thread safe. You can use that for starters though, as long as you at least keep map update threads at 1 in the worldserver config.
Check out std::unordered_map
You should be able to use that to store the kills. Use player low guid as the key (player->GetGUIDLow()) and the value can be the kills directly.
http://www.cplusplus.com/reference/unordered_map/unordered_map/
http://www.cplusplus.com/reference/unordered_map/unordered_map/operator[]/

The way to reward title would be this:
https://github.com/ElunaLuaEngine/Eluna/blob/master/PlayerMethods.h#L1279L1281
 
Last edited:

Black Ace

Insane Member
Hm I don't understand the part where you need to save the kill .

Pvp kills are easy to store cause they are saved in chars table but there is nothing for the pve.

Rochet2 said:
It will either need a variable in the Player class or it will require you to make an RW hashmap.
Usually a normal map would be alright though, but its not thread safe. You can use that for starters though, as long as you at least keep map update threads at 1 in the worldserver config.
Check out std::unordered_map
You should be able to use that to store the kills. Use player low guid as the key (player->GetGUIDLow()) and the value can be the kills directly.
 

Rochet2

Moderator / Eluna Dev
Hm I don't understand the part where you need to save the kill .
Pvp kills are easy to store cause they are saved in chars table but there is nothing for the pve.
Hmm, Not sure if its a good idea to store the kills in DB.
Sure it will persist through restart then, but I suggest you will look into storing the data in C++ containers and variables instead.
You can then move onto saving to DB afterwards. It should be easy to implement on top of the map with OnSave hook.

In C++ map there are key and value.
For this purpose the key could be uint32 for the key and uint32 for the value. so that is player guid pointing to the kill count.
We will use unordered map instead of map, since it should be faster for lookup, and we wont need looping through the map.
std::unordered_map<uint32, uint32> myMap;

Simple example:
Code:
std::unordered_map<uint32, uint32> myMap;
myMap[10] = 5;
printf("%u\n", myMap[9]);  // prints 0
printf("%u\n", myMap[10]); // prints 5

You can access a map element with the [] operator.
So for example if you need the kill count for a player, you can do
printf("%u\n", myMap[player->GetGUIDLow()]);
This will print the amount of kills saved for the player to the console.

If an element doesnt exist for the key used in [], an element is created. For uint32 and other integers the default value is 0.

Check out the site and the links I posted earlier for the map.
The site contains information examples of how to use each function and operator for map.



It is possible that there is a counter for overall creature kills, but that is true only if wow has an achievement for creature kills or some function like the player counter for pvp lifetime kills.
 
Last edited:

Black Ace

Insane Member
Hm I want the rewards to be permanent and life time just like those achievements.

wouldn't make sense to have the count reset on logout or restart since the reward might be an item and anyone can use it to get multiple rewards then.

and I think the boss achievements work with such function , or killing listed critters. just gotta find em
 
Last edited:

Rochet2

Moderator / Eluna Dev
Hm I want the rewards to be permanent and life time just like those achievements.

wouldn't make sense to have the count reset on logout or restart since the reward might be an item and anyone can use it to get multiple rewards then.

and I think the boss achievements work with such function , or killing listed critters. just gotta find em

The point was that the DB saving can be implemented easily afterwards.
Right after you have scripted the basic functionality of the script.
Also, one question is if you want to make a core modification or stick to a script.

Achievements might not do. They are counted by the achievement system, so lets say there is an achievement for killing critters.
When you kill one, it takes that up for you. When you kill the same, it wont do anything anymore.
Its like for quests. You do the quest's required amount, and that is the end of counting.
 

Tommy

Founder
I wrote a basic script for you:

Code:
struct CreatureKill
{
    uint32 creatureEntry;
    uint32 kills;
};

std::unordered_map<uint32, CreatureKill> KillMap;

class pve_count_kill : public PlayerScript
{
public:
    pve_count_kill() : PlayerScript("pve_count_kill") { }
	
    void OnCreatureKill(Player* killer, Creature* killed)
    {
        std::unordered_map<uint32, CreatureKill>::iterator itr = KillMap.find(killer->GetGUIDLow());
        if (itr != KillMap.end())
        {
            if (itr->second.creatureEntry == killed->GetEntry())
                itr->second.kills++;
				
            switch(itr->second.kills)
            {
                case 10: // Reward on 10 kills
                    RewardTitle(killer, 3000); // Change 3000 to your titleId
                    break;
            }
        }
        else
        {
            CreatureKill creatureKill;
            creatureKill.creatureEntry = killed->GetEntry();
            creatureKill.kills = 1;
            KillMap[killer->GetGUIDLow()] = creatureKill;
        }
    }
	
    void RewardTitle(Player* player, uint32 titleId)
    {
        CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId);
        if (titleEntry)
            player->SetTitle(titleEntry, false);
    }
};

void SetupPvECount()
{
    new pve_count_kill;
}

I only tested the loop logic via a separate project, but I did the rest in Notepad++. Hopefully it will compile fine.
 
Status
Not open for further replies.
Top