So far so good mate, great job on this! I got to watch the stumps turn to saplings on world save. I can't wait to play around with this further this system is incredible! I will of course let you know if I break anything else :)
 
So I did find one odd bug, not sure how it happens or why but I will explain to you what I did to cause it and see if it can be replicated.
Basically I cleared a small forest area by chopping the trees down and left all the logs on the ground since I didn't care about them. I then saved half a dozen times then remembered that it needs to be at least ONE minute then a save for the regrowth. So I waited until time had passed then saved again, all the logs vanished like they should then the saplings grew, however not all the stumps vanished and the trees grew into them lol.

Here is a SS to show you what I mean:
ss (2014-03-28 at 10.09.42.2).jpg
 
You know it didn't occur to me if it was just the same type of tree that did that lol, give me a sec to start my server up and I will check on that for you :)

**EDIT**
According to UO, the bottom right is ID 3280 (oxCD0) and the top left is ID 3277 (0xCCD), here is another SS of them:
ss (2014-03-29 at 04.05.25.2).jpg

I will also try chopping some of those same trees in another area and see if the same issue occurs.

**EDIT TWO**
Update: The same trees in another area seemed to be removed fine after waiting of course. I suppose this had something to do with me constantly saving it until it changed or something weird lol, I like to break things :p
 
Last edited:
I'll see if I can track that down, it should be removing the stumps of course.
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 think I might know another cause, let me explain and tell me what you think.
Before when I was crashing on save I could still log in and chop trees but then it would just crash on save, perhaps somehow those files were still there when I updated to the version that didn't crash and when I chopped the trees in the same area it somehow messed everything up on the first save?

Whatever the case may be I will of course keep an eye out for this or any other issues and let you know :)
 
Hey Praxiiz, found a issue with this system and the additional maps in UL, if you add map 32 but use a existing map index #, the harvest system causes a fatal error on the directory not accepting 2 of the same map ids. Making a copy of said map in the client and not using another maps ID solves the issue!

Suspected line of code causing problem :
Code:
 public static Dictionary<int, Dictionary<Point3D, int>> RegrowthMasterLookupTable = new Dictionary<int, Dictionary<Point3D, int>>();
 
tileID = (obj.ItemID & 0x3FFF) | 0x4000;

Wondering if anyone has successfully expanded the usable tiles for Harvesting past the end of the ML clients (as indicated above)? If so, would you mind sharing what those hex's are?

Edit: I've tried removing the hex limitation altogether, expanding it to the file end of HS clients (0xFFFF), and also to the last usable item art slot which to my understanding is 0xBFFE. None of the above work (all compile fine, it just doesn't let you chop them).

There are world art packets for both the SA and HS clients which indicate art usage well past the above limitations (0x7FFF for SA and 0xFFFF for HS), which I thought was promising. Nope.

Again, any light shed on this would be great since 99% of my custom tree art occurs past the 0x3FFF/0x4000 mark, and only being able to interact with a few trees out of them all seems silly.
 
Last edited:
I'm not in front of any code at the moment, but if memory serves me right, I thought it had something to do with the targeting. You might check the packet and targeting class being used, and as a last resort target something out of range and capture the packet.
 
I bet its still using the old item packet then. I'll have a look, but won't be for a bit. Had to plop a new hard disk into my tower and reinstall windows tonight. Have to download everything fresh from external and dropbox...bleh.

Thanks for the hint.
 
No luck on my end with expanding the item usage limit past the ML client range.

Hopefully someone else might have better luck.
 
Excellent work on this one, and I've got it installed and running on my test shard. I'm sure I've got some work to do to fully integrate it and I've noticed an issue on my end. Every time I chop a tree I successfully knock the leaves off but then can't do anything past that, nor harvest any wood. Has anyone else run into this issue and, if so, what was your fix?
 
So I implemented the system on a custom map. It worked beautifully until I had a server error and had to revert to a back-up, now the system only works intermitently or not at all, depending on the tree location. Is there something I need to do when I use a server back-up to make this system work again?
 
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. :(
 
@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?
 
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. :(

Problem Solved.
I removed the UltimaLive Lumber Overhaul from my server, booted it up and then saved. I then REINSTALLED it and it worked fine. I posted here hoping to bypass a trial and error session, but sometimes thats unavoidable. Besides, its good to get your blood pressure up now and then. :)
 
"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?

At this point no, however there is good news... The support for .uop files is in the project however the project is written mostly in C++ (.dll side) and most people on here probably don't know how to use that language. From what I've been told the .uop support just needs to be tested and cleaned up in order for it to work. You all have the source; feel free to make adjustments to Ultima Live and repost them on this thread so other people can benefit from your work.

My own schedule is really busy. I have been taking a 1on1 online course 3-4 hours a day 5 days a week, plus homework, in software engineering. It's fairly complex and none of it really has to do with UO emulation; though C++ is the core of the course and knowing that has given me a broader insight into C#. I am working on re-creating UOLandscaper under a different name as an open source project sdk. I'll be releasing that as soon as I fix the bugs and clean up the code a bit.
 
Everything is a stepping stone and like Bob Wiley (Bill Murray) in the movie What About Bob?... I'm taking Baby Steps...

Ultima Live, while easy to use and configure for the most part, is relatively complex on the back end. It requires knowledge of C++ and I'm just learning C++ as one of my core courses; now knowing that mathematics is my most dreaded subject in the world, it's taking me time to learn how to overcome that handicap and become the best programmer I can be :) I'm not just taking the courses to say hey look at me, I'm actually trying to learn something and maybe use those skills to (1) improve things in our community and (2) maybe one day build my own mmorpg ;)

I would love nothing more than to submit more systems to ServUO and RunUO, however the systems I want to start work on are very complex; ie. I'd like to rebuild a weather system/ environmental system that can be controlled effectively by region without the bugs or lag. I'm also looking into creating a new client, which my instructor said might be a future project in my course. It all depends on time and how much information we cover. He is a senior software engineer at a local gaming company which has built popular mmo's in the past so I don't think he's going to have much of an issue helping me create an engine similar to UO that is open source, legal, and free to operate and play.

As with everything, help is appreciated :) I will continue to support Ultima Live and other projects, but if people have ideas and can implement them then please do so. I also encourage anyone who is serious about contributing to my various project ideas to contact me and add me to their Skype. I don't mind doing the actual programming; I might need help here and there, I may ask a lot of questions, but I'm not above moving things along in the right direction because everything is an educational process and I'm trying to learn as much as I can. What I don't want is to give people the impression that I am a programming genius... I haven't reached that pinnacle and probably wont for another 10-15+ years ;)

I'm just a guy, who doesn't work (so I have a lot of time on my hands), has resources, and is trying to utilize those resources to further along his hobby. I want to contribute this community which has been a huge part of my life for the last 6-7 years, help troubleshoot issues for people who might be having issues that one day I'll be able to fix like some of you more experienced guys have been doing for the rest of us all of these years, and maybe provide inspiration to a lot of you; I'm seeing productivity dwindle and people becoming less active and I want to see that change :)
 
Last edited:
If you need any help with ideas or a sounding board or even when the time comes play testing, let me know. I have a lot of really good ideas but lack the programming skills to see them to fruition. I try, I spent the last 5 years trying to turn various other games into UO variants for fun, I even started building my own business RTS called Entrepeneur. In a city, you build factories, wherehouses and office buildings, in order to do R&D and manufacture goods and manage the supply line all against a backdrop of consumer demand, national economy and random events that alter your production schedule. I had the game all laid out with working formula's custom art and everything, when it came time to program it, I got frustrated and shelved it. It makes a great table-top game....kinda. :) Programming is as much art as it is science, I have the science of it down, but my programs never seem to come out quite right. I acknowledge my limits, but if I can contribute the font of wealth I have bouncing around with my brain cells to someone who has the ability to realized them in bytes, I'm all aboard.

Edit: I also had an idea to remove the stumps from the Lumber Overhaul. What if a specialized tool (StumpShovel.cs) was created that made a call to the [delstatic operation but only on the condition that the static holds the Stump ID? Then it could only be used to delete stumps.
 
Ok, so I have been looking at the scripts for UL Lumber, specifically LumberHarvest.cs. I've found the portion where the call is made to update the harvest phase of the static, my thought is to use the state of the static to identify the static for removal, or should I look to see about just clearing ANY statics from the tile on call? Here is where I'm thinking I should start trying to edit the code:


Code:
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);
 
}
}
}
}
}

So how badly will this screw things up if it would even work at all?
 
Last edited:
@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?

If I was in a position to troubleshoot this, I would begin by looking at the target packet format that the client uses. I would then look into using a different target cursor for getting the item id. Maybe something with a regular static target would work. Then I'd look through the harvest system and see if there was anything specific to the type of target they're calling or the callback they're using.

It may not be anything specific to the client, and could be all server side. If it is a specific client packet that is being used, you could probably use a different target cursor to accomplish the same thing. If you think about it, you can already click on statics that are above that range with the static commands that come with UL. A good place to start would be to modify the lumber system to use that type of target.

I wish I could be more help.
 
Thanks Praxiiz, yeah I was thinking along those same lines. Using the delete static command is already in UltimaLive it should be easy to put a call in to the public variable for "delstatic". I haven't tried it yet but I'll post an update once I do.
 
Deforestation ?

( as far as I can see, beat me if I'm wrong^^ )

All saved cutted trees wont respawn on reboot.

Cause it seems that "deserialize" method doesn't work, as the binaries readers are called in that loop : (OnLoad line 87)
Code:
for (int mapId = 0; mapId < RegrowthMasterLookupTable.Count; ++mapId)

where RegrowthMasterLookupTable.Count==0 :confused:

Cause of its assignation in Configure :
Code:
 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);
    }

Where Map.AllMaps not already assigned...

Cause Main call configure first, and then WorldLoad...

For my part I move it in OnLoad :
Code:
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)
			{...

[Edit]
Map.AllMaps is assigned during Configure too...

Maybe just after LumberHarvest?

I'm always on RunUO...

But the fact is that AllMaps.Count==0...
 
Last edited:
:( Yes, I realized that when I started to try and institute it. I'm doing a rework on my plan. Perhaps making it so that the stumps can only be removed on purchased property? I also had the idea of changing the requirements of wooden constructed items to only use boards, then requiring that logs be taken to a sawmill to be turned into boards. The added effort might stop random deforesting, it would also make it a little more realistic.....I don't mind a certain amount of deforestation, it will spur city growth. Plus being in the "southwest to midwest" there will be wide open plains and desert to build cities and houses. I'm hoping by setting up realistic scenarios as far as settling and the work involved will lead to realistic town development. I'm not sure though, still trying to figure out some of the details of the world. I wan't to make it as authentic as possible while not requiring a ridiculous amount of work for very little reward.
 
i get this error:
----------------------------------------------------------------------------
ServUO - [http://www.servuo.com] Version 0.5, Build 5658.25009
Publish 54
Core: Optimizing for 8 64-bit processors
RandomImpl: CSPRandom (Software)
OpenUO Error: Client files not found.
Scripts: Compiling C# scripts...done (cached)
Scripts: Skipping VB.NET Scripts...done (use -vb to enable)
Scripts: Verifying...
Finished (4996 items, 1016 mobiles, 11 customs) (1,30 seconds)
Error:
System.Reflection.TargetInvocationException: Se produjo una excepción en el dest
ino de la invocación. ---> System.ArgumentException: Ya se agregó un elemento co
n la misma clave.
en System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boo
lean add)
en Server.Engines.Harvest.UltimaLiveLumberjacking.Configure()
--- Fin del seguimiento de la pila de la excepción interna ---
en System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments,
Signature sig, Boolean constructor)
en System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Objec
t[] parameters, Object[] arguments)
en System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
en Server.ScriptCompiler.Invoke(String method)
en Server.Core.Main(String[] args)
This exception is fatal, press return to exit
----

any know the reason?
 
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)
 
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)
Hahaha, sorry!!!
 
This is a great script, I applyed it without any trouble installing both ultima97 and this addon and everything is fine, I copyed the Igrping_0_97.dll to client folder also.

Frankly I didnt expected I would be able to implement this system with so ease thanks to instructions provided.

I have only one issue: with EC which is the dll that needs to be changed?
 
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:
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;
    }
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.

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?
 
Last edited:
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:
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;
    }
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.

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?


ya i am having the same issue i am trying to find where it calls a check for the new log types but can't seem to find a proper check for it myself
@Praxiiz if you got any idea's on this can u let us know please
 
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.
 
@Praxiiz Okay ty, was wondering cause i went and without the lumber harvest in evry say 1 out of 5 tree's would automatically get a different type of log thats in the game now, but with the lumber harvest system i went threw 75 tree's (tried diff area's) and only ever got normal logs and well want to be able to in time expand the different types of logs/wood in the game but first want to have this working correctly as it seems to only ever use the call for normal logs when chopping down the tree's and i was not really wanting to add in new graphics to the client as i am still not familiar with that as of yet. tried twice and both times failed lol
 
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.


Okay i was just reading over what you had posted once again and i can see that pritty well no matter what i will need to add in the graphics to the clients to allow for the different types or logs, now is there a way to override this so that i do not have to go in and add in the new graphics at all to make it so that it will just randomly choose from the list log types without needing to add in additional graphics??
 
Even if you don't add in new graphics, you just need to define bonus resources for the existing graphics. I think there's a #def in there if you want to use custom graphics, but they aren't needed to add additional resources.
[doublepost=1479016646][/doublepost]Check the growth phases to see how new trees are spawned. When you define your trees (even without custom graphics) there's a way to define which logs are used. I believe its all handled with hues.
 
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
  }
I feel like I'm being daft here :D 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?
Is it possible to add multiple resources to one tree hue (type)? Like
Code:
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)));
would add normal wood and Oak to this particular tree phase with tree hue = 0?
 
Yup, just to confirm: the hue is the hue of the tree.

I'm not sure if I get the code right, though - in ReapResource() in BaseHarvestablePhase.cs there seem to be no chance check when chopping wood - if a character has enough skill for defined resource they will always get it?
 
Back