• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ storage code

ConAn Edujawa

Member
Joined
Feb 23, 2015
Messages
454
Reaction score
15
what the wrong with this code
Lua:
            std::string value;
            std::string name = creature->getName();
            toLowerCaseString(name);
            player->getStorage(name, value);
                int32_t intValue = atoi(value.c_str());
                if(intValue > 0)
                    ss << " done: " << intValue << ".";

0.4
 

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Support Team
Joined
Mar 16, 2017
Messages
997
Solutions
100
Reaction score
1,033
Location
London
GitHub
MillhioreBT
C++:
uint32_t key = 10000;
std::string strValue;
if(creature->getStorage(key, strValue))
{
    int32_t intValue = atoi(strValue.c_str());
    std:cout << "Your storage: " << intValue << std::endl;
}
 

esigma94

Well-Known Member
Joined
Nov 1, 2009
Messages
108
Solutions
17
Reaction score
86
If by 4.0 you mean: Fir3element/3777 (https://github.com/Fir3element/3777/), then...
getStorage: Fir3element/3777 (https://github.com/Fir3element/3777/blob/master/src/creature.cpp#L895)
StorageMap: Fir3element/3777 (https://github.com/Fir3element/3777/blob/master/src/creature.h#L130)

The code from links above:
C++:
bool Creature::getStorage(const uint32_t key, std::string& value) const
{
    StorageMap::const_iterator it = storageMap.find(key);
    if(it != storageMap.end())
    {
        value = it->second;
        return true;
    }

    value = "-1";
    return false;
}

C++:
typedef std::map<uint32_t, std::string> StorageMap;

getStorage parameters are integer for the key and string for value's target variable.
You provide a string for both (key and value).

Change your key (name variable in your code) to proper type (uint32_t) and it should work. Ofc as long as it is a creature name (string) you are not able to do that, you have to figure out some different solution.

Also as you can see in a snippet above, the code defines StorageMap as map of uint32_t (key) and string (value), so you are not able to use string-based keys.
 
OP
OP
ConAn Edujawa

ConAn Edujawa

Member
Joined
Feb 23, 2015
Messages
454
Reaction score
15
If by 4.0 you mean: Fir3element/3777 (https://github.com/Fir3element/3777/), then...
getStorage: Fir3element/3777 (https://github.com/Fir3element/3777/blob/master/src/creature.cpp#L895)
StorageMap: Fir3element/3777 (https://github.com/Fir3element/3777/blob/master/src/creature.h#L130)

The code from links above:
C++:
bool Creature::getStorage(const uint32_t key, std::string& value) const
{
    StorageMap::const_iterator it = storageMap.find(key);
    if(it != storageMap.end())
    {
        value = it->second;
        return true;
    }

    value = "-1";
    return false;
}

C++:
typedef std::map<uint32_t, std::string> StorageMap;

getStorage parameters are integer for the key and string for value's target variable.
You provide a string for both (key and value).

Change your key (name variable in your code) to proper type (uint32_t) and it should work. Ofc as long as it is a creature name (string) you are not able to do that, you have to figure out some different solution.

Also as you can see in a snippet above, the code defines StorageMap as map of uint32_t (key) and string (value), so you are not able to use string-based keys.
like this
Lua:
            std::string value;
            std::string name = creature->getName();
            toLowerCaseString(name);
            player->getStorage((int32_t)name, value);
                int32_t intValue = (int32_t)(atoi(value.c_str()));
                if(intValue > 0)
                    ss << " done: " << intValue << ".";
?
Post automatically merged:

C++:
uint32_t key = 10000;
std::string strValue;
if(creature->getStorage(key, strValue))
{
    int32_t intValue = atoi(strValue.c_str());
    std:cout << "Your storage: " << intValue << std::endl;
}
i need change monster name to number and check how many i killed from it
 
Last edited:

esigma94

Well-Known Member
Joined
Nov 1, 2009
Messages
108
Solutions
17
Reaction score
86
Not exactly. It should throw you a compilation error due to improper type casting.
It has to be a numeric value (as you can see in Sarah's example).

You are not able to easily cast a string to a number (also to stay in max key limitation). Rethink your idea. Also, it is not easy to give you a tip if we don't know what you'd like to do.

Here's a simple example what you cannot do.
C++:
player->getStorage("dragon", value); // <- that's WRONG! you HAVE TO use numeric key
player->getStorage(12345, value); // <- that's ok. key is a number.
So you are not able to use monster name as a key as it is string (chain of characters) instead of a number.

One more thing. uint32_t is 32-bit unsigned integer, which allows you to assign value up to 4,294,967,295 (2^32-1). So your storage key cannot exceed this value.
 
OP
OP
ConAn Edujawa

ConAn Edujawa

Member
Joined
Feb 23, 2015
Messages
454
Reaction score
15
Not exactly. It should throw you a compilation error due to improper type casting.
It has to be a numeric value (as you can see in Sarah's example).

You are not able to easily cast a string to a number (also to stay in max key limitation). Rethink your idea. Also, it is not easy to give you a tip if we don't know what you'd like to do.

Here's a simple example what you cannot do.
C++:
player->getStorage("dragon", value); // <- that's WRONG! you HAVE TO use numeric key
player->getStorage(12345, value); // <- that's ok. key is a number.
So you are not able to use monster name as a key as it is string (chain of characters) instead of a number.

One more thing. uint32_t is 32-bit unsigned integer, which allows you to assign value up to 4,294,967,295 (2^32-1). So your storage key cannot exceed this value.
so i must add storage to every mod right ?
 

esigma94

Well-Known Member
Joined
Nov 1, 2009
Messages
108
Solutions
17
Reaction score
86
As I wrote, I am not aware of what is your idea. If you have multiple modules that have to remember some value and it shouldn't override each other, then yes - you have to assign each mod to a different storage value.

If you misspelled in a previous message (mod -> mob), then you have to figure out what is your idea and remember not to overengineer the code. Sometimes you don't want to remember information about all the monsters. Important is also how often you'd like to access these data, etc. etc. Based on all these things you can choose different solutions.

It's hard to suggest you anything as you didn't provide any details of what you'd like to do. You just asked for your code failure and I think the code provided by @Sarah Wesker is the answer (and the proper example as well). If you have any other doubts/questions please provide more details of what's on your mind.
 

Sarah Wesker

ค∂vαηcε รүηтαx ❤
Support Team
Joined
Mar 16, 2017
Messages
997
Solutions
100
Reaction score
1,033
Location
London
GitHub
MillhioreBT
He needs to obtain a unique key for each monster so that he does not have to write a key table for each monster.
you want to use this to store the amount of monsters you kill, thus having a counter for each monster separately.

I do not usually recommend things that I have not tried, but I mentioned that you can use a hash converter to get a numeric key, although this method is not totally accurate, I think it will satisfy the needs of the boy

C++:
uint32_t getHash(const std::string& name) {
    uint32_t hash = 0x811c9dc5;
    uint32_t prime = 0x1000193;
    for(int i = 0; i < name.size(); ++i) {
        uint8_t value = name[i];
        hash = hash ^ value;
        hash *= prime;
    }
    return hash;
}
with this function obtain a valid numeric key, for uint32_t
 

esigma94

Well-Known Member
Joined
Nov 1, 2009
Messages
108
Solutions
17
Reaction score
86
Sure I wouldn't recommend that as well. It consumes all keys starting from 0x1000193, so almost the whole storage keys range spreading its hashes "randomly" (with a huuuuge gaps). I think that he will use at most 500 storages. That's overkill for storages :p It might bring more issues than benefits.
 
OP
OP
ConAn Edujawa

ConAn Edujawa

Member
Joined
Feb 23, 2015
Messages
454
Reaction score
15
He needs to obtain a unique key for each monster so that he does not have to write a key table for each monster.
you want to use this to store the amount of monsters you kill, thus having a counter for each monster separately.

I do not usually recommend things that I have not tried, but I mentioned that you can use a hash converter to get a numeric key, although this method is not totally accurate, I think it will satisfy the needs of the boy

C++:
uint32_t getHash(const std::string& name) {
    uint32_t hash = 0x811c9dc5;
    uint32_t prime = 0x1000193;
    for(int i = 0; i < name.size(); ++i) {
        uint8_t value = name[i];
        hash = hash ^ value;
        hash *= prime;
    }
    return hash;
}
with this function obtain a valid numeric key, for uint32_t
how i can use this source done
 

esigma94

Well-Known Member
Joined
Nov 1, 2009
Messages
108
Solutions
17
Reaction score
86
If you put above code to your sources then you can call it with monster name as parameter:
Code:
uint32_t key = getHash(name);
player->getStorage(key, value);
// or
player->getStorage(getHash(name), value);

Remember that it returns a number from 16,777,619 to 4,294,967,295 based on the provided string (monster name). So I suggest you not use any number from this range as a storage key for any other scripts. As we wrote this solution is not recommended and you use it at your own risk.

You have to reserve 99.7% of all available storage values for this solution (4,278,189,676 storages) :p
 
OP
OP
ConAn Edujawa

ConAn Edujawa

Member
Joined
Feb 23, 2015
Messages
454
Reaction score
15
If you put above code to your sources then you can call it with monster name as parameter:
Code:
uint32_t key = getHash(name);
player->getStorage(key, value);
// or
player->getStorage(getHash(name), value);

Remember that it returns a number from 16,777,619 to 4,294,967,295 based on the provided string (monster name). So I suggest you not use any number from this range as a storage key for any other scripts. As we wrote this solution is not recommended and you use it at your own risk.

You have to reserve 99.7% of all available storage values for this solution (4,278,189,676 storages) :p
anyway its not work
 

esigma94

Well-Known Member
Joined
Nov 1, 2009
Messages
108
Solutions
17
Reaction score
86
You got an answer to the topic. You CANNOT use string type variable as a key for storage. You have to use an INTEGER. So you can't use text, you have to use a number. You've got an example of how to use storage in C++ as well (kudos Sarah).

Moreover, you continued the topic without any specific request leaving just words without bigger context. Sarah posted an example code of how to hash text to obtain a number (assuming that this is what you want). Also, there is a suggestion that hashing is one of the ideas to solve such transformation (string -> int) but it is not recommended here (at least not in that way).

Imho this thread is already answered and went a little too far regarding the main topic. I suggest you create a different thread with a detailed question and specified needs. Having these details probably will allow someone to give you an idea of how to solve your issue in a blink.
 
Top