Ticket #2936: RelativeTemplates.patch
File RelativeTemplates.patch, 16.0 KB (added by , 8 years ago) |
---|
-
source/simulation2/components/CCmpVisualActor.cpp
146 146 "</element>" 147 147 "<element name='Box' a:help='Sets the selection shape to a box of specified dimensions'>" 148 148 "<attribute name='width'>" 149 "<ref name='positiveDecimal' />" 149 "<data type='decimal'>" 150 "<param name='minExclusive'>0.0</param>" 151 "</data>" 150 152 "</attribute>" 151 153 "<attribute name='height'>" 152 "<ref name='positiveDecimal' />" 154 "<data type='decimal'>" 155 "<param name='minExclusive'>0.0</param>" 156 "</data>" 153 157 "</attribute>" 154 158 "<attribute name='depth'>" 155 "<ref name='positiveDecimal' />" 159 "<data type='decimal'>" 160 "<param name='minExclusive'>0.0</param>" 161 "</data>" 156 162 "</attribute>" 157 163 "</element>" 158 164 "<element name='Cylinder' a:help='Sets the selection shape to a cylinder of specified dimensions'>" 159 165 "<attribute name='radius'>" 160 "<ref name='positiveDecimal' />" 166 "<data type='decimal'>" 167 "<param name='minExclusive'>0.0</param>" 168 "</data>" 161 169 "</attribute>" 162 170 "<attribute name='height'>" 163 "<ref name='positiveDecimal' />" 171 "<data type='decimal'>" 172 "<param name='minExclusive'>0.0</param>" 173 "</data>" 164 174 "</attribute>" 165 175 "</element>" 166 176 "</choice>" -
source/simulation2/components/CCmpFootprint.cpp
59 59 "<choice>" 60 60 "<element name='Square' a:help='Set the footprint to a square of the given size'>" 61 61 "<attribute name='width' a:help='Size of the footprint along the left/right direction (in metres)'>" 62 "<ref name='positiveDecimal'/>" 62 "<data type='decimal'>" 63 "<param name='minExclusive'>0.0</param>" 64 "</data>" 63 65 "</attribute>" 64 66 "<attribute name='depth' a:help='Size of the footprint along the front/back direction (in metres)'>" 65 "<ref name='positiveDecimal'/>" 67 "<data type='decimal'>" 68 "<param name='minExclusive'>0.0</param>" 69 "</data>" 66 70 "</attribute>" 67 71 "</element>" 68 72 "<element name='Circle' a:help='Set the footprint to a circle of the given size'>" 69 73 "<attribute name='radius' a:help='Radius of the footprint (in metres)'>" 70 "<ref name='positiveDecimal'/>" 74 "<data type='decimal'>" 75 "<param name='minExclusive'>0.0</param>" 76 "</data>" 71 77 "</attribute>" 72 78 "</element>" 73 79 "</choice>" -
source/simulation2/docs/SimulationDocs.h
298 298 - <code><text/></code> 299 299 - <code><data type='boolean'/></code> 300 300 - <code><data type='decimal'/></code> 301 - <code><data type='integer'/></code> 301 302 - <code><data type='nonNegativeInteger'/></code> 302 303 - <code><data type='positiveInteger'/></code> 304 - <code><ref name='decimal'/></code> 303 305 - <code><ref name='nonNegativeDecimal'/></code> 304 306 - <code><ref name='positiveDecimal'/></code> 305 307 306 (The last two are slightly different since they're not standard data types.)307 308 309 The <code><data></code> elements are native elements, while the <code><ref></code> elements are elements added for our engine. These non-native elements allow the definition of an operation that depends on the parent template. Possible operations are "add" and "mul", and can be applied as the example below. 310 311 Say the parent template is 312 @code 313 <Entity> 314 <Example> 315 <Name>Semi-Humanoids</Name> 316 <Height>9000</Height> 317 <Eyes/> 318 </Example> 319 <!-- ... other components ... --> 320 </Entity> 321 @endcode 322 and the child template appears like 323 @code 324 <Entity> 325 <Example> 326 <Name>Barney</Name> 327 <Height op="add">5</Height> 328 <Eyes/> 329 </Example> 330 <!-- ... other components ... --> 331 </Entity> 332 @endcode 333 then Barney would have a height of 9005. 334 308 335 Elements can be wrapped in <code><optional></code>. 309 336 Groups of elements can be wrapped in <code><choice></code> to allow only one of them. 310 337 The content of an <code><element></code> can be further nested elements, but note that -
source/simulation2/system/ParamNode.cpp
76 76 // Look for special attributes 77 77 int at_disable = xmb.GetAttributeID("disable"); 78 78 int at_replace = xmb.GetAttributeID("replace"); 79 int at_op = xmb.GetAttributeID("op"); 79 80 int at_datatype = xmb.GetAttributeID("datatype"); 81 enum op { 82 INVALID, 83 ADD, 84 MUL 85 } op = INVALID; 80 86 bool replacing = false; 81 87 { 82 88 XERO_ITER_ATTR(element, attr) … … 91 97 m_Childs.erase(name); 92 98 replacing = true; 93 99 } 100 else if (attr.Name == at_op) 101 { 102 if (std::wstring(attr.Value.begin(), attr.Value.end()) == L"add") 103 op = ADD; 104 else if (std::wstring(attr.Value.begin(), attr.Value.end()) == L"mul") 105 op = MUL; 106 else 107 LOGWARNING("Invalid op '%ls'", attr.Value); 108 } 94 109 } 95 110 } 96 111 { … … 137 152 138 153 // Add this element as a child node 139 154 CParamNode& node = m_Childs[name]; 155 if (op != INVALID) 156 { 157 // TODO: Support parsing of data types other than fixed; log warnings in other cases 158 fixed oldval = node.ToFixed(); 159 fixed mod = fixed::FromString(CStrW(value)); 160 switch (op) 161 { 162 case ADD: 163 node.m_Value = (oldval + mod).ToString().FromUTF8(); 164 break; 165 case MUL: 166 node.m_Value = (oldval.Multiply(mod)).ToString().FromUTF8(); 167 break; 168 } 169 hasSetValue = true; 170 } 140 171 if (!hasSetValue) 141 172 node.m_Value = value; 142 173 … … 150 181 XERO_ITER_ATTR(element, attr) 151 182 { 152 183 // Skip special attributes 153 if (attr.Name == at_replace) continue; 184 if (attr.Name == at_replace || attr.Name == at_op) 185 continue; 154 186 // Add any others 155 187 std::string attrName = xmb.GetAttributeString(attr.Name); 156 188 node.m_Childs["@" + attrName].m_Value = attr.Value.FromUTF8(); -
source/simulation2/system/ComponentManager.cpp
1092 1092 1093 1093 std::string CComponentManager::GenerateSchema() 1094 1094 { 1095 std::string numericOperation = 1096 "<optional>" 1097 "<attribute name='op'>" 1098 "<choice>" 1099 "<value>add</value>" 1100 "<value>mul</value>" 1101 "</choice>" 1102 "</attribute>" 1103 "</optional>"; 1095 1104 std::string schema = 1096 1105 "<grammar xmlns='http://relaxng.org/ns/structure/1.0' xmlns:a='http://ns.wildfiregames.com/entity' datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'>" 1106 "<define name='decimal'>" 1107 "<data type='decimal'/>" 1108 + numericOperation + 1109 "</define>" 1097 1110 "<define name='nonNegativeDecimal'>" 1098 1111 "<data type='decimal'><param name='minInclusive'>0</param></data>" 1112 + numericOperation + 1099 1113 "</define>" 1100 1114 "<define name='positiveDecimal'>" 1101 1115 "<data type='decimal'><param name='minExclusive'>0</param></data>" 1116 + numericOperation + 1102 1117 "</define>" 1103 1118 "<define name='anything'>" 1104 1119 "<zeroOrMore>" -
source/tools/entity/Entity.pm
83 83 } 84 84 } 85 85 $base->{' content'} = join ' ', @t; 86 } elsif ($new->{'@op'}) { 87 my $op = $new->{'@op'}{' content'}; 88 my $op1 = $base->{' content'}; 89 my $op2 = $new->{' content'}; 90 if ($op eq 'add') { 91 $base->{' content'} = $op1 + $op2; 92 } 93 elsif ($op eq 'mul') { 94 $base->{' content'} = $op1 * $op2; 95 } 96 else { 97 die "Invalid operator '$op'"; 98 } 86 99 } else { 87 100 $base->{' content'} = $new->{' content'}; 88 101 } -
source/tools/templatesanalyzer/unitTables.py
1 # Copyright (c) 2015 Wildfire Games 2 # 3 # Permission is hereby granted, free of charge, to any person obtaining a copy 4 # of this software and associated documentation files (the "Software"), to deal 5 # in the Software without restriction, including without limitation the rights 6 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 # copies of the Software, and to permit persons to whom the Software is 8 # furnished to do so, subject to the following conditions: 9 # 10 # The above copyright notice and this permission notice shall be included in 11 # all copies or substantial portions of the Software. 12 # 13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 # THE SOFTWARE. 20 1 21 import xml.etree.ElementTree as ET 2 22 import os 3 23 import glob 4 24 5 # What data to use6 25 AttackTypes = ["Hack","Pierce","Crush"] 7 26 Resources = ["food", "wood", "stone", "metal"] 8 27 … … 17 36 Civs = ["athen", "mace", "spart", "sele", "cart", "rome", "pers", "maur", "brit", "gaul", "iber"] 18 37 19 38 # Remote Civ templates with those strings in their name. 20 FilterOut = ["marian" ]39 FilterOut = ["marian", "thureophoros", "thorakites", "kardakes"] 21 40 22 41 # Sorting parameters for the "roster variety" table 23 42 ComparativeSortByCav = True … … 58 77 59 78 return False 60 79 80 def NumericStatProcess(unitValue, templateValue): 81 if not "op" in templateValue.attrib: 82 return float(templateValue.text) 83 if (templateValue.attrib["op"] == "add"): 84 unitValue += float(templateValue.text) 85 elif (templateValue.attrib["op"] == "sub"): 86 unitValue -= float(templateValue.text) 87 elif (templateValue.attrib["op"] == "mul"): 88 unitValue *= float(templateValue.text) 89 elif (templateValue.attrib["op"] == "div"): 90 unitValue /= float(templateValue.text) 91 return unitValue 92 93 61 94 # This function parses the entity values manually. 62 95 def CalcUnit(UnitName, existingUnit = None): 63 96 unit = { 'HP' : "0", "BuildTime" : "0", "Cost" : { 'food' : "0", "wood" : "0", "stone" : "0", "metal" : "0", "population" : "0"}, 64 97 'Attack' : { "Melee" : { "Hack" : 0, "Pierce" : 0, "Crush" : 0 }, "Ranged" : { "Hack" : 0, "Pierce" : 0, "Crush" : 0 } }, 65 'RepeatRate' : {"Melee" : "0", "Ranged" : "0"},'PrepRate' : {"Melee" : "0", "Ranged" : "0"}, "Armour" : { },66 "Ranged" : False, "Classes" : [], "AttackBonuses" : {}, "Restricted" : [], 98 'RepeatRate' : {"Melee" : "0", "Ranged" : "0"},'PrepRate' : {"Melee" : "0", "Ranged" : "0"}, "Armour" : { "Hack" : 0, "Pierce" : 0, "Crush" : 0}, 99 "Ranged" : False, "Classes" : [], "AttackBonuses" : {}, "Restricted" : [], "WalkSpeed" : 0, "Range" : 0, "Spread" : 0, 67 100 "Civ" : None } 68 101 69 102 if (existingUnit != None): … … 80 113 unit['Civ'] = Template.find("./Identity/Civ").text 81 114 82 115 if (Template.find("./Health/Max") != None): 83 unit['HP'] = Template.find("./Health/Max").text116 unit['HP'] = NumericStatProcess(unit['HP'], Template.find("./Health/Max")) 84 117 85 118 if (Template.find("./Cost/BuildTime") != None): 86 unit['BuildTime'] = Template.find("./Cost/BuildTime").text119 unit['BuildTime'] = NumericStatProcess(unit['BuildTime'], Template.find("./Cost/BuildTime")) 87 120 88 121 if (Template.find("./Cost/Resources") != None): 89 122 for type in list(Template.find("./Cost/Resources")): 90 unit['Cost'][type.tag] = type.text123 unit['Cost'][type.tag] = NumericStatProcess(unit['Cost'][type.tag], type) 91 124 92 125 if (Template.find("./Cost/Population") != None): 93 unit['Cost']["population"] = Template.find("./Cost/Population").text126 unit['Cost']["population"] = NumericStatProcess(unit['Cost']["population"], Template.find("./Cost/Population")) 94 127 95 128 if (Template.find("./Attack/Melee") != None): 96 129 if (Template.find("./Attack/Melee/RepeatTime") != None): 97 unit['RepeatRate']["Melee"] = Template.find("./Attack/Melee/RepeatTime").text130 unit['RepeatRate']["Melee"] = NumericStatProcess(unit['RepeatRate']["Melee"], Template.find("./Attack/Melee/RepeatTime")) 98 131 if (Template.find("./Attack/Melee/PrepareTime") != None): 99 unit['PrepRate']["Melee"] = Template.find("./Attack/Melee/PrepareTime").text132 unit['PrepRate']["Melee"] = NumericStatProcess(unit['PrepRate']["Melee"], Template.find("./Attack/Melee/PrepareTime")) 100 133 for atttype in AttackTypes: 101 134 if (Template.find("./Attack/Melee/"+atttype) != None): 102 unit['Attack']['Melee'][atttype] = Template.find("./Attack/Melee/"+atttype).text135 unit['Attack']['Melee'][atttype] = NumericStatProcess(unit['Attack']['Melee'][atttype], Template.find("./Attack/Melee/"+atttype)) 103 136 if (Template.find("./Attack/Melee/Bonuses") != None): 104 137 for Bonus in Template.find("./Attack/Melee/Bonuses"): 105 138 Against = [] … … 123 156 if (Template.find("./Attack/Ranged") != None): 124 157 unit['Ranged'] = True 125 158 if (Template.find("./Attack/Ranged/MaxRange") != None): 126 unit['Range'] = Template.find("./Attack/Ranged/MaxRange").text159 unit['Range'] = NumericStatProcess(unit['Range'], Template.find("./Attack/Ranged/MaxRange")) 127 160 if (Template.find("./Attack/Ranged/Spread") != None): 128 unit['Spread'] = Template.find("./Attack/Ranged/Spread").text161 unit['Spread'] = NumericStatProcess(unit['Spread'], Template.find("./Attack/Ranged/Spread")) 129 162 if (Template.find("./Attack/Ranged/RepeatTime") != None): 130 unit['RepeatRate']["Ranged"] = Template.find("./Attack/Ranged/RepeatTime").text163 unit['RepeatRate']["Ranged"] = NumericStatProcess(unit['RepeatRate']["Ranged"], Template.find("./Attack/Ranged/RepeatTime")) 131 164 if (Template.find("./Attack/Ranged/PrepareTime") != None): 132 unit['PrepRate']["Ranged"] = Template.find("./Attack/Ranged/PrepareTime").text165 unit['PrepRate']["Ranged"] = NumericStatProcess(unit['PrepRate']["Ranged"], Template.find("./Attack/Ranged/PrepareTime")) 133 166 for atttype in AttackTypes: 134 167 if (Template.find("./Attack/Ranged/"+atttype) != None): 135 unit['Attack']['Ranged'][atttype] = Template.find("./Attack/Ranged/"+atttype).text168 unit['Attack']['Ranged'][atttype] = NumericStatProcess(unit['Attack']['Ranged'][atttype], Template.find("./Attack/Ranged/"+atttype)) 136 169 if (Template.find("./Attack/Ranged/Bonuses") != None): 137 170 for Bonus in Template.find("./Attack/Ranged/Bonuses"): 138 171 Against = [] … … 155 188 if (Template.find("./Armour") != None): 156 189 for atttype in AttackTypes: 157 190 if (Template.find("./Armour/"+atttype) != None): 158 unit['Armour'][atttype] = Template.find("./Armour/"+atttype).text191 unit['Armour'][atttype] = NumericStatProcess(unit['Armour'][atttype], Template.find("./Armour/"+atttype)) 159 192 160 193 if (Template.find("./UnitMotion") != None): 161 194 if (Template.find("./UnitMotion/WalkSpeed") != None): 162 unit['WalkSpeed'] = Template.find("./UnitMotion/WalkSpeed").text195 unit['WalkSpeed'] = NumericStatProcess(unit['WalkSpeed'], Template.find("./UnitMotion/WalkSpeed")) 163 196 164 197 if (Template.find("./Identity/VisibleClasses") != None): 165 198 newClasses = Template.find("./Identity/VisibleClasses").text.split(" ") … … 209 242 ret += "<td> - </td>" 210 243 ret += "<td> - </td>" 211 244 212 if UnitDict["Ranged"] == True :245 if UnitDict["Ranged"] == True and UnitDict["Range"] > 0: 213 246 ret += "<td>" + str("%.1f" % float(UnitDict["Range"])) + "</td>" 214 247 spread = (float(UnitDict["Spread"]) / float(UnitDict["Range"]))*100.0 215 248 ret += "<td>" + str("%.1f" % spread) + "</td>"