• 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++ "readXML" on TFS 1.2

reisbro

Member
Joined
May 15, 2017
Messages
94
Solutions
1
Reaction score
7
EDIT: SOLVED, solution can be found in the Best Answer by Xeraphus (Post #10)


Guys, I am creating a new system based on: Feature - Random Attributes, but I want to make it for TFS 1.2

First post was a mess so I edited everything. Basically what I am trying to do is add new attributes on TFS 1.2 that can be used at items.xml
For instance:
XML:
<attribute key="attackMax" value="11" />
So on top of the base attack of the weapon, he will receive a random bonus from 0 to "attackMax", which in this example is 11, so a shortsword which has a base attack of 11 would get bonus damage from 0 to 11, with a total of 11-22 damage that would be determined randomly.
However unlike the system I am basing myself on, TFS 1.2 does not have a readXML function, and everytime I try to insert a XML tmpStrValue I get this warning when executing the server:
C++:
[Warning - Items::parseItemNode] Unknown key value: attackMax
 
Last edited:
Solution
So basically I want the item to get a bonus attack based on a random value between 0 and the "attackMax" value. When I compile the server, I get no errors, but when I execute the server I get a warning:
C++:
[Warning - Items::parseItemNode] Unknown key value: attackMax
tmpStrValue is lowercase, and you have attackMax not attackmax
it can be attackMax in the xml and it will be fine, but it gets converted to lowercase when it's assigned to tmpStrValue, so it will NEVER be attackMax cause of the M
Guys, I am creating a new system based on: Feature - Random Attributes

And I noticed a small change in syntax between TFS 0.4 and 1.2
On TFS 0.4, we had expressions like:
C++:
else if(tmpStrValue == "attack")
            {
                if(readXMLInteger(itemAttributesNode, "value", intValue))
                    it.attack = intValue;
            }

But in TFS 1.2 we have:
C++:
else if (tmpStrValue == "armor") {
            it.armor = pugi::cast<int32_t>(valueAttribute.value());
        }

How can I add new XML entries in version 1.2? I don't understand the pugi::cast function... I created tons of variables like attackChance (chance to get attack bonus on weapon), attackMin (minimum bonus if chance is true), attackMax (maximum bonus if chance is true) and many many many others haha. The problem is that the code I'm basing myself on is written for 0.4, and I could just ust readXML integer or string and etc...

If I remember correctly that happened during the transition from 1.0 - 1.1. I am not 100% on that tho. If I am correct you should be able to download the source from 1.0 and be fine. However I think they did change it on 1.1 first and then later pushed the commit to 1.0 as well, once it was proven safe. Anyway it goes you can search github and find a version before they made the alteration to using "pugi::cast".

Hell you may even be able to figure out what it all means and still use 1.2 to implement your system.
 
If I remember correctly that happened during the transition from 1.0 - 1.1. I am not 100% on that tho. If I am correct you should be able to download the source from 1.0 and be fine. However I think they did change it on 1.1 first and then later pushed the commit to 1.0 as well, once it was proven safe. Anyway it goes you can search github and find a version before they made the alteration to using "pugi::cast".

Hell you may even be able to figure out what it all means and still use 1.2 to implement your system.
I am currently compiling to check if the readXML integer works on 1.2, I will report back soon haha
 
Guys, I am creating a new system based on: Feature - Random Attributes

And I noticed a small change in syntax between TFS 0.4 and 1.2
On TFS 0.4, we had expressions like:
C++:
else if(tmpStrValue == "attack")
            {
                if(readXMLInteger(itemAttributesNode, "value", intValue))
                    it.attack = intValue;
            }

But in TFS 1.2 we have:
C++:
else if (tmpStrValue == "armor") {
            it.armor = pugi::cast<int32_t>(valueAttribute.value());
        }

How can I add new XML entries in version 1.2? I don't understand the pugi::cast function... I created tons of variables like attackChance (chance to get attack bonus on weapon), attackMin (minimum bonus if chance is true), attackMax (maximum bonus if chance is true) and many many many others haha. The problem is that the code I'm basing myself on is written for 0.4, and I could just ust readXML integer or string and etc...
pugi::cast casts the string that was read from the xml to a value specified, in your example it was casted to int32_t
pugi::cast<uint64_t>(valueAttribute.value()); would cast the string to a uint64_t value
as for adding new xml attributes, what you posted should be enough so it gets parsed
it just depends on how you use it and if you create new item attributes for your xml ones, which is how the values from the xml get stored (see it.armor, for item armor attribute)
 
Update:

readXML does not work in tfs 1.2, it is not declared anywhere.

I discovered that new XML nodes can be declared in the TFS SDK library, specifically inside the pugixml.hpp file. However I have LITERALLY NO IDEA on where I should do it inside the file, I tried adding it next to every "name" and "value" declarations since they are pretty much the only nodes used in TFS 1.2.
I am compiling now and will report back again soon haha
 
I now understand how the pugi function works. if you pugi::cast (valueAttribute.value), the function will return the XML entry 'value' as a number, and if you use it with (valueAttribute.as_string) it returns as a string. That means I need to declare another attribute called attackMax for instance, in the script below you can see what I am talking about:

C++:
else if (tmpStrValue == "attack") {
            it.attack = pugi::cast<int32_t>(valueAttribute.value());
            it.attackMax = pugi::cast<int32_t>(attackMaxAttribute.value());
        }

However, this as it is does not work because attackMax has not been declared inside pugixml.hpp, I know it has to be declared there but I have no idea about where I need to do it!

I am currently trying to declare it in lots of places but none of those are working, if anyone has an idea please share!
 
I now understand how the pugi function works. if you pugi::cast (valueAttribute.value), the function will return the XML entry 'value' as a number, and if you use it with (valueAttribute.as_string) it returns as a string. That means I need to declare another attribute called attackMax for instance, in the script below you can see what I am talking about:

C++:
else if (tmpStrValue == "attack") {
            it.attack = pugi::cast<int32_t>(valueAttribute.value());
            it.attackMax = pugi::cast<int32_t>(attackMaxAttribute.value());
        }

However, this as it is does not work because attackMax has not been declared inside pugixml.hpp, I know it has to be declared there but I have no idea about where I need to do it!

I am currently trying to declare it in lots of places but none of those are working, if anyone has an idea please share!
not sure if you actually understand what's happening here still
you don't edit the hpp file at all, nor even touch the sdk in any way
valueAttribute is the value="" key in the xml
C++:
pugi::xml_attribute valueAttribute = attributeNode.attribute("value");
in this case tmpStrValue holds the value parsed from the key attribute
C++:
pugi::xml_attribute keyAttribute = attributeNode.attribute("key");
later on:
C++:
std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string());
then it checks tmpStrValue with what it actually holds, and assigns something to an item type, like attack

so what you have to do is create your own attribute and check for tmpStrValue == "attackmax" (tmpStrValue is lowercase)
the xml would look like this
XML:
<attribute key="attackMax" value="10"/>

but you have to create your own attribute in the source for attackMax too which is harder to do
 
Last edited:
not sure if you actually understand what's happening here still
you don't edit the hpp file at all, nor even touch the sdk in any way
valueAttribute is the value="" key in the xml
C++:
pugi::xml_attribute valueAttribute = attributeNode.attribute("value");
in this case tmpStrValue holds the value parsed from the key attribute
C++:
pugi::xml_attribute keyAttribute = attributeNode.attribute("key");
later on:
C++:
std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string());
then it checks tmpStrValue with what it actually holds, and assigns something to an item type, like attack

so what you have to do is create your own attribute and check for tmpStrValue == "attackmax" (tmpStrValue is lowercase)
the xml would look like this
XML:
<attribute key="attackMax" value="10"/>

but you have to create your own attribute in the source for attackMax too which is harder to do
This is what I did so far:

I inserted this line in items.h
C++:
int32_t attackMax = 0;
under this
C++:
int32_t attack = 0;
then under
C++:
else if (tmpStrValue == "attack") {
            it.attack = pugi::cast<int32_t>(valueAttribute.value());
        }
I added this
C++:
else if (tmpStrValue == "attackMaxx") {
            it.attackMax = pugi::cast<int32_t>(valueAttribute.value());
        }
in items.cpp

And finally in item.cpp I added under
C++:
setDefaultDuration();
the following code:
C++:
if(it.attackMax > 0)
    {
          setIntAttr(ITEM_ATTRIBUTE_ATTACK, it.attack + rand() % (it.attackMax+1));
    }
 
So basically I want the item to get a bonus attack based on a random value between 0 and the "attackMax" value. When I compile the server, I get no errors, but when I execute the server I get a warning:
C++:
[Warning - Items::parseItemNode] Unknown key value: attackMax
 
So basically I want the item to get a bonus attack based on a random value between 0 and the "attackMax" value. When I compile the server, I get no errors, but when I execute the server I get a warning:
C++:
[Warning - Items::parseItemNode] Unknown key value: attackMax
tmpStrValue is lowercase, and you have attackMax not attackmax
it can be attackMax in the xml and it will be fine, but it gets converted to lowercase when it's assigned to tmpStrValue, so it will NEVER be attackMax cause of the M
 
Solution
tmpStrValue is lowercase, and you have attackMax not attackmax
it can be attackMax in the xml and it will be fine, but it gets converted to lowercase when it's assigned to tmpStrValue, so it will NEVER be attackMax cause of the M
Oh dude, I am so pissed at myself right know, I spent like 3 hours wondering was I was doing wrong and it was literally ONE CAPITAL LETTER? HAHA
Thank you so much, I am going to test it right now!
 
Oh dude, I am so pissed at myself right know, I spent like 3 hours wondering was I was doing wrong and it was literally ONE CAPITAL LETTER? HAHA
Thank you so much, I am going to test it right now!
yeah i did the same thing, created a custom attribute to test before posting my previous messages
but i took 5min to figure it out instead of 3 hours :/
 
yeah i did the same thing, created a custom attribute to test before posting my previous messages
but i took 5min to figure it out instead of 3 hours :/
I am recompiling now to check, but I really think it will work because the extra defense is declared as extraDef, with a capital D, but in the tmpStrValue it is used as extradef lol
 
yeah i did the same thing, created a custom attribute to test before posting my previous messages
but i took 5min to figure it out instead of 3 hours :/
what if I wanted to use subnodes?
Instead of doing this:

XML:
<attribute key="attackmax" value="11" />
<attribute key="attackmaxchance" value="20" />

I wanted to do this:

XML:
<attribute key="attackmax" value="11"  chance="20"/>

I would have to edit the pugixml thing right? Because the only "nodes" used are 'key' and 'value' in TFS 1.2
 
what if I wanted to use subnodes?
Instead of doing this:

XML:
<attribute key="attackmax" value="11" />
<attribute key="attackmaxchance" value="20" />

I wanted to do this:

XML:
<attribute key="attackmax" value="11"  chance="20"/>

I would have to edit the pugixml thing right? Because the only "nodes" used are 'key' and 'value' in TFS 1.2
no, you'd do something like this where valueAttribute and keyAttribute are defined
C++:
pugi::xml_attribute chanceAttribute = attributeNode.attribute("chance");
then use like
uint32_t chance = pugi::cast<uint32_t>(chanceAttribute.value());
 
Back
Top