From: <wel...@us...> - 2012-04-26 19:09:17
|
Revision: 8248 http://planeshift.svn.sourceforge.net/planeshift/?rev=8248&view=rev Author: weltall2 Date: 2012-04-26 19:09:10 +0000 (Thu, 26 Apr 2012) Log Message: ----------- Added support for defining and using modifiers on variables through the effect column <ModifierEffect operation="..." name="var.VarName" value="..." /> All the variables must have an operation="VAL" defining the default/start value then MUL and ADD can be used like other modifier effects. The default value picked up will always be only one (the last one) and the execution order of operations is from the first to the last according to the parsing system of the lootrandomizer. After this the variables will be available from the script like classic <let>. Variables names must also always be with the first letter uppercase per mathscript language. Modified Paths: -------------- trunk/src/server/lootrandomizer.cpp trunk/src/server/lootrandomizer.h Modified: trunk/src/server/lootrandomizer.cpp =================================================================== --- trunk/src/server/lootrandomizer.cpp 2012-04-26 18:45:21 UTC (rev 8247) +++ trunk/src/server/lootrandomizer.cpp 2012-04-26 19:09:10 UTC (rev 8248) @@ -290,8 +290,30 @@ oper1->equip_script.Append(oper2->equip_script); } -bool LootRandomizer::SetAttribute(const csString & op, const csString & attrName, float modifier, RandomizedOverlay* overlay, psItemStats* baseItem) +bool LootRandomizer::SetAttributeApplyOP(float* value[], float modifier, size_t amount, const csString &op) { + // Operations = ADD, MUL, SET + for (int i = 0; i < amount; i++) + { + if (op.CompareNoCase("ADD")) + { + if (value[i]) *value[i] += modifier; + } + + else if (op.CompareNoCase("MUL")) + { + if (value[i]) *value[i] *= modifier; + } + + else if (op.CompareNoCase("VAL")) + { + if (value[i]) *value[i] = modifier; + } + } +} + +bool LootRandomizer::SetAttribute(const csString & op, const csString & attrName, float modifier, RandomizedOverlay* overlay, psItemStats* baseItem, csArray<ValueModifier> &values) +{ float* value[3] = { NULL, NULL, NULL }; // Attribute Names: // item @@ -310,6 +332,22 @@ csString AttributeName(attrName); AttributeName.Downcase(); + if(AttributeName.StartsWith("var.")) + { + //if var. was found we have a script variable + //parse it and place it in the array which will be used later + //to handle those variables. + ValueModifier val; + + //start the name of the variable after var. + val.name = attrName.Slice(4); + val.value = modifier; + val.op = op; + + //add the variable to the array + values.Push(val); + return true; + } if ( AttributeName.Compare( "item.weight" ) ) { overlay->weight = baseItem->GetWeight(); @@ -367,29 +405,11 @@ value[0] = &overlay->damageStats[PSITEMSTATS_DAMAGETYPE_BLUNT]; } - // Operations = ADD, MUL, SET - for (int i = 0; i < 3; i++) - { - if (op.CompareNoCase("ADD")) - { - if (value[i]) *value[i] += modifier; - } + SetAttributeApplyOP(value, modifier, 3, op); - if (op.CompareNoCase("MUL")) - { - if (value[i]) *value[i] *= modifier; - } - - if (op.CompareNoCase("VAL")) - { - if (value[i]) *value[i] = modifier; - } - } - return true; } - void LootRandomizer::ApplyModifier(psItemStats* baseItem, RandomizedOverlay* overlay, csArray<uint32_t>& modifierIds) { LootModifier mod; @@ -397,6 +417,7 @@ //set up default mod data mod.cost_modifier = 1; mod.name = baseItem->GetName(); + csArray<ValueModifier> variableValues; //creates the full lootmodifier from the ids being applied. //0 should be left empty in the database as it acts as NO HIT. @@ -409,7 +430,7 @@ if(partialModifier) { overlay->active = true; - AddModifier(&mod,partialModifier); + AddModifier(&mod, partialModifier); } } } @@ -463,7 +484,7 @@ csString EffectName = node->GetAttribute("name")->GetValue(); float EffectValue = node->GetAttribute("value")->GetValueAsFloat(); //Add to the Attributes - if (!SetAttribute(EffectOp, EffectName, EffectValue, overlay, baseItem)) + if (!SetAttribute(EffectOp, EffectName, EffectValue, overlay, baseItem, variableValues)) { // display error and continue Error2("Unable to set attribute %s on new loot item.",EffectName.GetData()); @@ -513,8 +534,7 @@ // Apply equip script if (!mod.equip_script.IsEmpty()) { - csString scriptXML; - scriptXML.Format("<apply aim=\"Actor\" name=\"%s\" type=\"buff\">%s</apply>", mod.name.GetData(), mod.equip_script.GetData()); + csString scriptXML = GenerateScriptXML(mod.name, mod.equip_script, variableValues); overlay->equip_script = ApplicativeScript::Create(psserver->entitymanager, psserver->GetCacheManager(), scriptXML); } @@ -523,6 +543,72 @@ overlay->latency = 1.5F; } +csString LootRandomizer::GenerateScriptXML(csString &name, csString &equip_script, csArray<ValueModifier> &values) +{ + csString scriptXML = ""; + csHash<float, csString> results; + //parse the values and try to find the default values for all variables + //and put them in the hash in order to simplify access. + for(size_t i = 0; i < values.GetSize(); ++i) + { + //Do it only for the VAL references which identify a default value. + if(values[i].op.CompareNoCase("VAL")) + { + results.PutUnique(values[i].name, values[i].value); + //delete the entry as we don't need it anymore, in order to reduce the + //amount of items to check later + values.DeleteIndex(i); + //reduce the index as we have removed an item + i--; + } + } + //then do all the others operation entries, in order of definition. + for(size_t i = 0; i < values.GetSize(); ++i) + { + //first of all check if the item is available in its default value + //if it's not we are ignoring the operation as the variable is not + //defined. + if(results.Contains(values[i].name)) + { + //we don't check for null as at this point it's safe the presence + //of the variable in the hash (due to the check of contains). + float* value[1] = {results.GetElementPointer(values[i].name)}; + SetAttributeApplyOP(value, values[i].value, 1, values[i].op); + } + else + { + Error2("Unable to find base value for variable %s", values[i].name.GetData()); + } + } + + //if we have any variable defined we add their definition on top of the script. + //By defining each variable in a <let> entry for the script. It will be skipped + //if no variables are defined. + if(!results.IsEmpty()) + { + scriptXML.Format("<let vars=\""); + csHash<float, csString>::GlobalIterator it = results.GetIterator(); + while(it.HasNext()) + { + csTuple2<float, csString> entry = it.NextTuple(); + scriptXML.AppendFmt("%s = %f;", entry.second.GetData(), entry.first); + } + scriptXML.AppendFmt("\">"); + } + + //now copy the body of the script containing the equip script from the random loot entries. + scriptXML.AppendFmt("<apply aim=\"Actor\" name=\"%s\" type=\"buff\">%s</apply>", name.GetData(), equip_script.GetData()); + + //if we added the <let> we need to close it. + if(!results.IsEmpty()) + { + scriptXML.AppendFmt("</let>"); + } + + return scriptXML; +} + + LootModifier *LootRandomizer::GetModifier(uint32_t id) { return LootModifiersById.Get(id, NULL); Modified: trunk/src/server/lootrandomizer.h =================================================================== --- trunk/src/server/lootrandomizer.h 2012-04-26 18:45:21 UTC (rev 8247) +++ trunk/src/server/lootrandomizer.h 2012-04-26 19:09:10 UTC (rev 8248) @@ -41,6 +41,17 @@ csHash<bool, uint32> itemRestrain; ///< Contains if the itemid is allowed or not. item id 0 means all items, false means disallowed. }; +/** + * This structure contains the parsed data from Attributes + * recarding script variables. + */ +struct ValueModifier +{ + csString name; ///< The name of the variable. + csString op; ///< The operation parsed for this reference to the variable ADD, MUL, VAL (VAL is the default value, at least one is needed). + float value; ///< The value to apply to the variable through the requested operation in op. +}; + class MathScript; /** * This class stores an array of LootModifiers and randomizes @@ -107,8 +118,28 @@ * @param modifier The amount to change of the attribute (right operand, left operand is the basic attribute) * @param overlay The randomization overlay where we are applying these attributes. * @param baseItem The base item of the item we are applying these attributes to + * @param values An array which will be filled with the variables defined as attribute (var.Name). It's important the name + * starts with an Uppercase letter because of mathscript restrains. */ - bool SetAttribute(const csString & op, const csString & attrName, float modifier, RandomizedOverlay* overlay, psItemStats* baseItem); + bool SetAttribute(const csString & op, const csString & attrName, float modifier, RandomizedOverlay* overlay, psItemStats* baseItem, csArray<ValueModifier> &values); + + /** + * Sets the attributes in the passed float array according to the passed parameters. + * @param value An array of pointers to floats containing the value to be modified. + * @param modifier The amount to apply through all the array values. + * @param amount The size of the passed array of pointers. + * @param op The specifier of the operation to fullfill: ADD, MUL, VAL. + */ + bool SetAttributeApplyOP(float* value[], float modifier, size_t amount, const csString &op); + + /** + * Generates the equip script amended with the defined variables. + * @param name The name of the item. + * @param equip_script The inner equip script defined in the equip_script column of the database. + * @param values An array of values parsed from the set attributes which will be used to add in the + * equip_script environment those variables. + */ + csString GenerateScriptXML(csString &name, csString &equip_script, csArray<ValueModifier> &values); }; #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |