//---------------------------------------------------------------------- // Pick() -- this takes an encounter description and creates a real // instance. The primary purpose is to take the min/max // ranges of the elements and convert them into a specific // count -- nothing fancy. ) //---------------------------------------------------------------------- public RandomEncounter Pick( ) { RandomEncounter actualEncounter = new RandomEncounter( m_XmlNode, m_Facet, m_RegionType, m_RegionName, m_Inclusive ? "*" : m_Probability.ToString(), m_Shortest.ToString(), m_Farthest.ToString(), m_LandType.ToString(), m_EncounterTime.ToString(), m_Level.ToString(), m_LevelType.ToString(), m_ScaleUp.ToString() ); actualEncounter.m_Distance = Utility.RandomMinMax(m_Shortest, m_Farthest); foreach (EncounterElement element in m_Elements) { ArrayList pickedElements = element.Pick(); foreach (EncounterElement pickedElement in pickedElements) { actualEncounter.m_Elements.Add(pickedElement); } } return(actualEncounter); }
public void AddEncounter(RandomEncounter encounter) { object o = m_PossibleEncounters.Find(new EncounterSet.QuickSearch(encounter.Probability)); EncounterSet encounterSet; if (o == null) { encounterSet = new EncounterSet(encounter.Probability); m_PossibleEncounters.Add(encounterSet); } else { encounterSet = (EncounterSet)o; } encounterSet.Add(encounter); }
public void AddEncounter( RandomEncounter encounter ) { object o = m_PossibleEncounters.Find( new EncounterSet.QuickSearch( encounter.Probability )); EncounterSet encounterSet; if (o==null) { encounterSet = new EncounterSet( encounter.Probability ); m_PossibleEncounters.Add( encounterSet ); } else { encounterSet = (EncounterSet) o; } encounterSet.Add( encounter ); }
//---------------------------------------------------------------------- // Pick() -- this takes an encounter description and creates a real // instance. The primary purpose is to take the min/max // ranges of the elements and convert them into a specific // count -- nothing fancy. ) //---------------------------------------------------------------------- public RandomEncounter Pick( ) { RandomEncounter actualEncounter = new RandomEncounter( m_XmlNode, m_Facet, m_RegionType, m_RegionName, m_Inclusive ? "*" : m_Probability.ToString(), m_Shortest.ToString(), m_Farthest.ToString(), m_LandType.ToString(), m_EncounterTime.ToString(), m_Level.ToString(), m_LevelType.ToString(), m_ScaleUp.ToString() ); actualEncounter.m_Distance = Utility.RandomMinMax( m_Shortest, m_Farthest ); foreach( EncounterElement element in m_Elements ) { ArrayList pickedElements = element.Pick(); foreach( EncounterElement pickedElement in pickedElements ) { actualEncounter.m_Elements.Add( pickedElement ); } } return actualEncounter; }
private static void GenerateEncounterRecursive( Map map, PlayerMobile playerMobile, Point3D parentLocation, ArrayList cleanupList, RandomEncounter encounterTemplate, EncounterElement parentElement, object parentObject ) { Type typeObject = SpawnerType.GetType( parentElement.PickFrom ); if( typeObject == null ) { Console.WriteLine( "RandomEncounters: Bad attempt to generate an element of type \"{0}\".", parentElement.PickFrom ); return; } Point3D spawnPoint; if( parentObject == null ) spawnPoint = parentLocation; else { spawnPoint = new Point3D(); if( !SpawnFinder.FindOutwards( playerMobile, parentLocation, ref spawnPoint, encounterTemplate.LandType, 1, parentElement.Effect, parentElement.EffectHue ) ) { //Console.WriteLine("NO SPAWN LOCATION AVAILABLE"); return; } } object created; try { created = Activator.CreateInstance( typeObject ); } catch( Exception e ) //-------------------------------------------------------------- // most likely reason that we may fail is an attempt to construct an object // that requires arguments in its constructor; here we'll help the user // diagnose their problem, but otherwise ignore this part of the encounter // without terminating: //-------------------------------------------------------------- { string line = parentElement.XmlNode.Attributes["lineNumber"].Value; Console.WriteLine( "RandomEncounters: Bad attempt to contruct an element of type \"{0}\", on line {1}", parentElement.PickFrom, line ); Console.WriteLine( "{0}", e ); return; // go no deeper, we're done here, stop recursing } if( created is Mobile ) { Mobile m = (Mobile)created; XmlAttach.AttachTo( m, new XmlDateCount( "RandomEncountersCreated" ) ); //ObjectPropertyList props = m.PropertyList; cleanupList.Add( m ); //here's where we might add monster to its own party, if it had one //if( parentObject!=null && parentObject is Mobile ) //{ // Mobile parentMobile = (Mobile) parentObject; //} m.OnBeforeSpawn( spawnPoint, map ); m.MoveToWorld( spawnPoint, map ); if( m is BaseCreature ) { BaseCreature c = (BaseCreature)m; if( c.IsEnemy( playerMobile ) ) { // deprecated now with the configurable forceAttack option // if( c.AI == AIType.AI_Animal ) // { // if( c.Fame > 350 ) // { // c.Combatant = playerMobile; // } // } if( c.AI == AIType.AI_Vendor ) ; else if( parentElement.ForceAttack ) c.Combatant = playerMobile; } c.Home = spawnPoint; } m.OnAfterSpawn(); if( encounterTemplate.ScaleUp ) { double pLevel = Helpers.CalculateLevelForMobile( playerMobile, LevelType.Fighter ); double mLevel = Helpers.CalculateLevelForMobile( m, LevelType.Overall ); double ratio = pLevel / mLevel; int scaleUp = (int)(ratio - .5); if( scaleUp > 2 ) scaleUp = 2; //-------------------------------------------------------------- // Handle add-ons from level based scaling here: //-------------------------------------------------------------- if( scaleUp > 0 ) for( int i = 0; i < scaleUp; i++ ) { Point3D addonPoint = new Point3D(); if( !SpawnFinder.FindOutwards( playerMobile, parentLocation, ref addonPoint, encounterTemplate.LandType, 1, parentElement.Effect, parentElement.EffectHue ) ) { return; } Mobile addonMob = (Mobile)Activator.CreateInstance( typeObject ); XmlAttach.AttachTo( addonMob, new XmlDateCount( "RandomEncountersCreated" ) ); cleanupList.Add( addonMob ); addonMob.OnBeforeSpawn( addonPoint, map ); addonMob.MoveToWorld( addonPoint, map ); if( addonMob is BaseCreature ) { BaseCreature c = (BaseCreature)addonMob; if( c.IsEnemy( playerMobile ) ) { //if( c.AI == AIType.AI_Animal ) //{ // if( c.Fame > 350 ) c.Combatant = playerMobile; //} if( c.AI == AIType.AI_Vendor ) ; else if( parentElement.ForceAttack ) c.Combatant = playerMobile; } c.Home = addonPoint; } addonMob.OnAfterSpawn(); } } } else if( created is Item ) { Item item = (Item)created; //ObjectPropertyList props = item.PropertyList; //if( !item.Movable) XmlAttach.AttachTo( item, new XmlDate( "RandomEncountersCreated" )); XmlAttach.AttachTo( item, new XmlDateCount( "RandomEncountersCreated" ) ); item.OnBeforeSpawn( spawnPoint, map ); //-------------------------------------------------------------- // some core items won't decay, but we need them to: // the code is in the core, and we don't want to modify that, // so we will do it here instead //-------------------------------------------------------------- if( !item.Movable ) { cleanupList.Add( created ); } if( parentObject != null ) { if( parentObject is Mobile ) { Mobile mobileParent = (Mobile)parentObject; //Console.WriteLine( "RandomEncounters: added item to mobile: " + item ); mobileParent.AddItem( item ); } else if( parentObject is Container ) { Container itemParent = (Container)parentObject; //Console.WriteLine( "RandomEncounters: added item to container: " + item ); itemParent.AddItem( item ); } else { item.MoveToWorld( spawnPoint, map ); //Console.WriteLine( "RandomEncounters: inserted item into world: " + item ); } } else { item.MoveToWorld( spawnPoint, map ); //Console.WriteLine( "RandomEncounters: inserted item into world: " + item ); } item.OnAfterSpawn(); } foreach( EncounterElement childElement in parentElement.Elements ) { GenerateEncounterRecursive( map, playerMobile, spawnPoint, cleanupList, encounterTemplate, childElement, created ); } }
//---------------------------------------------------------------------- // GenerateEncounter -- this takes an encounter description and // creates an actual encounter. Since our random draw in the previous // section means that we got here, all that's left to do is narrow // down the actual encounter template to a definitive description // (this converts min-max ranges to actuals), plot out positions // for the various elements, create their Mobiles/Items, and go. //---------------------------------------------------------------------- private static void GenerateEncounter( PlayerMobile playerMobile, RandomEncounter encounterTemplate, ArrayList cleanupList ) { RandomEncounter encounter = encounterTemplate.Pick(); Map map = playerMobile.Map; Point3D location = new Point3D( playerMobile.X, playerMobile.Y, playerMobile.Z ); Point3D spawnPoint = new Point3D(); if( m_Debug ) { Console.WriteLine( "RandomEncounters: generating instances: {0} ...", encounter ); DumpEncounter( 1, encounter ); } // test code // Tile playerTile = map.Tiles.GetLandTile( location.X, location.Y ); // Tile[] staticTiles = map.Tiles.GetStaticTiles( location.X, location.Y, true ); // // Console.WriteLine("Player Location: {0}", location ); // Console.WriteLine(" Land Tile id={0} z={1} height={2}: ", playerTile.ID, playerTile.Z, playerTile.Height ); // // uint flags = (uint) TileData.LandTable[playerTile.ID & 0x3FFF].Flags; // Console.WriteLine(" Land Flags: {0:x}", flags ); // // foreach( Tile staticTile in staticTiles ) // { // Console.WriteLine(" Static Tile id={0} z={1} height={2}", staticTile.ID, staticTile.Z, staticTile.Height ); // flags = (uint) TileData.LandTable[staticTile.ID & 0x3FFF].Flags; // Console.WriteLine(" Static Flags: {0:x}", flags ); // } foreach( EncounterElement element in encounter.Elements ) { bool running = ((playerMobile.Direction & Direction.Running) > 0); bool foundQuadrant = false; if( running ) { foundQuadrant = SpawnFinder.FindAhead( playerMobile, location, ref spawnPoint, encounter.LandType, encounter.Distance, element.Effect, element.EffectHue ); } if( !foundQuadrant ) if( !SpawnFinder.FindInwards( playerMobile, location, ref spawnPoint, encounter.LandType, encounter.Distance, element.Effect, element.EffectHue ) ) { //---------------------------------------------------------- // if we can't find a location, there's no chance we'll find any others: // STOP! do not attempt to add any more elements to the encounter, there // simply is NO SPACE LEFT. //---------------------------------------------------------- // Console.WriteLine("NO SPAWN LOCATION AVAILABLE"); return; } GenerateEncounterRecursive( map, playerMobile, spawnPoint, cleanupList, encounterTemplate, element, null ); } }
//---------------------------------------------------------------------- // Process New Encounter -- this fills up our records database, // per facet, per region, per region name, of probability-organized // enounters to pick from. //---------------------------------------------------------------------- private static void ProcessNewEncounter( RandomEncounter encounter ) { //------------------------------------------------------------------ // Previously encountered something pertaining to this facet, region, // and region name... //------------------------------------------------------------------ if( m_RegionHash.Contains( encounter.Key ) ) { RegionRecord region = (RegionRecord)m_RegionHash[encounter.Key]; region.AddEncounter( encounter ); } //------------------------------------------------------------------ // Have never encountered anything for this facet, region, and region // name: //------------------------------------------------------------------ else { RegionRecord region = new RegionRecord( encounter.Key ); region.AddEncounter( encounter ); m_RegionHash[encounter.Key] = region; } }
//---------------------------------------------------------------------- // Actual XML load-out and node iteration //---------------------------------------------------------------------- private static bool LoadXml() { XmlLinePreservingDocument xmlDoc = new XmlLinePreservingDocument( m_EncountersFile ); try { xmlDoc.DoLoad(); string language = "en-US"; string skipHidden = "true"; string picker = "sqrt"; string delay = "60"; string interval = "1800"; string cleanup = "300"; string cleanupgrace = "1"; string debug = "false"; string debugEffect = "false"; string RTFM = "true"; //------------------------------------------------------------------ // Pull out initial information for configuration tags //------------------------------------------------------------------ XmlNode root = xmlDoc["RandomEncounters"]; try { language = root.Attributes["language"].Value; } catch { } try { skipHidden = root.Attributes["skiphidden"].Value; } catch { } try { picker = root.Attributes["picker"].Value; } catch { } try { delay = root.Attributes["delay"].Value; } catch { } try { interval = root.Attributes["interval"].Value; } catch { } try { cleanup = root.Attributes["cleanup"].Value; } catch { } try { cleanupgrace = root.Attributes["cleanupGrace"].Value; } catch { } try { debug = root.Attributes["debug"].Value; } catch { } try { debugEffect = root.Attributes["debugEffect"].Value; } catch { } try { RTFM = root.Attributes["RTFM"].Value; } catch { } m_Language = new CultureInfo( language ); m_SkipHidden = bool.Parse( skipHidden ); m_Picker = picker; m_Delay = float.Parse( delay, m_Language ); m_Cleanup = float.Parse( cleanup, m_Language ); m_CleanupGrace = int.Parse( cleanupgrace, m_Language ); m_Debug = bool.Parse( debug ); m_DebugEffect = bool.Parse( debugEffect ); bool rtfm = bool.Parse( RTFM ); if( !rtfm ) { Console.WriteLine( "\n" + "##### RandomEncounters: SYSTEM CONFIG FILE FOUND, HOWEVER IT APPEARS THAT YOU DID NOT ACTUALLY READ IT!\n\n" + " RandomEncounters will **NOT** work if you have not read and edited the config file.\n" + " It is suggested that you do so now; the file can be found here:\n\n" + " \"{0}\"\n", m_EncountersFile ); throw new Exception( "RTFM" ); } // Break out our intervals into our acceptible set; careful here, // changing this to return less than 3 intervals will break other code // Dungeon Wilderness Guarded House Jail { string[] tokens = interval.Split( new Char[] { ':' } ); int n = tokens.Length < 3 ? 3 : tokens.Length; m_Intervals = new float[n]; if( tokens.Length == 5 ) { m_Intervals[4] = float.Parse( tokens[4], m_Language ); // Jail } if( tokens.Length >= 4 ) { m_Intervals[3] = float.Parse( tokens[3], m_Language ); // House } if( tokens.Length >= 3 ) { m_Intervals[0] = float.Parse( tokens[0], m_Language ); // Guarded m_Intervals[1] = float.Parse( tokens[1], m_Language ); // Guarded m_Intervals[2] = float.Parse( tokens[2], m_Language ); // Guarded } if( tokens.Length == 2 ) { m_Intervals[0] = float.Parse( tokens[0], m_Language ); // Dungeon m_Intervals[1] = float.Parse( tokens[1], m_Language ); // Wilderness m_Intervals[2] = float.Parse( tokens[1], m_Language ); // Guarded } if( tokens.Length == 1 ) { m_Intervals[0] = float.Parse( tokens[0], m_Language ); // Dungeon m_Intervals[1] = float.Parse( tokens[0], m_Language ); // Wilderness m_Intervals[2] = float.Parse( tokens[0], m_Language ); // Guarded } } XmlNodeList facetNodes = xmlDoc.GetElementsByTagName( "Facet" ); //------------------------------------------------------------------ // Iterate over facets //------------------------------------------------------------------ foreach( XmlNode facetNode in facetNodes ) { string facetName = ""; try { facetName = facetNode.Attributes["name"].Value; } catch { Console.WriteLine( "RandomEncounters: Facet at {1} had no name. THIS IS ILLEGAL. IGNORED ENTIRE FACET!", facetNode.Attributes["lineNumber"].Value ); continue; } XmlNodeList regionNodes = facetNode.SelectNodes( "./Region" ); if( regionNodes.Count == 0 ) Console.WriteLine( "RandomEncounters: Facet \"{0}\" at {1} had no elements. IGNORED.", facetName, facetNode.Attributes["lineNumber"].Value ); //-------------------------------------------------------------- // Now over regions //-------------------------------------------------------------- foreach( XmlNode regionNode in regionNodes ) { string regionType = "Wilderness"; string regionName = "default"; string failed = ""; try { regionType = regionNode.Attributes["type"].Value; } catch { failed = "type"; } try { regionName = regionNode.Attributes["name"].Value; } catch { ; } if( failed != "" ) { Console.WriteLine( "Attempted to add an element without a {0} at {1}. IGNORING.", failed, regionNode.Attributes["lineNumber"].Value ); return false; } XmlNodeList encounterNodes = regionNode.SelectNodes( "./Encounter" ); if( encounterNodes.Count == 0 ) Console.WriteLine( "RandomEncounters: {0} Region \"{1}\" at {2} had no elements. IGNORED.", regionType, regionName, regionNode.Attributes["lineNumber"].Value ); //------------------------------------------------------ // Now over encounters //------------------------------------------------------ foreach( XmlNode encounterNode in encounterNodes ) { string encounterProbability = "1.0"; string encounterDistance = "7"; string encounterLand = "AnyLand"; string encounterTime = "AnyTime"; string encounterWater = "false"; string encounterLevel = "1"; string encounterScale = "false"; try { encounterDistance = encounterNode.Attributes["distance"].Value; } catch { } try { encounterProbability = encounterNode.Attributes["p"].Value; } catch { } try { encounterLand = encounterNode.Attributes["landType"].Value; } catch { } try { encounterWater = encounterNode.Attributes["water"].Value; } catch { } try { encounterTime = encounterNode.Attributes["time"].Value; } catch { } try { encounterLevel = encounterNode.Attributes["level"].Value; } catch { } try { encounterScale = encounterNode.Attributes["scaleUp"].Value; } catch { } if( bool.Parse( encounterWater ) == true ) { if( m_Debug ) Console.WriteLine( "RandomEncounters, WARNING: \"water\" tag is deprecated; use landType=\"Water\" instead" ); encounterLand = "Water"; } string[] distance_tok = encounterDistance.Split( new Char[] { ':' } ); // splits to shortest:farthest, or just distance if no ':' string[] level_tok = encounterLevel.Split( new Char[] { ':' } ); RandomEncounter randomEncounter = new RandomEncounter( encounterNode, facetName, regionType, regionName, encounterProbability, distance_tok[0], (distance_tok.Length > 1 ? distance_tok[1] : distance_tok[0]), encounterLand, encounterTime, level_tok[0], (level_tok.Length > 1 ? level_tok[1] : "Overall"), encounterScale ); XmlNodeList elementNodes = encounterNode.SelectNodes( "Mobile | Item " ); if( elementNodes.Count == 0 ) Console.WriteLine( "RandomEncounters: Encounter on line {0} had no children. IGNORED.", encounterNode.Attributes["lineNumber"].Value ); //---------------------------------------------- // Now iterate over subelements //---------------------------------------------- foreach( XmlNode elementNode in elementNodes ) AddRecursiveMobilesAndItems( encounterNode, elementNode, randomEncounter ); //------------------------------------------ // Now they we've built it up, process it: //------------------------------------------ ProcessNewEncounter( randomEncounter ); } } } return true; } catch( Exception e ) { Console.WriteLine( "RandomEncounters: Exception caught attempting to load file: " + m_EncountersFile ); Console.WriteLine( "{0}", e ); xmlDoc.Close(); return false; } }
//---------------------------------------------------------------------- // Dump out text for debugging information //---------------------------------------------------------------------- internal static void DumpEncounter( int depth, RandomEncounter encounter ) { string prepend = ""; for( int i = 0; i < depth; i++ ) prepend += " "; Console.WriteLine( "{0}{1}", prepend, encounter ); foreach( EncounterElement element in encounter.Elements ) { DumpElementRecursive( 2, element ); } }