Praxiiz updated UltimaLive Lumber Harvesting with a new update entry:
Fixed Typo
Read the rest of this update entry...
Fixed Typo
Fixed typo from previous package
Read the rest of this update entry...
Fixed typo from previous package
Eh I can't seem to replicate it lol.. perhaps I just broke something at that point. I have tried to replicate it and I even used [DelStatic to remove the stumps and try to do it in the same area. I think it was just a fluke that seems to have fixed itself.I'll see if I can track that down, it should be removing the stumps of course.
public static Dictionary<int, Dictionary<Point3D, int>> RegrowthMasterLookupTable = new Dictionary<int, Dictionary<Point3D, int>>();
tileID = (obj.ItemID & 0x3FFF) | 0x4000;
if you reverted your server to a backup that shouldn't have affected the scripts inside your script folder... so we're good there. If it was a save backup you reverted from.... then the problem is you deleted some key files when you reverted that gets exported when the server is running. Look in the UltimaLiveSettings.cs folder to find the directory for the Lumber Harvest.... It will look something like this:
public const string ULTIMA_LIVE_LUMBER_HARVEST_FOLDER_NAME = @"LumberHarvest";
The only other option I think is to reinstall Ultima Live and then the Lumber Harvest System.
"m309, post: 13204, member: 7"]@gametec, any chance that now that you've taken this on you're going to look into the fact that files can't be used after the ML client range?
StaticTarget harvestTarget = toHarvest
as StaticTarget;
if (harvestTarget != null)
{
if (from.CheckSkill(def.Skill, 0, 120))
{
if (tool is IUsesRemaining)
{
IUsesRemaining toolWithUses = (IUsesRemaining)tool;
toolWithUses.ShowUsesRemaining =
true;
if (toolWithUses.UsesRemaining > 0)
{
--toolWithUses.UsesRemaining;
}
if (toolWithUses.UsesRemaining < 1)
{
tool.Delete();
def.SendMessageTo(from, def.ToolBrokeMessage);
}
}
}
BaseHarvestablePhase hTreePhase = BaseHarvestablePhase.LookupPhase(harvestTarget.ItemID);
if (hTreePhase != null && hTreePhase is BaseTreeHarvestPhase)
{
hTreePhase.Harvest(from, harvestTarget.ItemID, harvestTarget.Location, map);
!!!ADDITION TO SCRIPT!!!
else public DelStaticCommand(from, harvestTarget.ItemID, harvestTarget.Location, map);
}
}
}
}
}
@gametec, any chance that now that you've taken this on you're going to look into the fact that files can't be used after the ML client range?
for (int mapId = 0; mapId < RegrowthMasterLookupTable.Count; ++mapId)
public static void Configure()
{
foreach (Map m in Map.AllMaps)
{
RegrowthMasterLookupTable.Add(m.MapID, new Dictionary<Point3D, int>());
}
EventSink.WorldSave += new WorldSaveEventHandler(OnSave);
EventSink.WorldLoad += new WorldLoadEventHandler(OnLoad);
}
public static void OnLoad()
{
foreach (Map m in Map.AllMaps)
{
RegrowthMasterLookupTable.Add(m.MapID, new Dictionary<Point3D, int>());
}
for (int mapId = 0; mapId < RegrowthMasterLookupTable.Count; ++mapId)
{...
ServUO - [http://www.servuo.com] Version 0.5, Build 5658.25009
Publish 54
Core: Optimizing for August 64-bit processors
RandomImpl: CSPRandom (Software)
OpenUO Error: Client files not found.
Scripts: Compiling C # scripts ... done (cached)
Scripts: Scripts VB.NET Skipping ... done (to enable use -vb)
Scripts: Verifying ...
Finished (4996 items, 1016 mobiles 11 customs) (1.30 seconds)
Error:
System.Reflection.TargetInvocationException: An exception occurred in the dest
ino invocation. ---> System.ArgumentException: Since an element is added co
n the same key.
in System.Collections.Generic.Dictionary`2.Insert (TKey key, TValue value, Boo
read add)
in Server.Engines.Harvest.UltimaLiveLumberjacking.Configure ()
--- End of monitoring the inner exception stack ---
in System.RuntimeMethodHandle.InvokeMethod (Object target, Object [] arguments,
Signature sig, Boolean constructor)
in System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal (Object obj, Objec
t [] parameters, Object [] arguments)
in System.Reflection.RuntimeMethodInfo.Invoke (Object obj, invoke BindingFlags
Attr, Binder binder, Object [] parameters, CultureInfo culture)
in Server.ScriptCompiler.Invoke (String method)
in Server.Core.Main (String [] args)
Hahaha, sorry!!!pall you should consider do a translate on your errors when posting
Code:ServUO - [http://www.servuo.com] Version 0.5, Build 5658.25009 Publish 54 Core: Optimizing for August 64-bit processors RandomImpl: CSPRandom (Software) OpenUO Error: Client files not found. Scripts: Compiling C # scripts ... done (cached) Scripts: Scripts VB.NET Skipping ... done (to enable use -vb) Scripts: Verifying ... Finished (4996 items, 1016 mobiles 11 customs) (1.30 seconds) Error: System.Reflection.TargetInvocationException: An exception occurred in the dest ino invocation. ---> System.ArgumentException: Since an element is added co n the same key. in System.Collections.Generic.Dictionary`2.Insert (TKey key, TValue value, Boo read add) in Server.Engines.Harvest.UltimaLiveLumberjacking.Configure () --- End of monitoring the inner exception stack --- in System.RuntimeMethodHandle.InvokeMethod (Object target, Object [] arguments, Signature sig, Boolean constructor) in System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal (Object obj, Objec t [] parameters, Object [] arguments) in System.Reflection.RuntimeMethodInfo.Invoke (Object obj, invoke BindingFlags Attr, Binder binder, Object [] parameters, CultureInfo culture) in Server.ScriptCompiler.Invoke (String method) in Server.Core.Main (String [] args)
public bool Harvest(Mobile from, int itemId, Point3D harvestTargetLocation, Map map, ref MapOperationSeries operationSeries)
{
Point3D trunkLocation = LookupOriginLocation(harvestTargetLocation, itemId);
List<KeyValuePair<int, GraphicAsset>> phasePiecesRemoved = null;
//If the next phase is not null, tear it all down and construct the next phase
if (NextHarvestPhase != null)
{
phasePiecesRemoved = RemoveAssets(map, trunkLocation, ref operationSeries, BaseAssetSets);
int constructedTreeHue = 0;
if (MasterHarvestablePhaseLookupByTypeList.ContainsKey(NextHarvestPhase))
{
constructedTreeHue = MasterHarvestablePhaseLookupByTypeList[NextHarvestPhase].Construct(trunkLocation, map, ref operationSeries);
}
if (operationSeries != null)
{
RecordTreeLocationAndGraphic(map.MapID, BaseAssetSets[0][0].ItemID, trunkLocation);
if (AddStump)
{
operationSeries.Add(new AddStatic(map.MapID, StumpGraphic, trunkLocation.Z, trunkLocation.X, trunkLocation.Y, constructedTreeHue));
}
}
}
else //the next phase is not null, so destroy one asset at a time
{
GraphicAsset asset = LookupAsset(itemId);
List<GraphicAsset[]> assetsToRemove = new List<GraphicAsset[]>();
assetsToRemove.Add(new GraphicAsset[] { asset });
phasePiecesRemoved = RemoveAssets(map, trunkLocation, ref operationSeries, assetsToRemove);
}
int hue = 0;
from.SendMessage("{0}", phasePiecesRemoved.Count); // DEBUG
//give out phase resource for each graphic asset removed
foreach (KeyValuePair<int, GraphicAsset> assetPair in phasePiecesRemoved)
{
hue = assetPair.Key;
Item itm = this.ReapResource(assetPair.Key, from, assetPair.Value.HarvestResourceBaseAmount);
from.SendMessage("{0}, {1}", hue, itm); // DEBUG
if (itm != null)
{
from.AddToBackpack(itm);
}
}
//give out asset bonus resources
foreach (Item itm in this.ReapBonusResources(hue, from))
{
from.AddToBackpack(itm);
}
bool returnValue = false;
if (operationSeries != null)
{
returnValue = true;
}
return returnValue;
}
amazing system, Praxiiz! huge thanks for contribution!
I have a problem with wood types, though - every time I harvest I can only get the resource defined in the "0" key of "PhaseResources" dictionary.
method "Harvest()" in BaseTreeHarvestPhase.cs:debug messages show that "phasePiecesRemoved" always return 1 entry with key (hue) value 0 - if that entry is not defined in the tree's resources, you get no logs.Code:public bool Harvest(Mobile from, int itemId, Point3D harvestTargetLocation, Map map, ref MapOperationSeries operationSeries) { Point3D trunkLocation = LookupOriginLocation(harvestTargetLocation, itemId); List<KeyValuePair<int, GraphicAsset>> phasePiecesRemoved = null; //If the next phase is not null, tear it all down and construct the next phase if (NextHarvestPhase != null) { phasePiecesRemoved = RemoveAssets(map, trunkLocation, ref operationSeries, BaseAssetSets); int constructedTreeHue = 0; if (MasterHarvestablePhaseLookupByTypeList.ContainsKey(NextHarvestPhase)) { constructedTreeHue = MasterHarvestablePhaseLookupByTypeList[NextHarvestPhase].Construct(trunkLocation, map, ref operationSeries); } if (operationSeries != null) { RecordTreeLocationAndGraphic(map.MapID, BaseAssetSets[0][0].ItemID, trunkLocation); if (AddStump) { operationSeries.Add(new AddStatic(map.MapID, StumpGraphic, trunkLocation.Z, trunkLocation.X, trunkLocation.Y, constructedTreeHue)); } } } else //the next phase is not null, so destroy one asset at a time { GraphicAsset asset = LookupAsset(itemId); List<GraphicAsset[]> assetsToRemove = new List<GraphicAsset[]>(); assetsToRemove.Add(new GraphicAsset[] { asset }); phasePiecesRemoved = RemoveAssets(map, trunkLocation, ref operationSeries, assetsToRemove); } int hue = 0; from.SendMessage("{0}", phasePiecesRemoved.Count); // DEBUG //give out phase resource for each graphic asset removed foreach (KeyValuePair<int, GraphicAsset> assetPair in phasePiecesRemoved) { hue = assetPair.Key; Item itm = this.ReapResource(assetPair.Key, from, assetPair.Value.HarvestResourceBaseAmount); from.SendMessage("{0}, {1}", hue, itm); // DEBUG if (itm != null) { from.AddToBackpack(itm); } } //give out asset bonus resources foreach (Item itm in this.ReapBonusResources(hue, from)) { from.AddToBackpack(itm); } bool returnValue = false; if (operationSeries != null) { returnValue = true; } return returnValue; }
Without custom graphics each fallen tree is "SmallFallenTreeEastWest". Am I missing something? I can't see any Random() in the code of the method, when does it check if you should get other resources than regular logs?
public SmallTree() : base ()
{
#region Full Grown Tree Phase
//This is a simple tree type, so there is only main Tree phase
PhaseResources.Add(0, new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log)));
// 350 here is hue number 350
PhaseResources.Add(350, new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog)));
PhaseResources.Add(751, new HarvestResource(80.0, 40.0, 120.0, 1072542, typeof(AshLog)));
PhaseResources.Add(545, new HarvestResource(95.0, 55.0, 135.0, 1072543, typeof(YewLog)));
PhaseResources.Add(436, new HarvestResource(100.0, 60.0, 140.0, 1072544, typeof(HeartwoodLog)));
PhaseResources.Add(339, new HarvestResource(100.0, 60.0, 140.0, 1072545, typeof(BloodwoodLog)));
PhaseResources.Add(688, new HarvestResource(100.0, 60.0, 140.0, 1072546, typeof(FrostwoodLog)));
//this tree has two sets of leafs that are possible
foreach (int treeTrunkId in SmallTreeTrunkGraphics)
{
BaseAssetSets.Add(new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) });
}
foreach (int leafId in SmallTreeLeafGraphics)
{
LeafSets.Add(new GraphicAsset[] { new GraphicAsset(leafId, 0, 0) });
}
#endregion
}
BaseAssetSets.Add(new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) });
var asset = new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) }
var resource1 = new BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type);
var resource2 = new BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type);
asset.BonusResources[hue] = new BonusResource[] { resource1, resource2}
asset.BonusResourceBaseAmount =1;
BaseAssetSets.Add(asset)
The way the system works is through phases. If you look at the HarvestableTrees.cs, you'll see lots of examples of this.
The base classes of the system are setup so that they can be reused for other types of graphic harvest systems.
Phases handle what happens when you harvest the tree (or something else) or when the tree grows.
Graphic assets define the graphics and possible bonus rewards granted from harvesting a tree.
If you look at HarvestableTrees.cs, you will see lots of examples of this.
The basehavestablephase defines several overridable methods:
StartingGrowthPhase, NextGrowthPhase, NextHarvestPhase, FinalHarvestPhase, etc...
This allows you to build up phases, each phase pointing to the next.
e.g. phase1 --> phase2 --> phase3
It also describes growth:
e.g. growth phase1 --> growth phase2 --> growth phase3
each phase consists of graphics assets, rewards, etc.
If you look at the SmallTree class, you'll see the hues defined with their associated resources.
Code:public SmallTree() : base () { #region Full Grown Tree Phase //This is a simple tree type, so there is only main Tree phase PhaseResources.Add(0, new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log))); // 350 here is hue number 350 PhaseResources.Add(350, new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog))); PhaseResources.Add(751, new HarvestResource(80.0, 40.0, 120.0, 1072542, typeof(AshLog))); PhaseResources.Add(545, new HarvestResource(95.0, 55.0, 135.0, 1072543, typeof(YewLog))); PhaseResources.Add(436, new HarvestResource(100.0, 60.0, 140.0, 1072544, typeof(HeartwoodLog))); PhaseResources.Add(339, new HarvestResource(100.0, 60.0, 140.0, 1072545, typeof(BloodwoodLog))); PhaseResources.Add(688, new HarvestResource(100.0, 60.0, 140.0, 1072546, typeof(FrostwoodLog))); //this tree has two sets of leafs that are possible foreach (int treeTrunkId in SmallTreeTrunkGraphics) { BaseAssetSets.Add(new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) }); } foreach (int leafId in SmallTreeLeafGraphics) { LeafSets.Add(new GraphicAsset[] { new GraphicAsset(leafId, 0, 0) }); } #endregion }
If you want to add bonus resources, you need to adjust some properties of each graphic asset. Instead of doing
Code:BaseAssetSets.Add(new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) });
You will want to add a graphic asset with bonus resources:
Code:var asset = new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) } var resource1 = new BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type); var resource2 = new BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type); asset.BonusResources[hue] = new BonusResource[] { resource1, resource2} asset.BonusResourceBaseAmount =1; BaseAssetSets.Add(asset)
You'll have to fill in the hue, and figure out what bonus resource you want to use in the above code. You'll also have to decide how many of the resources you want to be possible for harvest.
I feel like I'm being daft here I thought the hue in PhaseResources.Add(350, new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog))); was the hue of the resource. Is it the hue of the tree? Is that why with stock graphics I got only normal wood - because the tree's hue was 0, and for a tree with hue 0 only normal log was defined? So, you can use the same type of tree, but set it to different hue to get different resource?If you look at the SmallTree class, you'll see the hues defined with their associated resources.
Code:public SmallTree() : base () { #region Full Grown Tree Phase //This is a simple tree type, so there is only main Tree phase PhaseResources.Add(0, new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log))); // 350 here is hue number 350 PhaseResources.Add(350, new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog))); PhaseResources.Add(751, new HarvestResource(80.0, 40.0, 120.0, 1072542, typeof(AshLog))); PhaseResources.Add(545, new HarvestResource(95.0, 55.0, 135.0, 1072543, typeof(YewLog))); PhaseResources.Add(436, new HarvestResource(100.0, 60.0, 140.0, 1072544, typeof(HeartwoodLog))); PhaseResources.Add(339, new HarvestResource(100.0, 60.0, 140.0, 1072545, typeof(BloodwoodLog))); PhaseResources.Add(688, new HarvestResource(100.0, 60.0, 140.0, 1072546, typeof(FrostwoodLog))); //this tree has two sets of leafs that are possible foreach (int treeTrunkId in SmallTreeTrunkGraphics) { BaseAssetSets.Add(new GraphicAsset[] { new GraphicAsset(treeTrunkId, 0, 0) }); } foreach (int leafId in SmallTreeLeafGraphics) { LeafSets.Add(new GraphicAsset[] { new GraphicAsset(leafId, 0, 0) }); } #endregion }
PhaseResources.Add(0, new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log)));
PhaseResources.Add(0, new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog)));
We use essential cookies to make this site work, and optional cookies to enhance your experience.