public static bool SpawnTypeKeyword(object invoker, XmlSpawner.SpawnObject TheSpawn, string typeName, string substitutedtypeName, bool requiresurface, List<XmlSpawner.SpawnPositionInfo> spawnpositioning, Mobile triggermob, Point3D location, Map map, XmlGumpCallback gumpcallback, out string status_str) { status_str = null; if (typeName == null || TheSpawn == null || substitutedtypeName == null) return false; XmlSpawner spawner = invoker as XmlSpawner; // check for any special keywords that might appear in the type such as SET, GIVE, or TAKE if (IsTypeKeyword(typeName)) { typeKeyword kw = (typeKeyword)typeKeywordHash[typeName]; switch (kw) { case typeKeyword.SET: { // the syntax is SET/prop/value/prop2/value... // check for the SET,itemname[,itemtype]/prop/value form is used string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length > 1) { string typestr = null; if (keywordargs.Length > 2) { typestr = keywordargs[2]; } // is the itemname a serialno? object setitem = null; if (keywordargs[1].StartsWith("0x")) { int serial = -1; try { serial = Convert.ToInt32(keywordargs[1], 16); } catch { } if (serial >= 0) setitem = World.FindEntity(serial); } else { // just look it up by name setitem = FindItemByName(spawner, keywordargs[1], typestr); } if (setitem == null) { status_str = "cant find unique item :" + keywordargs[1]; return false; } else { ApplyObjectStringProperties(spawner, substitutedtypeName, setitem, triggermob, invoker, out status_str); } } else if (spawner != null) { ApplyObjectStringProperties(spawner, substitutedtypeName, spawner.SetItem, triggermob, invoker, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONMOB: { // the syntax is SETONMOB,mobname[,mobtype]/prop/value/prop2/value... string[] arglist = ParseSlashArgs(substitutedtypeName, 3); Mobile mob = null; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length > 1) { string typestr = null; if (keywordargs.Length > 2) { typestr = keywordargs[2]; } mob = FindMobileByName(spawner, keywordargs[1], typestr); if (mob == null) { status_str = String.Format("named mob '{0}' not found", keywordargs[1]); } } else { status_str = "missing mob name in SETONMOB"; } } if (mob != null) { ApplyObjectStringProperties(spawner, substitutedtypeName, mob, triggermob, invoker, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONTHIS: { // the syntax is SETONTHIS/prop/value/prop2/value... //string [] arglist = ParseString(substitutedtypeName,3,"/"); if (invoker != null) { ApplyObjectStringProperties(spawner, substitutedtypeName, invoker, triggermob, invoker, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONTRIGMOB: { // the syntax is SETONTRIGMOB/prop/value/prop2/value... ApplyObjectStringProperties(spawner, substitutedtypeName, triggermob, triggermob, invoker, out status_str); TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETACCOUNTTAG: { // the syntax is SETACCOUNTTAG,tagname/value string[] arglist = ParseSlashArgs(substitutedtypeName, 2); if (arglist.Length > 1) { string[] objstr = ParseString(arglist[0], 2, ","); if (objstr.Length < 2) { status_str = "missing tagname in SETACCOUNTTAG"; return false; } string tagname = objstr[1]; string tagval = arglist[1]; // set the tag value // get the value of the account tag from the triggering mob if (triggermob != null && !triggermob.Deleted) { Account acct = triggermob.Account as Account; if (acct != null) { acct.SetTag(tagname, tagval); } } } else { status_str = "no value assigned to SETACCOUNTTAG"; return false; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETVAR: { // the syntax is SETVAR,varname/value string[] arglist = ParseSlashArgs(substitutedtypeName, 2); if (arglist.Length > 1) { string[] objstr = ParseString(arglist[0], 2, ","); if (objstr.Length < 2) { status_str = "missing varname in SETVAR"; return false; } string varname = objstr[1]; string varval = arglist[1]; // find the xmllocalvariable attachment with that name XmlLocalVariable a = (XmlLocalVariable)XmlAttach.FindAttachment(invoker, typeof(XmlLocalVariable), varname); if (a == null) { // doesnt already exist so add it XmlAttach.AttachTo(invoker, new XmlLocalVariable(varname, varval)); } else { a.Data = varval; } } else { status_str = "no value assigned to SETVAR"; return false; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONNEARBY: { // the syntax is SETONNEARBY,range,name[,type][,searchcontainers][,proptest]/prop/value/prop/value... string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string typestr = null; string targetname = null; string proptest = null; int range = -1; bool searchcontainers = false; if (arglist.Length > 0) { string[] objstr = ParseString(arglist[0], 6, ","); if (objstr.Length < 3) { status_str = "missing range or name in SETONNEARBY"; return false; } try { range = int.Parse(objstr[1]); } catch { } if (range < 0) { status_str = "invalid range in SETONNEARBY"; return false; } targetname = objstr[2]; if (objstr.Length > 3) { typestr = objstr[3]; } if (objstr.Length > 4) { try { searchcontainers = bool.Parse(objstr[4]); } catch { } } if (objstr.Length > 5) { proptest = objstr[5]; } } else { status_str = "missing args to SETONNEARBY"; return false; } Type targettype = null; if (typestr != null) { targettype = SpawnerType.GetType(typestr); } ArrayList nearbylist = GetNearbyObjects(invoker, targetname, targettype, typestr, range, searchcontainers, proptest); // apply the properties to everything on the list foreach (object nearbyobj in nearbylist) { ApplyObjectStringProperties(spawner, substitutedtypeName, nearbyobj, triggermob, invoker, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONPETS: { // the syntax is SETONPETS,range/prop/value/prop/value... string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string typestr = "BaseCreature"; string targetname = null; int range = -1; bool searchcontainers = false; if (arglist.Length > 0) { string[] objstr = ParseString(arglist[0], 2, ","); if (objstr.Length < 2) { status_str = "missing range or name in SETONPETS"; return false; } try { range = int.Parse(objstr[1]); } catch { } if (range < 0) { status_str = "invalid range in SETONPETS"; return false; } } else { status_str = "missing args to SETONPETS"; return false; } Type targettype = null; if (typestr != null) { targettype = SpawnerType.GetType(typestr); } // get all of the nearby pets ArrayList nearbylist = GetNearbyObjects(triggermob, targetname, targettype, typestr, range, searchcontainers, null); // apply the properties to everything on the list foreach (object nearbyobj in nearbylist) { // is this a pet of the triggering mob BaseCreature pet = nearbyobj as BaseCreature; if (pet != null && pet.Controlled && pet.ControlMaster == triggermob) { ApplyObjectStringProperties(spawner, substitutedtypeName, nearbyobj, triggermob, invoker, out status_str); } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONCARRIED: { // the syntax is SETONCARRIED,itemname[,itemtype][,equippedonly]/prop/value/prop2/value... // or SETONCARRIED,itemname[,itemtype]/prop/value // first find the carried item string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string typestr = null; string itemname = null; bool equippedonly = false; if (arglist.Length > 0) { string[] objstr = ParseString(arglist[0], 4, ","); if (objstr.Length < 2) { status_str = "missing itemname in SETONCARRIED"; return false; } itemname = objstr[1]; if (objstr.Length > 2) { typestr = objstr[2]; } if (objstr.Length > 3) { if (objstr[3].ToLower() == "equippedonly") { equippedonly = true; } else { try { equippedonly = bool.Parse(objstr[3]); } catch { } } } } else { status_str = "missing args to SETONCARRIED"; return false; } Item testitem = SearchMobileForItem(triggermob, ParseObjectType(itemname), typestr, false, equippedonly); ApplyObjectStringProperties(spawner, substitutedtypeName, testitem, triggermob, invoker, out status_str); TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONSPAWN: { // the syntax is SETONSPAWN[,spawnername],subgroup/prop/value/prop2/value... // or SETONSPAWN[,spawnername],subgroup/prop/value // first find the spawn int subgroup = -1; string[] arglist = ParseSlashArgs(substitutedtypeName, 3); XmlSpawner targetspawner = spawner; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length < 2) { status_str = "missing subgroup in SETONSPAWN"; return false; } else { string subgroupstr = keywordargs[1]; string spawnerstr = null; if (keywordargs.Length > 2) { spawnerstr = keywordargs[1]; subgroupstr = keywordargs[2]; } if (spawnerstr != null) { targetspawner = FindSpawnerByName(spawner, spawnerstr); } try { subgroup = int.Parse(subgroupstr); } catch { } } } if (subgroup == -1) { status_str = "invalid subgroup in SETONSPAWN"; return false; } ArrayList spawnedlist = XmlSpawner.GetSpawnedList(targetspawner, subgroup); if (spawnedlist == null) return true; foreach (object targetobj in spawnedlist) { if (targetobj == null) return true; // dont apply it to keyword tags if (targetobj is KeywordTag) continue; // set the properties on the target object ApplyObjectStringProperties(spawner, substitutedtypeName, targetobj, triggermob, spawner, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONSPAWNENTRY: { // the syntax is SETONSPAWNENTRY[,spawnername],entrystring/prop/value/prop2/value... // find the spawn entry string entrystring = null; string[] arglist = ParseSlashArgs(substitutedtypeName, 3); XmlSpawner targetspawner = spawner; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length < 2) { status_str = "missing entrystring in SETONSPAWNENTRY"; return false; } else { entrystring = keywordargs[1]; string spawnerstr = null; if (keywordargs.Length > 2) { spawnerstr = keywordargs[1]; entrystring = keywordargs[2]; } if (spawnerstr != null) { targetspawner = FindSpawnerByName(spawner, spawnerstr); } } } if (entrystring == null || entrystring.Length == 0) { status_str = "invalid entrystring in SETONSPAWNENTRY"; return false; } int entryindex = -1; // is the entrystring a number? if (entrystring[0] >= '0' && entrystring[0] <= '9') { try { entryindex = int.Parse(entrystring); } catch { } } if (targetspawner == null || targetspawner.SpawnObjects == null) return true; for (int i = 0; i < targetspawner.SpawnObjects.Length; i++) { XmlSpawner.SpawnObject targetobj = targetspawner.SpawnObjects[i]; // is this references by entrystring or entryindex? if ((entryindex == i) || (entryindex == -1 && targetobj != null && targetobj.TypeName != null && targetobj.TypeName.IndexOf(entrystring) >= 0)) { // set the properties on the spawn entry object ApplyObjectStringProperties(spawner, substitutedtypeName, targetobj, triggermob, spawner, out status_str); } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SETONPARENT: { // the syntax is SETONPARENT/prop/value/prop2/value... string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (invoker != null && (invoker is Item)) { ApplyObjectStringProperties(spawner, substitutedtypeName, ((Item)invoker).Parent, triggermob, invoker, out status_str); } else if (invoker != null && (invoker is XmlAttachment)) { ApplyObjectStringProperties(spawner, substitutedtypeName, ((XmlAttachment)invoker).Attached, triggermob, invoker, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.GIVE: { string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string remainder; if (arglist.Length > 1) { // check for any special keywords such as the additem option or the subproperty specification // note this will be an arg to some property string[] keywordargs = ParseString(arglist[0], 2, ","); AddItemToTarget(spawner, triggermob, keywordargs, arglist, triggermob, invoker, false, out remainder, out status_str); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.TAKE: { // syntax TAKE[,prob[,quantity[,true,[type]]]]/itemname string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string targetName; string typestr = null; if (arglist.Length > 1) { targetName = arglist[1]; } else { status_str = "invalid TAKE specification"; return false; } string[] keywordargs = ParseString(arglist[0], 5, ","); double drop_probability = 1; int quantity = 0; bool banksearch = false; Item savedItem = null; if (keywordargs.Length > 1) { bool converterror = false; try { drop_probability = Convert.ToDouble(keywordargs[1], CultureInfo.InvariantCulture); } catch { status_str = "Invalid TAKE probability : " + arglist[1]; converterror = true; } if (converterror) return false; } if (keywordargs.Length > 2) { bool converterror = false; try { quantity = int.Parse(keywordargs[2]); } catch { status_str = "Invalid TAKE quantity : " + arglist[1]; converterror = true; } if (converterror) return false; } if (keywordargs.Length > 3) { bool converterror = false; try { banksearch = bool.Parse(keywordargs[3]); } catch { status_str = "Invalid TAKE bankflag : " + arglist[1]; converterror = true; } if (converterror) return false; } if (keywordargs.Length > 4) { typestr = keywordargs[4]; } if (drop_probability == 1 || Utility.RandomDouble() < drop_probability) { // search the trigger mob for the named item Item itemTarget = SearchMobileForItem(triggermob, targetName, typestr, banksearch); // found the item so get rid of it if (itemTarget != null) { // if a quantity was specified and the item is stackable, then try to take the quantity if (quantity > 0 && itemTarget.Stackable) { // create a copy of the stacked item to be saved //savedItem = itemTarget.Dupe(0); savedItem = Mobile.LiftItemDupe(itemTarget, itemTarget.Amount); if (savedItem != null) { savedItem.Internalize(); } int totaltaken = 0; int remaining = itemTarget.Amount - quantity; if (remaining <= 0) { int taken = itemTarget.Amount; totaltaken += taken; itemTarget.Delete(); while (remaining < 0) { quantity -= taken; // if didnt get the full amount then keep looking for other stacks itemTarget = SearchMobileForItem(triggermob, targetName, typestr, banksearch); if (itemTarget == null) break; remaining = itemTarget.Amount - quantity; if (remaining <= 0) { taken = itemTarget.Amount; totaltaken += taken; itemTarget.Delete(); } else { totaltaken += quantity; itemTarget.Amount = remaining; } } } else { totaltaken = quantity; itemTarget.Amount = remaining; } if (savedItem != null) { savedItem.Amount = totaltaken; } } else { // dont save quest holders if (itemTarget is XmlQuestBook || itemTarget is IXmlQuest) { itemTarget.Delete(); } else savedItem = itemTarget; } // if the saved item was being held then release it otherwise the player can take it back if (triggermob != null && triggermob.Holding == savedItem) { triggermob.Holding = null; } XmlSaveItem si = (XmlSaveItem)XmlAttach.FindAttachment(invoker, typeof(XmlSaveItem), "Taken"); if (si == null) { XmlAttach.AttachTo(invoker, new XmlSaveItem("Taken", savedItem, triggermob)); } else { si.SavedItem = savedItem; si.WasOwnedBy = triggermob; } } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.TAKEBYTYPE: { // syntax TAKEBYTYPE[,prob[,quantity[,true]]]/itemtype string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string targetName; if (arglist.Length > 1) { targetName = arglist[1]; } else { status_str = "invalid TAKEBYTYPE specification"; return false; } string[] keywordargs = ParseString(arglist[0], 4, ","); double drop_probability = 1; int quantity = 0; bool banksearch = false; Item savedItem = null; if (keywordargs.Length > 1) { bool converterror = false; try { drop_probability = Convert.ToDouble(keywordargs[1], CultureInfo.InvariantCulture); } catch { status_str = "Invalid TAKEBYTYPE probability : " + arglist[1]; converterror = true; } if (converterror) return false; } if (keywordargs.Length > 2) { bool converterror = false; try { quantity = int.Parse(keywordargs[2]); } catch { status_str = "Invalid TAKEBYTYPE quantity : " + arglist[1]; converterror = true; } if (converterror) return false; } if (keywordargs.Length > 3) { bool converterror = false; try { banksearch = bool.Parse(keywordargs[3]); } catch { status_str = "Invalid TAKEBYTYPE bankflag : " + arglist[1]; converterror = true; } if (converterror) return false; } if (drop_probability == 1 || Utility.RandomDouble() < drop_probability) { // search the trigger mob for the named item Item itemTarget = SearchMobileForItemType(triggermob, targetName, banksearch); // found the item so get rid of it if (itemTarget != null) { // if a quantity was specified and the item is stackable, then try to take the quantity if (quantity > 0 && itemTarget.Stackable) { // create a copy of the stacked item to be saved //savedItem = itemTarget.Dupe(0); savedItem = Mobile.LiftItemDupe(itemTarget, itemTarget.Amount); if (savedItem != null) { savedItem.Internalize(); } int totaltaken = 0; int remaining = itemTarget.Amount - quantity; if (remaining <= 0) { int taken = itemTarget.Amount; totaltaken += taken; itemTarget.Delete(); while (remaining < 0) { quantity -= taken; // if didnt get the full amount then keep looking for other stacks itemTarget = SearchMobileForItemType(triggermob, targetName, banksearch); if (itemTarget == null) break; remaining = itemTarget.Amount - quantity; if (remaining <= 0) { taken = itemTarget.Amount; totaltaken += taken; itemTarget.Delete(); } else { totaltaken += quantity; itemTarget.Amount = remaining; } } } else { totaltaken = quantity; itemTarget.Amount = remaining; } if (savedItem != null) { savedItem.Amount = totaltaken; } } else { // dont save quest holders if (itemTarget is XmlQuestBook || itemTarget is XmlQuestHolder || itemTarget is XmlQuestToken) { itemTarget.Delete(); } else savedItem = itemTarget; } } // is there an existing xmlsaveitem attachment XmlSaveItem si = (XmlSaveItem)XmlAttach.FindAttachment(invoker, typeof(XmlSaveItem), "Taken"); if (si == null) { XmlAttach.AttachTo(invoker, new XmlSaveItem("Taken", savedItem, triggermob)); } else { si.SavedItem = savedItem; si.WasOwnedBy = triggermob; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.GUMP: { // the syntax is GUMP,title,type/string // can alternatively accept a gump constructor name // GUMP,title,type,constructorname/string string[] arglist = ParseSlashArgs(substitutedtypeName, 3); string gumpText; if (arglist.Length > 1) { gumpText = arglist[1]; } else { status_str = "invalid GUMP specification"; return false; } string[] gumpkeywordargs = ParseString(arglist[0], 4, ","); string gumpTitle = ""; int gumpNumber = 0; // 0=simple text gump, 1=yes/no gump, 2=reply gump, 3=quest gump if (gumpkeywordargs.Length > 2) { gumpTitle = gumpkeywordargs[1]; bool converterror = false; try { gumpNumber = int.Parse(gumpkeywordargs[2]); } catch { status_str = "Invalid GUMP args"; converterror = true; } if (converterror) return false; } else { status_str = "invalid GUMP specification"; return false; } string gumptypestr = "XmlSimpleGump"; // default gump constructor if (gumpkeywordargs.Length > 3) { // get the gump constructor type gumptypestr = gumpkeywordargs[3].Trim(); } Type type = null; if (gumptypestr != null) { try { type = SpawnerType.GetType(gumptypestr); } catch { } } if (type == null) { status_str = "invalid GUMP constructor : " + gumptypestr; return false; } // prepare the keyword tag for the gump KeywordTag newtag = new KeywordTag(substitutedtypeName, spawner, 1); if (triggermob != null && !triggermob.Deleted && (triggermob is PlayerMobile)) { object newgump = null; object[] gumpargs = new object[7]; gumpargs[0] = invoker; gumpargs[1] = gumpText; gumpargs[2] = gumpTitle; gumpargs[3] = gumpNumber; gumpargs[4] = newtag; gumpargs[5] = triggermob; gumpargs[6] = gumpcallback; //spawner.TriggerMob.SendGump( new XmlSimpleGump(this, gumpText,gumpTitle, gumpType )); try { newgump = Activator.CreateInstance(type, gumpargs); } catch { status_str = "Error in creating gump type : " + gumptypestr; newtag.Delete(); return false; } if (newgump != null) { if (newgump is Gump) { triggermob.SendGump((Gump)newgump); } else if (newgump is Item) { ((Item)newgump).Delete(); status_str = gumptypestr + " is not a Gump type"; newtag.Delete(); return false; } else if (newgump is Mobile) { ((Mobile)newgump).Delete(); status_str = gumptypestr + " is not a Gump type"; newtag.Delete(); return false; } else { status_str = gumptypestr + " is not a Gump type"; newtag.Delete(); return false; } } } TheSpawn.SpawnedObjects.Add(newtag); break; } case typeKeyword.BROWSER: { // the syntax is BROWSER/url string[] arglist = ParseSlashArgs(substitutedtypeName, 2); string url; if (arglist.Length > 1) { if (arglist[1] != null && arglist[1].Length > 0 && arglist[1][0] == '@') { url = arglist[1].Substring(1); } else url = arglist[1]; } else { status_str = "invalid BROWSER specification"; return false; } if (triggermob != null && !triggermob.Deleted && (triggermob is PlayerMobile)) { triggermob.LaunchBrowser(url); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SENDMSG: { // the syntax is SENDMSG[,hue]/string string[] arglist = ParseSlashArgs(substitutedtypeName, 3); // check for literal string msgText; int hue = 0x3B2; int font = 3; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 2, ","); if (keywordargs.Length > 1) { try { hue = int.Parse(keywordargs[1]); } catch { status_str = "invalid hue arg to SENDMSG"; } } } if (arglist.Length > 1) { if (arglist[1] != null && arglist[1].Length > 0 && arglist[1][0] == '@') { arglist = ParseSlashArgs(substitutedtypeName, 2); msgText = arglist[1].Substring(1); } else msgText = arglist[1]; } else { status_str = "invalid SENDMSG specification"; return false; } if (triggermob != null && !triggermob.Deleted && (triggermob is PlayerMobile)) { //triggermob.SendMessage(msgText); triggermob.Send(new UnicodeMessage(Serial.MinusOne, -1, MessageType.Regular, hue, font, "ENU", "System", msgText)); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SENDASCIIMSG: { // the syntax is SENDASCIIMSG[,hue][,font#]/string string[] arglist = ParseSlashArgs(substitutedtypeName, 3); // check for literal string msgText; int hue = 0x3B2; int font = 3; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length > 1) { try { hue = int.Parse(keywordargs[1]); } catch { status_str = "invalid hue arg to SENDASCIIMSG"; } } if (keywordargs.Length > 2) { try { font = int.Parse(keywordargs[2]); } catch { status_str = "invalid font arg to SENDASCIIMSG"; } } } if (arglist.Length > 1) { if (arglist[1] != null && arglist[1].Length > 0 && arglist[1][0] == '@') { arglist = ParseSlashArgs(substitutedtypeName, 2); msgText = arglist[1].Substring(1); } else msgText = arglist[1]; } else { status_str = "invalid SENDASCIIMSG specification"; return false; } if (triggermob != null && !triggermob.Deleted && (triggermob is PlayerMobile)) { triggermob.Send(new AsciiMessage(Serial.MinusOne, -1, MessageType.Regular, hue, font, "System", msgText)); } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.WAITUNTIL: { // the syntax is WAITUNTIL[,delay][,timeout][/condition][/thendogroup] string[] arglist = ParseSlashArgs(substitutedtypeName, 4); double delay = 0; double timeout = 0; string condition = null; int gotogroup = -1; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length > 1) { try { delay = double.Parse(keywordargs[1]); } catch { status_str = "invalid delay arg to WAITUNTIL"; } } if (keywordargs.Length > 2) { try { timeout = double.Parse(keywordargs[2]); } catch { status_str = "invalid timeout arg to WAITUNTIL"; } } } if (arglist.Length > 1) { condition = arglist[1]; } if (arglist.Length > 2) { try { gotogroup = int.Parse(arglist[2]); } catch { status_str = "invalid goto arg to WAITUNTIL"; } } if (status_str != null) { return false; } // suppress sequential advancement //spawner.HoldSequence = true; TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner, TimeSpan.FromMinutes(delay), TimeSpan.FromMinutes(timeout), condition, gotogroup)); break; } case typeKeyword.WHILE: { // the syntax is WHILE/condition/dogroup string[] arglist = ParseSlashArgs(substitutedtypeName, 4); string condition = null; int gotogroup = -1; if (arglist.Length < 3) { status_str = "insufficient args to WHILE"; } else { condition = arglist[1]; try { gotogroup = int.Parse(arglist[2]); } catch { status_str = "invalid dogroup arg to WHILE"; } } if (status_str != null) { return false; } // test the condition if (TestItemProperty(spawner, spawner, condition, triggermob, out status_str)) { // try to spawn the dogroup if (spawner != null && !spawner.Deleted) { if (gotogroup >= 0) { // spawn the subgroup spawner.SpawnSubGroup(gotogroup); // advance the sequence to that group //spawner.SequentialSpawn = gotogroup; } // and suppress sequential advancement spawner.HoldSequence = true; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.IF: { // the syntax is IF/condition/thengroup [/elsegroup] string[] arglist = ParseSlashArgs(substitutedtypeName, 5); string condition = null; int thengroup = -1; int elsegroup = -1; if (arglist.Length < 3) { status_str = "insufficient args to IF"; } else { condition = arglist[1]; try { thengroup = int.Parse(arglist[2]); } catch { status_str = "invalid thengroup arg to IF"; } } if (arglist.Length > 3) { try { elsegroup = int.Parse(arglist[3]); } catch { status_str = "invalid elsegroup arg to IF"; } } if (status_str != null) { return false; } // test the condition if (TestItemProperty(spawner, spawner, condition, triggermob, out status_str)) { // try to spawn the thengroup if (thengroup >= 0 && spawner != null && !spawner.Deleted) { // spawn the subgroup spawner.SpawnSubGroup(thengroup); // advance the sequence to that group //spawner.SequentialSpawn = thengroup; } // and suppress sequential advancement //spawner.HoldSequence = true; } else { // try to spawn the elsegroup if (elsegroup >= 0 && spawner != null && !spawner.Deleted) { // spawn the subgroup spawner.SpawnSubGroup(elsegroup); // advance the sequence to that group //spawner.SequentialSpawn = elsegroup; } // and suppress sequential advancement //spawner.HoldSequence = true; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.DESPAWN: { // the syntax is DESPAWN[,spawnername],subgroup // first find the spawner and group int subgroup = -1; string[] arglist = ParseSlashArgs(substitutedtypeName, 3); XmlSpawner targetspawner = spawner; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length < 2) { status_str = "missing subgroup in DESPAWN"; return false; } else { string subgroupstr = keywordargs[1]; string spawnerstr = null; if (keywordargs.Length > 2) { spawnerstr = keywordargs[1]; subgroupstr = keywordargs[2]; } if (spawnerstr != null) { targetspawner = FindSpawnerByName(spawner, spawnerstr); } try { subgroup = int.Parse(subgroupstr); } catch { } } } if (subgroup == -1) { status_str = "invalid subgroup in DESPAWN"; return false; } if (targetspawner != null) { targetspawner.ClearSubgroup(subgroup); } else { status_str = "invalid spawner in DESPAWN"; return false; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SPAWN: { // the syntax is SPAWN[,spawnername],subgroup // first find the spawner and group int subgroup = -1; string[] arglist = ParseSlashArgs(substitutedtypeName, 3); XmlSpawner targetspawner = spawner; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length < 2) { status_str = "missing subgroup in SPAWN"; return false; } else { string subgroupstr = keywordargs[1]; string spawnerstr = null; if (keywordargs.Length > 2) { spawnerstr = keywordargs[1]; subgroupstr = keywordargs[2]; } if (spawnerstr != null) { targetspawner = FindSpawnerByName(spawner, spawnerstr); } try { subgroup = int.Parse(subgroupstr); } catch { } } } if (subgroup == -1) { status_str = "invalid subgroup in SPAWN"; return false; } if (targetspawner != null) { if (spawner != targetspawner) { // allow spawning of other spawners to be forced and ignore the normal loop protection targetspawner.SpawnSubGroup(subgroup, false, true); } else { targetspawner.SpawnSubGroup(subgroup); } } else { status_str = "invalid spawner in SPAWN"; return false; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.GOTO: { // the syntax is GOTO/subgroup string[] arglist = ParseSlashArgs(substitutedtypeName, 3); int group = -1; if (arglist.Length < 2) { status_str = "insufficient args to GOTO"; } else { try { group = int.Parse(arglist[1]); } catch { status_str = "invalid subgroup arg to GOTO"; } } if (status_str != null) { return false; } // move the sequence to the specified subgroup if (group >= 0 && spawner != null && !spawner.Deleted) { // note, this will activate sequential spawning if it wasnt already set spawner.SequentialSpawn = group; // and suppress sequential advancement so that the specified group is the next to spawn spawner.HoldSequence = true; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner, 2)); break; } case typeKeyword.COMMAND: { // the syntax is COMMAND/commandstring string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { // mod to use a dummy char to issue commands if (CommandMobileName != null) { Mobile dummy = FindMobileByName(spawner, CommandMobileName, "Mobile"); if (dummy != null) { CommandSystem.Handle(dummy, String.Format("{0}{1}", CommandSystem.Prefix, arglist[1])); } } else if (triggermob != null && !triggermob.Deleted) { CommandSystem.Handle(triggermob, String.Format("{0}{1}", CommandSystem.Prefix, arglist[1])); } } else { status_str = "insufficient args to COMMAND"; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.MUSIC: { // the syntax is MUSIC,name,range string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { SendMusicToPlayers(arglist[0], triggermob, invoker, out status_str); if (status_str != null) { return false; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.SOUND: { string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { // Syntax is SOUND,soundnumber string[] keywordargs = ParseString(arglist[0], 3, ","); int sound = -1; // try to get the soundnumber argument if (keywordargs.Length < 2) { status_str = "Missing sound number"; } else { try { sound = int.Parse(keywordargs[1]); } catch { status_str = "Improper sound number format"; } } if (sound >= 0 && spawner != null && !spawner.Deleted) { Effects.PlaySound(spawner.Location, spawner.Map, sound); } if (status_str != null) { return false; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } // // MEFFECT keyword // case typeKeyword.MEFFECT: { string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 9, ","); if (keywordargs.Length < 9) { status_str = "Missing args"; } else { int effect = -1; int duration = 0; int speed = 1; Point3D eloc1 = new Point3D(0, 0, 0); Point3D eloc2 = new Point3D(0, 0, 0); Map emap = Map.Internal; // syntax is MEFFECT,itemid,speed,x,y,z,x2,y2,z2 // try to get the effect argument try { effect = int.Parse(keywordargs[1]); } catch { status_str = "Improper effect number format"; } try { speed = int.Parse(keywordargs[2]); } catch { status_str = "Improper effect speed format"; } int x = 0; int y = 0; int z = 0; try { x = int.Parse(keywordargs[3]); y = int.Parse(keywordargs[4]); z = int.Parse(keywordargs[5]); } catch { status_str = "Improper effect location format"; } eloc1 = new Point3D(x, y, z); try { x = int.Parse(keywordargs[6]); y = int.Parse(keywordargs[7]); z = int.Parse(keywordargs[8]); } catch { status_str = "Improper effect location format"; } eloc2 = new Point3D(x, y, z); if (effect >= 0 && emap != Map.Internal) { Effects.SendPacket(eloc1, emap, new HuedEffect(EffectType.Moving, -1, -1, effect, eloc1, eloc2, speed, duration, false, false, 0, 0)); } } if (status_str != null) { return false; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.EFFECT: { string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (spawner == null || spawner.Deleted) return false; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 6, ","); int effect = -1; int duration = 1; // syntax is EFFECT,itemid,duration[,x,y,z] or EFFECT,itemid,duration[,trigmob] // try to get the effect argument // some interesting effects are explosion(14013,15), sparkle(14155,15), explosion2(14000,13) if (keywordargs.Length < 3) { status_str = "Missing effect number and duration"; } else { try { effect = int.Parse(keywordargs[1]); } catch { status_str = "Improper effect number format"; } try { duration = int.Parse(keywordargs[2]); } catch { status_str = "Improper effect duration format"; } } // by default just use the spawner location Point3D eloc = spawner.Location; Map emap = spawner.Map; if (keywordargs.Length > 3) { // is this applied to the trig mob or to a location? if (keywordargs.Length > 5) { int x = spawner.Location.X; int y = spawner.Location.Y; int z = spawner.Location.Z; try { x = int.Parse(keywordargs[3]); y = int.Parse(keywordargs[4]); z = int.Parse(keywordargs[5]); } catch { status_str = "Improper effect location format"; } eloc = new Point3D(x, y, z); } } if (status_str != null) { return false; } if (effect >= 0) { Effects.SendLocationEffect(eloc, emap, effect, duration); } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.POISON: { // the syntax is POISON,name,range string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { ApplyPoisonToPlayers(arglist[0], triggermob, invoker, out status_str); if (status_str != null) { return false; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.DAMAGE: { // the syntax is DAMAGE,damage,phys,fire,cold,pois,energy[,range] string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { ApplyDamageToPlayers(arglist[0], triggermob, invoker, out status_str); if (status_str != null) { return false; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.RESURRECT: { // the syntax is RESURRECT[,range][,PETS] string[] arglist = ParseSlashArgs(substitutedtypeName, 3); if (arglist.Length > 0) { ResurrectPlayers(arglist[0], triggermob, invoker, out status_str); if (status_str != null) { return false; } } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } case typeKeyword.CAST: { string[] arglist = ParseSlashArgs(substitutedtypeName, 3); // Syntax is CAST,spellnumber[,arg] or CAST,spellname[,arg] string[] keywordargs = ParseString(arglist[0], 3, ","); int spellnumber = 0; bool hasnumber = true; // try it as spellnumber if (keywordargs.Length > 1) { try { spellnumber = int.Parse(keywordargs[1]); } catch { hasnumber = false; } } else { status_str = "invalid CAST specification"; // note that returning true means that Spawn will assume that it worked and will not try to recast return true; } // call this with the 3 argument version that includes the bodytype arg int keywordarg2 = 0; if (keywordargs.Length > 2) { try { keywordarg2 = int.Parse(keywordargs[2]); } catch { } } Spell spell = null; // the trigger mob will cast the spells Mobile caster = triggermob; if (caster == null) { // note that returning true means that Spawn will assume that it worked and will not try to recast return true; } // make the placeholder wand to avoid reagent and mana use // this has been removed because Divinity doesn't have ClumsyWand //BaseWand cwand = new ClumsyWand(); //cwand.Parent = caster; BaseWand cwand = null; spell = null; /*if (hasnumber) { spell = SpellRegistry.NewSpell(spellnumber, caster, cwand); } else { spell = SpellRegistry.NewSpell(keywordargs[1], caster, cwand); }*/ if (spell != null) { bool casterror = false; try { // deal with the 3 types of spells, mob targeted, location targeted, and self targeted // dont go through all of the warm up stuff, get right to the casting spell.State = SpellState.Sequencing; Type spelltype = spell.GetType(); // deal with any special cases here if (spelltype == typeof(Server.Spells.Seventh.PolymorphSpell)) { if (keywordarg2 == 0) { // this is invalid so dont cast throw (new ArgumentNullException()); } object[] polyargs = new object[3]; polyargs[0] = caster; polyargs[1] = cwand; polyargs[2] = keywordarg2; spell = (Spell)Activator.CreateInstance(spelltype, polyargs); if (spell == null) { throw (new ArgumentNullException()); } spell.State = SpellState.Sequencing; } MethodInfo spelltargetmethod = null; // get the targeting method from the spell // note, the precedence is important as the target call should override oncast if it is present if (spelltype != null && (spelltargetmethod = spelltype.GetMethod("Target")) != null) { } // if it doesnt have it then check for self targeted types else if (spelltype != null && (spelltargetmethod = spelltype.GetMethod("OnCast")) != null) { } else { throw (new ArgumentNullException()); } // Get the parameters for the target method. ParameterInfo[] spelltargetparms = spelltargetmethod.GetParameters(); // target will have one parm // selftarg will have none object[] targetargs = null; // check the parameters if (spelltargetparms != null && spelltargetparms.Length > 0) { if (spelltargetparms[0].ParameterType == typeof(Server.Mobile)) { // set the target parameter targetargs = new object[1]; targetargs[0] = triggermob; } else if (spelltargetparms[0].ParameterType == typeof(Server.IPoint3D)) { // set the target parameter targetargs = new object[1]; // pick a random point around the caster int range = keywordarg2; if (range == 0) range = 1; int randx = Utility.RandomMinMax(-range, range); int randy = Utility.RandomMinMax(-range, range); if (randx == 0 && randy == 0) randx = 1; targetargs[0] = new Point3D(triggermob.Location.X + randx, triggermob.Location.Y + randy, triggermob.Location.Z); } else { // dont handle any other types of args throw (new ArgumentNullException()); } } // set the spell on the caster caster.Spell = spell; // invoke the spell method with the appropriate args spelltargetmethod.Invoke(spell, targetargs); // get rid of the placeholder wand if (cwand != null && !cwand.Deleted) cwand.Delete(); } catch { status_str = "bad spell call : " + spell.Name; casterror = true; // get rid of the placeholder wand if (cwand != null && !cwand.Deleted) cwand.Delete(); } if (casterror) return true; } else { status_str = "spell invalid or disabled : " + keywordargs[1]; //return true; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); // note that returning true means that Spawn assume that it worked and will not try to recast break; } case typeKeyword.BCAST: { // syntax is BCAST[,hue][,font]/message string[] arglist = ParseSlashArgs(substitutedtypeName, 3); int hue = 0x482; int font = -1; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 3, ","); if (keywordargs.Length > 1) { try { hue = int.Parse(keywordargs[1]); } catch { status_str = "invalid hue arg to BCAST"; } } if (keywordargs.Length > 2) { try { font = int.Parse(keywordargs[2]); } catch { status_str = "invalid font arg to BCAST"; } } } if (arglist.Length > 1) { string msg = arglist[1]; if (arglist[1] != null && arglist[1].Length > 0 && arglist[1][0] == '@') { arglist = ParseSlashArgs(substitutedtypeName, 2); msg = arglist[1].Substring(1); } if (font >= 0) { // broadcast an ascii message to all players BroadcastAsciiMessage(AccessLevel.Player, hue, font, msg); } else { // standard unicode message format CommandHandlers.BroadcastMessage(AccessLevel.Player, hue, msg); } } else { status_str = "missing msg arg in BCAST"; return false; } TheSpawn.SpawnedObjects.Add(new KeywordTag(substitutedtypeName, spawner)); break; } default: { status_str = "unrecognized keyword"; // should never get here break; } } // indicate successful keyword spawn return true; } else if (IsSpecialItemKeyword(typeName)) { // these are special keyword item drops string[] arglist = ParseSlashArgs(substitutedtypeName, 2); string itemtypestr = arglist[0]; string baseitemtype = typeName; // itemtypestr will have the form keyword[,x[,y]] string[] itemkeywordargs = ParseString(itemtypestr, 3, ","); // deal with the special keywords itemKeyword kw = (itemKeyword)itemKeywordHash[baseitemtype]; switch (kw) { case itemKeyword.ARMOR: { // syntax is ARMOR,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid ARMOR args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid ARMOR args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicArmor(min, max, false, false); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "ARMOR takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.WEAPON: { // syntax is WEAPON,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid WEAPON args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid WEAPON args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicWeapon(min, max, false); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "WEAPON takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.JARMOR: { // syntax is JARMOR,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid JARMOR args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid JARMOR args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicArmor(min, max, true, true); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "JARMOR takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.JWEAPON: { // syntax is JWEAPON,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid JWEAPON args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid JWEAPON args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicWeapon(min, max, true); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "JWEAPON takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.SARMOR: { // syntax is SARMOR,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid SARMOR args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid SARMOR args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicArmor(min, max, false, true); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "SARMOR takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.SHIELD: { // syntax is SHIELD,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid SHIELD args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid SHIELD args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicShield(min, max); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "SHIELD takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.JEWELRY: { // syntax is JEWELRY,min,max //get the min,max if (itemkeywordargs.Length == 3) { int min = 0; int max = 0; bool converterror = false; try { min = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid JEWELRY args : " + itemtypestr; converterror = true; } try { max = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid JEWELRY args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = MagicJewelry(min, max); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "JEWELRY takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.SCROLL: { // syntax is SCROLL,mincircle,maxcircle //get the min,max if (itemkeywordargs.Length == 3) { int minCircle = 0; int maxCircle = 0; bool converterror = false; try { minCircle = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid SCROLL args : " + itemtypestr; converterror = true; } try { maxCircle = int.Parse(itemkeywordargs[2]); } catch { status_str = "Invalid SCROLL args : " + itemtypestr; converterror = true; } if (converterror) return false; int circle = Utility.RandomMinMax(minCircle, maxCircle); int min = (circle - 1) * 8; Item item = Loot.RandomScroll(min, min + 7, SpellbookType.Regular); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "SCROLL takes 2 args : " + itemtypestr; return false; } break; } case itemKeyword.LOOT: { // syntax is LOOT,methodname if (itemkeywordargs.Length == 2) { Item item = null; // look up the method Type ltype = typeof(Loot); if (ltype != null) { MethodInfo method = null; try { // get the zero arg method with the specified name method = ltype.GetMethod(itemkeywordargs[1], new Type[0]); } catch { } if (method != null && method.IsStatic) { ParameterInfo[] pinfo = method.GetParameters(); // check to make sure the method for this object has the right args if (pinfo.Length == 0) { // method must be public static with no arguments returning an Item class object try { item = method.Invoke(null, null) as Item; } catch { } } else { status_str = "LOOT method must be zero arg : " + itemtypestr; return false; } } else { status_str = "LOOT no valid method found : " + itemtypestr; return false; } } if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "LOOT takes 1 arg : " + itemtypestr; return false; } break; } case itemKeyword.POTION: { // syntax is POTION Item item = Loot.RandomPotion(); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } break; } case itemKeyword.TAKEN: { // syntax is TAKEN // find the XmlSaveItem attachment Item item = GetTaken(invoker); if (item != null) { AddSpawnItem(spawner, invoker, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } break; } case itemKeyword.GIVEN: { // syntax is GIVEN // find the XmlSaveItem attachment Item item = GetGiven(invoker); if (item != null) { AddSpawnItem(spawner, invoker, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } break; } case itemKeyword.NECROSCROLL: { // syntax is NECROSCROLL,index if (itemkeywordargs.Length == 2) { int necroindex = 0; bool converterror = false; try { necroindex = int.Parse(itemkeywordargs[1]); } catch { status_str = "Invalid NECROSCROLL args : " + itemtypestr; converterror = true; } if (converterror) return false; if (Core.AOS) { Item item = Loot.Construct(Loot.NecromancyScrollTypes, necroindex); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } } else { status_str = "NECROSCROLL takes 1 arg : " + itemtypestr; return false; } break; } case itemKeyword.MULTIADDON: { // syntax is MULTIADDON,filename if (itemkeywordargs.Length == 2) { string filename = itemkeywordargs[1]; // read in the multi.txt file Item item = XmlSpawnerAddon.ReadMultiFile(filename, out status_str); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "MULTIADDON takes 1 arg : " + itemtypestr; return false; } break; } default: { status_str = "unrecognized keyword"; // should never get here break; } } return true; } else { // should never get here status_str = "unrecognized keyword"; return false; } }
public XmlSimpleGump(object invoker, string gumptext, string gumptitle, int gumptype, BaseXmlSpawner.KeywordTag tag, Mobile from, XmlGumpCallback gumpcallback) : base(0, 0) { string maintext = gumptext; int nselections = 0; int height = 400; int width = 369; Closable = false; Dragable = true; m_gumptype = gumptype; m_invoker = invoker; m_keywordtag = tag; m_gumpcallback = gumpcallback; AddPage(0); // for the multiple selection gump, parse the gumptext for selections and responses if (gumptype == 4) { maintext = ParseGumpText(gumptext); nselections = gumpSelections.Count; height = height + nselections * 40; } if (gumptype == 5) { maintext = ParseGumpText(gumptext); nselections = gumpSelections.Count; // the maintext in this case is a width,height specifier so parse it string [] args = maintext.Split(','); if (args != null && args.Length > 1) { int.TryParse(args[0].Trim(), out width); int.TryParse(args[1].Trim(), out height); } } AddImageTiled(54, 33, width, height, 2624); AddAlphaRegion(54, 33, width, height); AddImageTiled(width + 47, 39, 44, height - 11, 203); AddImageTiled(58, 39, 29, height - 10, 10460); // left hand border AddImageTiled(width + 43, 37, 31, height - 11, 10460); // right hand border AddImageTiled(40, 38, 17, height - 9, 9263); // leftmost border //AddImageTiled( 94, 25, width - 27, 15, 10304 ); // top border AddImageTiled(40, 25, width + 48, 15, 10304); // top border AddImageTiled(40, height + 27, width + 46, 16, 10304); // bottom border if (gumptype != 5) { AddImage(width + 61, 9, 10441); // dragon borders AddImage(6, 25, 10421); AddImage(34, 12, 10420); AddImage(-10, height - 86, 10402); AddImage(56, 150, 10411); AddImage(136, 84, 96); // divider AddImage(width + 3, 57, 1417); // quest icons AddImage(width + 12, 66, 5576); AddButton(width - 31, height - 8, 2130, 2129, 3, GumpButtonType.Reply, 0); // Okay button } else { AddButton(width + 70, 25, 0x138b, 0x138b, 0, GumpButtonType.Reply, 0); // closegump button } if (gumptitle != null && gumptitle.Length > 0 && gumptype != 5) { // display the title if it is there AddImage(156, 126, 2103); // bullet LocalAddHtml(gumptitle, 174, 121, 200, 40, 0x00FF42, false, false); } if (gumptype == 0) { // simple message gump LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if (gumptype == 1) { // Yes/no type gump AddRadio(101, height - 45, 9721, 9724, true, 1); // accept/yes radio AddRadio(101, height - 11, 9721, 9724, false, 2); // decline/no radio AddHtmlLocalized(137, height - 41, 200, 30, 1049016, 0x7fff, false, false); // Yes AddHtmlLocalized(137, height - 7, 200, 30, 1049017, 0x7fff, false, false); // No LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if (gumptype == 2) { // reply type gump AddImageTiled(134, height - 7, 159, 23, 0x52); AddImageTiled(135, height - 6, 157, 21, 0xBBC); AddHtmlLocalized(105, height - 7, 200, 30, 3002006, 0x7fff, false, false); // Say: AddTextEntry(135, height - 7, 150, 21, 0, 99, null); LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if (gumptype == 3) { // Quest type gump AddImage(97, 49, 9005); // quest ribbon AddRadio(101, height - 45, 9721, 9724, true, 1); // accept/yes radio AddRadio(101, height - 11, 9721, 9724, false, 2); // decline/no radio AddHtmlLocalized(139, 59, 200, 30, 1046013, 0x7fff, false, false); // Quest Offer AddHtmlLocalized(137, height - 41, 200, 30, 1049011, 0x7fff, false, false); // I accept! AddHtmlLocalized(137, height - 7, 200, 30, 1049012, 0x7fff, false, false); // No thanks, I decline. LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if (gumptype == 4) { // multiple selection type gump // parse the gump text to get the selections and responses for (int i = 0; i < gumpSelections.Count; i++) { int y = 360 + i * 40; AddRadio(101, y, 9721, 9724, i == 0 ? true: false, i); // accept/yes radio AddHtml(137, y + 4, 250, 40, XmlSimpleGump.Color(gumpSelections[i].Selection, "FFFFFF"), false, false); } LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if (gumptype == 5) { // parse the gump text to get the selections and responses for (int i = 0; i < gumpSelections.Count; i++) { string selection = gumpSelections[i].Selection; string response = gumpSelections[i].Response; int gx = 0; int gy = 0; int gwidth = 0; int gheight = 0; string label = null; string [] args = null; int gumpid = 0; int color = 0; if (selection != null) { args = selection.Split(','); } // process the gumpitem specifications if (args.Length > 1) { for (int j = 0; j < args.Length; j++) { args[j] = args[j].Trim(); } if (args[0].ToLower() == "button") { // syntax is button,gumpid,x,y if (args.Length > 3) { if (args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); int buttonid = 1000 + i; // add the button AddButton(gx, gy, gumpid, gumpid, buttonid, GumpButtonType.Reply, 0); } } else if (args[0].ToLower() == "label") { // syntax is label,x,y,label[,color] if (args.Length > 3) { int.TryParse(args[1], out gx); int.TryParse(args[2], out gy); label = args[3]; } // set the default label color color = 0x384; if (args.Length > 4) { int.TryParse(args[4], out color); } // add the label AddLabel(gx, gy, color, label); } else if (args[0].ToLower() == "html") { // reparse the specification to allow for the possibility of commas in the html text args = selection.Split(new char[] { ',' }, 6); color = 0xEFEF5A; // syntax is html,x,y,width,height,text[,hue] * hue has to be in HEX format, ex: 0xFF00AA (lenght of 8 mandatory!) if (args.Length > 5) { int.TryParse(args[1].Trim(), out gx); int.TryParse(args[2].Trim(), out gy); int.TryParse(args[3].Trim(), out gwidth); int.TryParse(args[4].Trim(), out gheight); if (args.Length > 6 && args[5].StartsWith("0x") && args[5].Trim().Length == 8) { if (!int.TryParse(args[5].Trim().Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out color)) { color = 0xEFEF5A; } label = args[6]; } else { label = args[5]; } } // add the html area //AddHtml( gx, gy, gwidth, gheight, label, false, true ); LocalAddHtml(label, gx, gy, gwidth, gheight, color, false, true); } else if (args[0].ToLower() == "textentry") { gumpSelections[i].GumpItemType = 1; // syntax is textentry,x,y,width,height[,textcolor][,text] if (args.Length > 4) { int.TryParse(args[1].Trim(), out gx); int.TryParse(args[2].Trim(), out gy); int.TryParse(args[3].Trim(), out gwidth); int.TryParse(args[4].Trim(), out gheight); } if (args.Length > 5) { label = args[5]; } // set the default textentry color color = 0x384; if (args.Length > 6) { int.TryParse(args[6], out color); } AddTextEntry(gx, gy, gwidth, gheight, color, i, label); } else if (args[0].ToLower() == "radio") { int gumpid1 = 0; int gumpid2 = 0; // syntax is radio,gumpid1,gumpid2,x,y[,initialstate] if (args.Length > 4) { int.TryParse(args[1].Trim(), out gumpid1); int.TryParse(args[2].Trim(), out gumpid2); int.TryParse(args[3].Trim(), out gx); int.TryParse(args[4].Trim(), out gy); } bool initial = false; if (args.Length > 5) { bool.TryParse(args[5], out initial); } AddRadio(gx, gy, gumpid1, gumpid2, initial, i); } else if (args[0].ToLower() == "image") { // syntax is image,gumpid,x,y[,hue] if (args.Length > 3) { if (args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); if (args.Length > 4) { int.TryParse(args[4], out color); } // add the image AddImage(gx, gy, gumpid, color); } } else if (args[0].ToLower() == "imagetiled") { // syntax is imagetiled,gumpid,x,y,width,height if (args.Length > 5) { if (args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); int.TryParse(args[4], out gwidth); int.TryParse(args[5], out gheight); // add the image AddImageTiled(gx, gy, gwidth, gheight, gumpid); } } else if (args[0].ToLower() == "item") { // syntax is item,itemid,x,y[,hue] if (args.Length > 3) { if (args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); if (args.Length > 4) { int.TryParse(args[4], out color); } // add the image AddItem(gx, gy, gumpid, color); } } } } } }
public static bool SpawnTypeKeyword(object invoker, XmlSpawner.SpawnObject TheSpawn, string typeName, string substitutedtypeName, bool requiresurface, Mobile triggermob, Point3D location, Map map, XmlGumpCallback gumpcallback, out string status_str) { return SpawnTypeKeyword(invoker, TheSpawn, typeName, substitutedtypeName, requiresurface, null, triggermob, location, map, gumpcallback, out status_str); }
public XmlSimpleGump( object invoker, string gumptext, string gumptitle, int gumptype, BaseXmlSpawner.KeywordTag tag, Mobile from, XmlGumpCallback gumpcallback) : base( 0, 0 ) { string maintext = gumptext; int nselections = 0; int height = 400; int width = 369; Closable = false; Dragable = true; m_gumptype = gumptype; m_invoker = invoker; m_keywordtag = tag; m_gumpcallback = gumpcallback; AddPage( 0 ); // for the multiple selection gump, parse the gumptext for selections and responses if(gumptype == 4) { maintext = ParseGumpText(gumptext); nselections = gumpSelections.Count; height = height + nselections*40; } if(gumptype == 5) { maintext = ParseGumpText(gumptext); nselections = gumpSelections.Count; // the maintext in this case is a width,height specifier so parse it string [] args = maintext.Split(','); if(args != null && args.Length>1) { int.TryParse(args[0].Trim(), out width); int.TryParse(args[1].Trim(), out height); } } AddImageTiled( 54, 33, width, height, 2624 ); AddAlphaRegion( 54, 33, width, height ); AddImageTiled( width + 47, 39, 44, height-11, 203 ); AddImageTiled( 58, 39, 29, height - 10, 10460 ); // left hand border AddImageTiled( width + 43, 37, 31, height - 11, 10460 ); // right hand border AddImageTiled( 40, 38, 17, height - 9, 9263 ); // leftmost border //AddImageTiled( 94, 25, width - 27, 15, 10304 ); // top border AddImageTiled( 40, 25, width + 48, 15, 10304 ); // top border AddImageTiled( 40, height + 27, width + 46, 16, 10304 ); // bottom border if(gumptype != 5) { AddImage( width + 61, 9, 10441); // dragon borders AddImage( 6, 25, 10421 ); AddImage( 34, 12, 10420 ); AddImage( -10, height - 86, 10402 ); AddImage( 56, 150, 10411 ); AddImage( 136, 84, 96 ); // divider AddImage( width + 3, 57, 1417); // quest icons AddImage( width + 12, 66, 5576); AddButton( width - 31, height - 8, 2130, 2129, 3, GumpButtonType.Reply, 0 ); // Okay button } else { AddButton( width + 70, 25, 0x138b, 0x138b, 0, GumpButtonType.Reply, 0 ); // closegump button } if(gumptitle != null && gumptitle.Length > 0 && gumptype != 5) { // display the title if it is there AddImage( 156, 126, 2103 ); // bullet LocalAddHtml(gumptitle, 174, 121, 200, 40, 0x00FF42, false, false); } if(gumptype == 0) { // simple message gump LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if(gumptype == 1) { // Yes/no type gump AddRadio( 101, height - 45, 9721, 9724, true, 1 ); // accept/yes radio AddRadio( 101, height - 11, 9721, 9724, false, 2 ); // decline/no radio AddHtmlLocalized(137, height - 41, 200, 30, 1049016, 0x7fff , false , false ); // Yes AddHtmlLocalized(137, height - 7, 200, 30, 1049017, 0x7fff , false , false ); // No LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if(gumptype == 2) { // reply type gump AddImageTiled( 134, height - 7, 159, 23, 0x52 ); AddImageTiled( 135, height - 6, 157, 21, 0xBBC ); AddHtmlLocalized(105, height - 7, 200, 30, 3002006, 0x7fff , false , false ); // Say: AddTextEntry( 135, height - 7, 150, 21, 0, 99, (string)null ); LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if(gumptype == 3) { // Quest type gump AddImage( 97, 49, 9005 ); // quest ribbon AddRadio( 101, height - 45, 9721, 9724, true, 1 ); // accept/yes radio AddRadio( 101, height - 11, 9721, 9724, false, 2 ); // decline/no radio AddHtmlLocalized( 139, 59, 200, 30, 1046013, 0x7fff, false , false ); // Quest Offer AddHtmlLocalized(137, height - 41, 200, 30, 1049011, 0x7fff , false , false ); // I accept! AddHtmlLocalized(137, height - 7, 200, 30, 1049012, 0x7fff , false , false ); // No thanks, I decline. LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if(gumptype == 4) { // multiple selection type gump // parse the gump text to get the selections and responses for(int i=0;i < gumpSelections.Count; i++) { int y = 360 + i*40; AddRadio( 101, y, 9721, 9724, i==0 ? true: false, i ); // accept/yes radio AddHtml( 137, y+4, 250, 40, XmlSimpleGump.Color( gumpSelections[i].Selection, "FFFFFF" ), false, false ); } LocalAddHtml(maintext, 105, 159, 299, 182, 0xEFEF5A, false, true); } else if(gumptype == 5) { // parse the gump text to get the selections and responses for(int i=0;i < gumpSelections.Count; i++) { string selection = gumpSelections[i].Selection; string response = gumpSelections[i].Response; int gx = 0; int gy = 0; int gwidth = 0; int gheight = 0; string label = null; string [] args = null; int gumpid = 0; int color = 0; if(selection != null) { args = selection.Split(','); } // process the gumpitem specifications if(args.Length > 1) { for(int j=0;j<args.Length;j++) { args[j] = args[j].Trim(); } if(args[0].ToLower() == "button") { // syntax is button,gumpid,x,y if(args.Length > 3) { if(args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); int buttonid = 1000 + i; // add the button AddButton( gx, gy, gumpid, gumpid, buttonid, GumpButtonType.Reply, 0 ); } } else if(args[0].ToLower() == "label") { // syntax is label,x,y,label[,color] if(args.Length > 3) { int.TryParse(args[1], out gx); int.TryParse(args[2], out gy); label = args[3]; } // set the default label color color = 0x384; if(args.Length > 4) { int.TryParse(args[4], out color); } // add the label AddLabel( gx, gy, color, label ); } else if(args[0].ToLower() == "html") { // reparse the specification to allow for the possibility of commas in the html text args = selection.Split(new char[] {','},6); color = 0xEFEF5A; // syntax is html,x,y,width,height,text[,hue] * hue has to be in HEX format, ex: 0xFF00AA (lenght of 8 mandatory!) if(args.Length > 5) { int.TryParse(args[1].Trim(), out gx); int.TryParse(args[2].Trim(), out gy); int.TryParse(args[3].Trim(), out gwidth); int.TryParse(args[4].Trim(), out gheight); if(args.Length>6 && args[5].StartsWith("0x") && args[5].Trim().Length==8) { if(!int.TryParse(args[5].Trim().Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out color)) color=0xEFEF5A; label = args[6]; } else label = args[5]; } // add the html area //AddHtml( gx, gy, gwidth, gheight, label, false, true ); LocalAddHtml(label, gx, gy, gwidth, gheight, color, false, true); } else if(args[0].ToLower() == "textentry") { gumpSelections[i].GumpItemType = 1; // syntax is textentry,x,y,width,height[,textcolor][,text] if(args.Length > 4) { int.TryParse(args[1].Trim(), out gx); int.TryParse(args[2].Trim(), out gy); int.TryParse(args[3].Trim(), out gwidth); int.TryParse(args[4].Trim(), out gheight); } if(args.Length > 5) { label = args[5]; } // set the default textentry color color = 0x384; if(args.Length > 6) { int.TryParse(args[6], out color); } AddTextEntry( gx, gy, gwidth, gheight, color, i, label ); } else if(args[0].ToLower() == "radio") { int gumpid1 = 0; int gumpid2 = 0; // syntax is radio,gumpid1,gumpid2,x,y[,initialstate] if(args.Length > 4) { int.TryParse(args[1].Trim(), out gumpid1); int.TryParse(args[2].Trim(), out gumpid2); int.TryParse(args[3].Trim(), out gx); int.TryParse(args[4].Trim(), out gy); } bool initial = false; if(args.Length > 5) { bool.TryParse(args[5], out initial); } AddRadio( gx, gy, gumpid1, gumpid2, initial, i); } else if(args[0].ToLower() == "image") { // syntax is image,gumpid,x,y[,hue] if(args.Length > 3) { if(args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); if(args.Length > 4) { int.TryParse(args[4], out color); } // add the image AddImage( gx, gy, gumpid, color ); } } else if(args[0].ToLower() == "imagetiled") { // syntax is imagetiled,gumpid,x,y,width,height if(args.Length > 5) { if(args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); int.TryParse(args[4], out gwidth); int.TryParse(args[5], out gheight); // add the image AddImageTiled( gx, gy, gwidth, gheight, gumpid ); } } else if(args[0].ToLower() == "item") { // syntax is item,itemid,x,y[,hue] if(args.Length > 3) { if(args[1].StartsWith("0x")) { int.TryParse(args[1].Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out gumpid); } else { int.TryParse(args[1], out gumpid); } int.TryParse(args[2], out gx); int.TryParse(args[3], out gy); if(args.Length > 4) { int.TryParse(args[4], out color); } // add the image AddItem( gx, gy, gumpid, color ); } } } } } }