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 && invoker is IEntity) { Effects.PlaySound(((IEntity)invoker).Location, ((IEntity)invoker).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 BaseWand cwand = new ClumsyWand(); cwand.Parent = caster; 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; } case typeKeyword.BSOUND: { // syntax is BSOUND,soundid string[] arglist = ParseSlashArgs(substitutedtypeName, 3); int soundid = -1; if (arglist.Length > 0) { string[] keywordargs = ParseString(arglist[0], 2, ","); if (keywordargs.Length > 1) { try { soundid = int.Parse(keywordargs[1]); } catch { status_str = "invalid soundid arg to BSOUND"; } } if (soundid >= 0) { // broadcast a sound to all players BroadcastSound(AccessLevel.Player, soundid); } } 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.ITEM: { // syntax is ITEM,serial if (itemkeywordargs.Length == 2) { int serial = -1; bool converterror = false; try { serial = Convert.ToInt32(itemkeywordargs[1], 16); } catch { status_str = "Invalid ITEM args : " + itemtypestr; converterror = true; } if (converterror) return false; Item item = World.FindItem(serial); if (item != null) { AddSpawnItem(spawner, TheSpawn, item, location, map, triggermob, requiresurface, spawnpositioning, substitutedtypeName, out status_str); } } else { status_str = "ITEM takes 1 arg : " + 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 override void OnResponse( NetState sender, RelayInfo info ) { Container pack = sender.Mobile.Backpack; if ( pack == null ) { sender.Mobile.SendMessage( 1192, "You need a backpack." ); return; } int items = 0; BaseCustomWand wand = null; BaseWand magewand = null; switch( (Buttons)info.ButtonID ) { case Buttons.MainMenu: { if ( sender.Mobile.HasGump( typeof( SpellBindingGump ) ) ) sender.Mobile.CloseGump( typeof( SpellBindingGump ) ); sender.Mobile.SendGump( new SpellBindingGump() ); break; } case Buttons.Magery: { if ( sender.Mobile.HasGump( typeof( SpellBindingGump ) ) ) sender.Mobile.CloseGump( typeof( SpellBindingGump ) ); sender.Mobile.SendGump( new SpellBindingGump( Buttons.Magery ) ); break; } case Buttons.Necromancy: { if ( sender.Mobile.HasGump( typeof( SpellBindingGump ) ) ) sender.Mobile.CloseGump( typeof( SpellBindingGump ) ); sender.Mobile.SendGump( new SpellBindingGump( Buttons.Necromancy ) ); break; } case Buttons.Chivalry: { if ( sender.Mobile.HasGump( typeof( SpellBindingGump ) ) ) sender.Mobile.CloseGump( typeof( SpellBindingGump ) ); sender.Mobile.SendGump( new SpellBindingGump( Buttons.Chivalry ) ); break; } case Buttons.Golems: { if ( sender.Mobile.HasGump( typeof( SpellBindingGump ) ) ) sender.Mobile.CloseGump( typeof( SpellBindingGump ) ); sender.Mobile.SendGump( new SpellBindingGump( Buttons.Golems ) ); break; } #region Magery case Buttons.Clumsy: { items = pack.ConsumeTotal( new Type[] { typeof( Bloodmoss ), typeof( Nightshade ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new ClumsyWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.Feeble: { items = pack.ConsumeTotal( new Type[] { typeof( Ginseng ), typeof( Nightshade ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new FeebleWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.Fireball: { items = pack.ConsumeTotal( new Type[] { typeof( BlackPearl ), typeof( ArcaneGem ) }, new int[]{ 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new FireballWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.GreaterHeal: { items = pack.ConsumeTotal( new Type[] { typeof( Garlic ), typeof( Ginseng ), typeof( MandrakeRoot ), typeof( SpidersSilk ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new GreaterHealWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.Harm: { items = pack.ConsumeTotal( new Type[] { typeof( Nightshade ), typeof( SpidersSilk ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new HarmWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.Identification: { sender.Mobile.SendMessage( 1192, "The Spell Binders of Tolaria have not concentrated on this area of work yet." ); goto case Buttons.Magery; } case Buttons.Lightning: { items = pack.ConsumeTotal( new Type[] { typeof( MandrakeRoot ), typeof( SulfurousAsh ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new LightningWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.MagicArrow: { items = pack.ConsumeTotal( new Type[] { typeof( SulfurousAsh ), typeof( ArcaneGem ) }, new int[]{ 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand= new MagicArrowWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.ManaDrain: { items = pack.ConsumeTotal( new Type[] { typeof( BlackPearl ), typeof( MandrakeRoot ), typeof( SpidersSilk ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new ManaDrainWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.Weakness: { items = pack.ConsumeTotal( new Type[] { typeof( Garlic ), typeof( Nightshade ), typeof( ArcaneGem ) }, new int[]{ 50, 50, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || items != -1 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & 100 mana.<br>" + "Items: An Arcane Gem." + "Regents: 50 of the regents the spell requires." ); goto case Buttons.Magery; } magewand = new WeaknessWand(); magewand.Crafter = sender.Mobile; pack.DropItem( magewand ); goto case Buttons.Magery; } case Buttons.MarkRune: { sender.Mobile.SendMessage( 1192, "The Spell Binders of Tolaria have not concentrated on this area of work yet." ); goto case Buttons.Magery; } case Buttons.ArcaneGem: { items = pack.ConsumeTotal( new Type[] { typeof( BlackPearl ), typeof( Bloodmoss ), typeof( Garlic ), typeof( Ginseng ), typeof( MandrakeRoot ), typeof( Nightshade ), typeof( SpidersSilk ), typeof( SulfurousAsh ) }, new int[]{ 10, 10, 10, 10, 10, 10, 10, 10 } ); if ( sender.Mobile.Skills[SkillName.ItemID].Base < 100.0 || items != -1 || sender.Mobile.Mana < 25 ) { SendFailedGump( sender.Mobile, "Skill Required: ItemID 100.0+ & 25 mana.<br>" + "Regents: 10 of all magery regents." ); goto case Buttons.Magery; } sender.Mobile.SendMessage( 1192, "The Spell Binders of Tolaria have not concentrated on this area of work yet." ); goto case Buttons.Magery; } #endregion #region Necromancy case Buttons.PainSpike: { items = pack.ConsumeTotal( new Type[] { typeof( GnarledStaff ), typeof( ArcaneGem ), typeof( GraveDust ), typeof( PigIron ) }, new int[]{ 1, 1, 20, 20 } ); if ( sender.Mobile.Skills[SkillName.Necromancy].Base < 40.0 || items != -1 || sender.Mobile.Mana < 24 ) { SendFailedGump( sender.Mobile, "Skill Required: Necromancy 40.0+ & 25 mana.<br>" + "Items: An Arcane Gem, a Gnarled Staff (enchantments will be removed).<br>" + "Regents: 20 each of Grave Dust, Pig Iron." ); goto case Buttons.Necromancy; } sender.Mobile.Mana -= 25; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new PainSpikeStaff(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Necromancy; } case Buttons.BloodOath: { items = pack.ConsumeTotal( new Type[] { typeof( GnarledStaff ), typeof( ArcaneGem ), typeof( DaemonBlood ) }, new int[]{ 1, 1, 20 } ); if ( sender.Mobile.Skills[SkillName.Necromancy].Base < 40.0 || items != -1 || sender.Mobile.Mana < 64 ) { SendFailedGump( sender.Mobile, "Skill Required: Necromancy 40.0+ & 25 mana.<br>" + "Items: An Arcane Gem, a Gnarled Staff (enchantments will be removed).<br>" + "Regents: 20 Daemon Blood." ); goto case Buttons.Necromancy; } sender.Mobile.Mana -= 65; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new BloodOathStaff(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Necromancy; } case Buttons.CorpseSkin: { items = pack.ConsumeTotal( new Type[] { typeof( GnarledStaff ), typeof( ArcaneGem ), typeof( BatWing ), typeof( GraveDust ) }, new int[]{ 1, 1, 20, 20 } ); if ( sender.Mobile.Skills[SkillName.Necromancy].Base < 40.0 || items != -1 || sender.Mobile.Mana < 54 ) { SendFailedGump( sender.Mobile, "Skill Required: Necromancy 40.0+ & 25 mana.<br>" + "Items: An Arcane Gem, a Gnarled Staff (enchantments will be removed).<br>" + "Regents: 20 each of Bat Wing, Grave Dust." ); goto case Buttons.Necromancy; } sender.Mobile.Mana -= 55; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new CorpseSkinStaff(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Necromancy; } case Buttons.EvilOmen: { items = pack.ConsumeTotal( new Type[] { typeof( GnarledStaff ), typeof( ArcaneGem ), typeof( BatWing ), typeof( NoxCrystal ) }, new int[]{ 1, 1, 20, 20 } ); if ( sender.Mobile.Skills[SkillName.Necromancy].Base < 40.0 || items != -1 || sender.Mobile.Mana < 54 ) { SendFailedGump( sender.Mobile, "Skill Required: Necromancy 40.0+ & 25 mana.<br>" + "Items: An Arcane Gem, a Gnarled Staff (enchantments will be removed).<br>" + "Regents: 20 of each Bat Wing, Nox Crystal." ); goto case Buttons.Necromancy; } sender.Mobile.Mana -= 55; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new EvilOmenStaff(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Necromancy; } case Buttons.AnimateDead: { items = pack.ConsumeTotal( new Type[] { typeof( GnarledStaff ), typeof( ArcaneGem ), typeof( GraveDust ), typeof( DaemonBlood ) }, new int[]{ 1, 2, 20, 20 } ); if ( sender.Mobile.Skills[SkillName.Necromancy].Base < 60.0 || items != -1 || sender.Mobile.Mana < 114 ) { SendFailedGump( sender.Mobile, "Skill Required: Necromancy 40.0+ & 25 mana.<br>" + "Items: 2 Arcane Gems, a Gnarled Staff (enchantments will be removed).<br>" + "Regents: 20 of each Grave Dust, Daemon Blood." ); goto case Buttons.Necromancy; } sender.Mobile.Mana -= 115; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new AnimateDeadStaff(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Necromancy; } #endregion #region Chivalry case Buttons.CleanseByFire: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( Mace ), }, new int[]{ 1, 1 } ); if ( sender.Mobile.Skills[SkillName.Chivalry].Base < 25.0 || items != -1 || sender.Mobile.TithingPoints < 50 || sender.Mobile.Mana < 50 ) { SendFailedGump( sender.Mobile, "Skill Required: Chivalry 25.0+ & 50 mana.<br>" + "Items: Arcane Gem, a Mace (enchantments will be removed).<br>" + "Tithing: 50." ); goto case Buttons.Chivalry; } sender.Mobile.Mana -= 50; sender.Mobile.TithingPoints -= 50; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new CleanseByFireMace(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Chivalry; } case Buttons.CloseWounds: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( WarMace ), }, new int[]{ 1, 1 } ); if ( sender.Mobile.Skills[SkillName.Chivalry].Base < 20.0 || items != -1 || sender.Mobile.TithingPoints < 50 || sender.Mobile.Mana < 50 ) { SendFailedGump( sender.Mobile, "Skill Required: Chivalry 20.0+ & 50 mana.<br>" + "Items: Arcane Gem, a War Mace (enchantments will be removed).<br>" + "Tithing: 50." ); goto case Buttons.Chivalry; } sender.Mobile.Mana -= 50; sender.Mobile.TithingPoints -= 50; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new CloseWoundsWarMace(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Chivalry; } case Buttons.ConsecrateWeapon: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( HammerPick ), }, new int[]{ 1, 1 } ); if ( sender.Mobile.Skills[SkillName.Chivalry].Base < 35.0 || items != -1 || sender.Mobile.TithingPoints < 50 || sender.Mobile.Mana < 50 ) { SendFailedGump( sender.Mobile, "Skill Required: Chivalry 35.0+ & 50 mana.<br>" + "Items: Arcane Gem, a Hammer Pick (enchantments will be removed).<br>" + "Tithing: 50." ); goto case Buttons.Chivalry; } sender.Mobile.Mana -= 50; sender.Mobile.TithingPoints -= 50; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new ConsecrateWeaponHammerPick(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Chivalry; } case Buttons.RemoveCurse: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( Scepter ), }, new int[]{ 1, 1 } ); if ( sender.Mobile.Skills[SkillName.Chivalry].Base < 25.0 || items != -1 || sender.Mobile.TithingPoints < 50 || sender.Mobile.Mana < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Chivalry 25.0+ & 100 mana.<br>" + "Items: Arcane Gem, a Sceptor (enchantments will be removed).<br>" + "Tithing: 50." ); goto case Buttons.Chivalry; } sender.Mobile.Mana -= 100; sender.Mobile.TithingPoints -= 50; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new RemoveCurseScepter(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Chivalry; } case Buttons.DivineFury: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( WarHammer ), }, new int[]{ 1, 1 } ); if ( sender.Mobile.Skills[SkillName.Chivalry].Base < 45.0 || items != -1 || sender.Mobile.TithingPoints < 50 || sender.Mobile.Mana < 75 ) { SendFailedGump( sender.Mobile, "Skill Required: Chivalry 45.0+ & 75 mana.<br>" + "Items: Arcane Gem, a War Hammer (enchantments will be removed).<br>" + "Tithing: 50." ); goto case Buttons.Chivalry; } sender.Mobile.Mana -= 75; sender.Mobile.TithingPoints -= 50; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); wand = new DivineFuryWarHammer(); wand.Crafter = sender.Mobile; pack.DropItem( wand ); goto case Buttons.Chivalry; } #endregion #region Golems case Buttons.BloodGolem: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( PowerCrystal ), typeof( Garlic ), typeof( Ginseng ), typeof( MandrakeRoot ), typeof( SpidersSilk ), typeof( Head ), typeof( LeftArm ), typeof( RightArm ), typeof( LeftLeg ), typeof( RightLeg ) }, new int[]{ 3, 1, 50, 50, 50, 50, 1, 1, 1, 1, 1 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 50.0 || sender.Mobile.Skills[SkillName.Necromancy].Base < 50.0 || items != -1 || sender.Mobile.Mana < 74 || sender.Mobile.Hits < 100 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 50.0+ & Necromancy 50.0+ & 75 mana.<br>" + "Items: 3 Arcane Gems, Power Crystal, All the flesh parts from a humanoid corpse.<br>" + "Regents: 50 each of Garlic, Ginsing, Mandrake Root, Spider's Silk." + "Special: 100 Hit Points." ); goto case Buttons.Golems; } sender.Mobile.Hits -= 100; sender.Mobile.Mana -= 75; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); pack.DropItem( new GolemItem( GolemType.Blood ) ); goto case Buttons.Golems; } case Buttons.ClayGolem: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( PowerCrystal ), typeof( FertileDirt ), typeof( Bloodmoss ), typeof( GraveDust ), typeof( NoxCrystal ), typeof( SpidersSilk ), }, new int[]{ 2, 1, 4, 50, 50, 50, 50 } ); if ( items == -1 ) { Item[] itemlist = pack.FindItemsByType( typeof( Pitcher ) ); if ( itemlist.Length == 0 ) items = 0; Pitcher p = null; int found = 0; for ( int i = 0; i < itemlist.Length; i++ ) { p = (Pitcher)itemlist[i]; if ( p.IsFull && p.Content == BeverageType.Water ) found++; } if ( found < 4 ) items = 0; } if ( sender.Mobile.Skills[SkillName.Magery].Base < 75.0 || sender.Mobile.Skills[SkillName.Necromancy].Base < 75.0 || items != -1 || sender.Mobile.Mana < 99 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 75.0+ & Necromancy 75.0+ & 100 mana<br>" + "Items: 2 Arcane Gems, Power Crystal, 4 Fertile Dirt, 4 Pitchers full of water.<br>" + "Regents: 50 each of Bloodmoss, Grave Dust, Nox Crystal, Spider's Silk." ); goto case Buttons.Golems; } sender.Mobile.Mana -= 100; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); pack.DropItem( new GolemItem( GolemType.Clay ) ); goto case Buttons.Golems; } case Buttons.IronGolem: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( PowerCrystal ), typeof( BatWing ), typeof( Nightshade ), typeof( PigIron ) }, new int[]{ 4, 2, 50, 50, 100 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 100.0 || sender.Mobile.Skills[SkillName.Necromancy].Base < 100.0 || items != -1 || sender.Mobile.Mana < 124 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 100.0+ & Necromancy 100.0+ & 125 mana.<br>" + "Items: 4 Arcane Gems, 2 Power Crystals.<br>" + "Regents: 50 each of Bat Wing, Nightshade & 100 Pig Iron.<br>" + "Special: Armor or Weapon (consumed on use)" ); goto case Buttons.Golems; } sender.Mobile.Mana -= 125; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); pack.DropItem( new GolemItem( GolemType.Iron ) ); goto case Buttons.Golems; } case Buttons.FireGolem: { items = pack.ConsumeTotal( new Type[] { typeof( ArcaneGem ), typeof( PowerCrystal ), typeof( BlackPearl ), typeof( DaemonBlood ), typeof( MandrakeRoot ), typeof( SulfurousAsh ), }, new int[]{ 5, 2, 50, 50, 50, 200 } ); if ( sender.Mobile.Skills[SkillName.Magery].Base < 115.0 || sender.Mobile.Skills[SkillName.Necromancy].Base < 115.0 || items != -1 || sender.Mobile.Mana < 149 ) { SendFailedGump( sender.Mobile, "Skill Required: Magery 115.0+ & Necromancy 115.0+ & 150 mana." + "Items: 5 Arcane Gems, 2 Power Crystals, 200 Sulfurous Ash" + "Regents: 50 each of Black Peral, Daemon Blood, Mandrake Root & 200 Sulfurous Ash" + "Special: Armor or Weapon" ); goto case Buttons.Golems; } sender.Mobile.Mana -= 150; sender.Mobile.SendMessage( 1192, "You bound the spell to the item." ); pack.DropItem( new GolemItem( GolemType.Fire ) ); goto case Buttons.Golems; } #endregion } }