/// <summary> /// Setter function (can use vars like THIS().xmlobjs.test can be accessed with XMLOBJS(THIS(), xmlobjs.varName) with this function, which you can't do with with THIS().xmlobjs._____ alone /// </summary> /// <param name="trigObject"></param> /// <param name="o"></param> /// <param name="name"></param> /// <param name="value"></param> /// <returns></returns> public static void XMLOBJS(TriggerObject trigObject, IEntity o, string name, object value) { if (!(o is Mobile || o is Item)) { throw new UberScriptException("Can't set xmlobjs on anything but Mobile or Item"); } var arglist = name.Split('.'); XmlObject xmlObject = XmlAttach.GetObjectAttachment(o, arglist[0]); if (xmlObject == null) { // arglist should only have [xmlints, name], nothing more if (arglist.Length > 1) { throw new UberScriptException("Attempted to set property on a not-yet-existant attachment!:" + name); } xmlObject = new XmlObject(arglist[0], value); XmlAttach.AttachTo(null, o, xmlObject); } else if (arglist.Length == 1) { xmlObject.Value = value; } else if (arglist.Length > 1) { // XmlObject only contains a few properties that // can be accessed through statements like THIS().xmlobjs.test._____ // since there is a potential conflict between the developer wanting access // to the properties on the object contained in the XmlObject.Value (most likely) // or the properties on the XmlObject itself (far less likely) string testPropName = arglist[1].ToLower(); // to access properties on the xmlobject itself (e.g. expiration), one must do this: // THIS().xmlobjs.test.xmlobject.expiration if (testPropName == "xmlobject") { if (arglist.Length < 3) { throw new UberScriptException("Can't set an xmlobject directly, use ATTACH function!"); } string propLookup = arglist[2]; // add this first so later additions all prepended with '.' for (int i = 3; i < arglist.Length; i++) { propLookup += "." + arglist[i]; } PropertySetters.SetPropertyValue(trigObject, xmlObject, propLookup, value); } else { string propLookup = arglist[1]; // add this first so later additions all prepended with '.' for (int i = 2; i < arglist.Length; i++) { propLookup += "." + arglist[i]; } PropertySetters.SetPropertyValue(trigObject, xmlObject.Value, propLookup, value); } } }
// These functions are borrowed heavily from ArteGordon's BaseXmlSpawner class // set property values with support for nested attributes public static void SetPropertyValue(TriggerObject trigObj, object o, string name, object value) { if (o == null) { throw new UberScriptException("Null object"); } //Type ptype = null; object po = null; Type type = o.GetType(); PropertyInfo[] props = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); // parse the strings of the form property.attribute into two parts // first get the property List<string> arglist = PropertyGetters.PropSplitter(name); string propname = arglist[0]; if (propname.Length == 0) throw new UberScriptException("Empty string property!"); // Check whether they are trying to set an xml attachment through the // shortcut e.g. TRIGMOB().xmlints.score = TRIGMOB().xmlints.score + 1 if (arglist.Count > 1 && (propname[0] == 'x' || propname[0] == 'X')) { // NEED TO HANDLE SETTING PROPERTIES ON THE ATTACHMENTS! string lowerPropName = propname.ToLower(); if (lowerPropName == "xmlints") { IEntity entity = o as IEntity; if (entity == null) throw new UberScriptException("Can't set xmlints on anything but Mobile or Item"); // check for existing xmlValue attachment or create a new one XmlValue xmlValue = XmlAttach.GetValueAttachment(entity, arglist[1]); if (xmlValue == null) { // arglist should only have [xmlints, name], nothing more if (arglist.Count > 2) throw new UberScriptException("Attempted to set property on a not-yet-existant attachment!:" + name ); xmlValue = new XmlValue(arglist[1], (int)value); XmlAttach.AttachTo(null, entity, xmlValue); } else if (arglist.Count == 2) { if (value == null) { xmlValue.Delete(); } else { xmlValue.Value = (int)value; } } else if (arglist.Count > 2) { // could be setting a property on an existing XmlAttachment! // e.g. xmlints.test.expiration = 0:0:1 SetPropertyValue(trigObj, xmlValue, arglist[2], value); } return; } else if (lowerPropName == "xmlstrings") { IEntity entity = o as IEntity; if (entity == null) throw new UberScriptException("Can't set xmlstrings on anything but Mobile or Item"); XmlLocalVariable xmlLocalVariable = XmlAttach.GetStringAttachment(entity, arglist[1]); if (xmlLocalVariable == null) { // arglist should only have [xmlints, name], nothing more if (arglist.Count > 2) throw new UberScriptException("Attempted to set property on a not-yet-existant attachment!:" + name); xmlLocalVariable = new XmlLocalVariable(arglist[1], (string)value); XmlAttach.AttachTo(null, entity, xmlLocalVariable); } else if (arglist.Count == 2) { if (value == null) { xmlLocalVariable.Delete(); } else { xmlLocalVariable.Data = (string)value; } } else if (arglist.Count > 2) { // could be setting a property on an existing XmlAttachment! // e.g. xmlints.test.expiration = 0:0:1 SetPropertyValue(trigObj, xmlLocalVariable, arglist[2], value); } return; } else if (lowerPropName == "xmldoubles") { IEntity entity = o as IEntity; if (entity == null) throw new UberScriptException("Can't set xmldoubles on anything but Mobile or Item"); XmlDouble xmlDouble = XmlAttach.GetDoubleAttachment(entity, arglist[1]); if (xmlDouble == null) { // arglist should only have [xmlints, name], nothing more if (arglist.Count > 2) throw new UberScriptException("Attempted to set property on a not-yet-existant attachment!:" + name); xmlDouble = new XmlDouble(arglist[1], (double)value); XmlAttach.AttachTo(null, entity, xmlDouble); } else if (arglist.Count == 2) { if (value == null) { xmlDouble.Delete(); } else { xmlDouble.Value = (double)value; } } else if (arglist.Count > 2) { // could be setting a property on an existing XmlAttachment! // e.g. xmlints.test.expiration = 0:0:1 SetPropertyValue(trigObj, xmlDouble, arglist[2], value); } return; } else if (lowerPropName == "xmlobjs") { IEntity entity = o as IEntity; if (entity == null) throw new UberScriptException("Can't set xmlobjs on anything but Mobile or Item"); XmlObject xmlObject = XmlAttach.GetObjectAttachment(entity, arglist[1]); if (xmlObject == null) { // arglist should only have [xmlints, name], nothing more if (arglist.Count > 2) throw new UberScriptException("Attempted to set property on a not-yet-existant attachment!:" + name); xmlObject = new XmlObject(arglist[1], value); XmlAttach.AttachTo(null, entity, xmlObject); } else if (arglist.Count == 2) { if (value == null) { xmlObject.Delete(); } else { xmlObject.Value = value; } } else if (arglist.Count > 2) { // XmlObject only contains a few properties that // can be accessed through statements like THIS().xmlobjs.test._____ // since there is a potential conflict between the developer wanting access // to the properties on the object contained in the XmlObject.Value (most likely) // or the properties on the XmlObject itself (far less likely) string testPropName = arglist[2].ToLower(); // to access properties on the xmlobject itself (e.g. expiration), one must do this: // THIS().xmlobjs.test.xmlobject.expiration if (testPropName == "xmlobject") { if (arglist.Count < 4) { throw new UberScriptException("Can't set an xmlobject directly, use ATTACH function!"); } else { string propLookup = arglist[3]; // add this first so later additions all prepended with '.' for (int i = 4; i < arglist.Count; i++) { propLookup += "." + arglist[i]; } SetPropertyValue(trigObj, xmlObject, propLookup, value); } } else { string propLookup = arglist[2]; // add this first so later additions all prepended with '.' for (int i = 3; i < arglist.Count; i++) { propLookup += "." + arglist[i]; } SetPropertyValue(trigObj, xmlObject.Value, propLookup, value); } } //else if (arglist.Count > 2) //{ // could be setting a property on an existing XmlAttachment! // e.g. xmlints.test.expiration = 0:0:1 // SetPropertyValue(trigObject, xmlObject, arglist[2], value); //} return; } } /* string[] keywordargs = ParseString(propname, 4, ","); // check for special keywords if (keywordargs[0] == "ATTACHMENT") { if (keywordargs.Length < 4) { return "Invalid ATTACHMENT format"; } // syntax is ATTACHMENT,type,name,propname string apropname = keywordargs[3]; string aname = keywordargs[2]; Type attachtype = SpawnerType.GetType(keywordargs[1]); // allow empty string specifications to be used to indicate a null string which will match any name if (aname == "") aname = null; ArrayList attachments = XmlAttach.FindAttachments(o, attachtype, aname); if (attachments != null && attachments.Count > 0) { // change the object, object type, and propname to refer to the attachment o = attachments[0]; propname = apropname; if (o == null) { return "Null object"; } type = o.GetType(); props = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); } else return "Attachment not found"; } else if (keywordargs[0] == "SKILL") { if (keywordargs.Length < 2) { return "Invalid SKILL format"; } bool found = true; try { SkillName skillname = (SkillName)Enum.Parse(typeof(SkillName), keywordargs[1], true); if (o is Mobile) { Skill skill = ((Mobile)o).Skills[skillname]; skill.Base = double.Parse(value); return "Property has been set."; } else return "Object is not mobile"; } catch { found = false; } if (!found) return "Invalid SKILL reference."; } else if (keywordargs[0] == "STEALABLE") { bool found = true; try { if (o is Item) { ItemFlags.SetStealable(o as Item, bool.Parse(value)); return "Property has been set."; } else return "Object is not an item"; } catch { found = false; } if (!found) return "Invalid Stealable assignment."; } * */ // do a bit of parsing to handle array references string[] arraystring = propname.Split('['); int index = 0; if (arraystring.Length > 1) { // parse the property name from the indexing propname = arraystring[0]; // then parse to get the index value string[] arrayvalue = arraystring[1].Split(']'); if (arrayvalue.Length > 0) { try { index = int.Parse(arrayvalue[0]); } catch { try { index = (int)(new MathTree(null, arrayvalue[0])).Calculate(trigObj); } catch { throw new UberScriptException("Could not get int array value from: " + arrayvalue[0] + " for prop of " + name + " on object " + o); } } } } PropertyInfo propInfoToSet = null; string lowerCasePropName = propname.ToLower(); // optimization to find propertyInfo without looping through if (o is BaseCreature) { if (BaseCreatureProperties.ContainsKey(lowerCasePropName)) propInfoToSet = BaseCreatureProperties[lowerCasePropName]; } else if (o is PlayerMobile) { if (PlayerMobileProperties.ContainsKey(lowerCasePropName)) propInfoToSet = PlayerMobileProperties[lowerCasePropName]; } else if (o is Item) { if (ItemProperties.ContainsKey(lowerCasePropName)) propInfoToSet = ItemProperties[lowerCasePropName]; } // is a nested property with attributes so first get the property if (propInfoToSet == null) foreach (PropertyInfo p in props) { if (Insensitive.Equals(p.Name, propname)) { propInfoToSet = p; break; } } if (propInfoToSet != null) { //if (IsProtected(type, propname)) // return "Property is protected."; if (arglist.Count > 1) { //ptype = propInfoToSet.PropertyType; po = propInfoToSet.GetValue(o, null); // now set the nested attribute using the new property list string propLookup = arglist[1]; for (int i = 2; i < arglist.Count; i++) { propLookup += "." + arglist[i]; } SetPropertyValue(trigObj, po, propLookup, value); return; // otherwise let it roll through and throw an exception } else // arglist.Count == 1 { //if (IsProtected(type, propname)) // return "Property is protected."; if (!propInfoToSet.CanWrite) throw new UberScriptException("Property is read only."); InternalSetValue(o, propInfoToSet, value, false, index); return; } } throw new UberScriptException("Property " + name + " not found on " + o + "."); }