Humzie

Citizen
I would like to get this running on my project and we are using RunUO 2.7 - anyone come across these errors below(attachment)?
 

Attachments

  • unknown.png
    unknown.png
    46.3 KB · Views: 13

tass23

Moderator
I was able to get this system working on my old core, which is not running the latest DotNet framework, which is also half the problem people with older cores are having. Some coding changes in versions make merging the EventSinks problematic. The two that cause issue here are
=> and { get; }.
DotNet version code changes:
=> also equals { get { return X; } } -> for example { get { return m_From; } }
{ get; } also equals { get; private set; } -> for example public Mobile Harvester { get; private set; }

The other half is related to EventSinks added in the ServUO repos that are not in the older 'shard Server->EventSink.cs file. These can be merged into an older EventSink.cs, but the calls to the EventSinks must still be added into the Scripts. Whereas ServUO repos have the code already in place for the new EventSinks.

An EventSink is when something specific occurs in-game, like successfully crafting an item, or logging it and out. Newer versions of ServUO repos have more EventSinks added, which means not only merging in the data from EventSink.cs, but also looking in the Scripts folder to merge the Distro calls for the new EventSinks.

Guide to installing Mythik Achievement System to a 'shard core running DotNet < 4.8, using ServUO Pub 57 repo as a foundation:
1. The Server folder contains the EventSink.cs file. Open both EventSink.cs files "side-by-side", using a program such as WinMerge. Sometimes the merges are nice and clean, but if the EventSink is much older, the merge might be a lot more complex, so in the event of a messy merge, use Notepad++ to open both files and then copy/paste entire sections of code from ServUO's repo into the older core. Note the version code changes mentioned above!

2. If you do not have the Playermobile edits, you will have to use the define STOREITEM <--- This is what creates the AchievementSystemMemoryStone in the next step.
Drag/Drop Mythik Achievement System into Scripts->Customs and then open AchievementSystem.cs and remove the // at the very top from define STOREITEM and make the following changes to "force" the system to use the stone.
Scroll down a few lines and add // to the lines that say:
```
//#if STOREONITEM
//#else
//using Scripts.Mythik.Mobiles;
//#endif

#if STOREONITEM
if (!AchievementSystemMemoryStone.GetInstance().Achievements.ContainsKey(player.Serial))
AchievementSystemMemoryStone.GetInstance().Achievements.Add(player.Serial, new Dictionary<int, AchieveData>());
var achieves = AchievementSystemMemoryStone.GetInstance().Achievements[player.Serial];
var total = AchievementSystemMemoryStone.GetInstance().GetPlayerPointsTotal(player);
//#else
//var achieves = (player as MythikPlayerMobile).Achievements;
//var total = (player as MythikPlayerMobile).AchievementPointsTotal;
#endif

#if STOREONITEM
if (!AchievementSystemMemoryStone.GetInstance().Achievements.ContainsKey(player.Serial))
AchievementSystemMemoryStone.GetInstance().Achievements.Add(player.Serial, new Dictionary<int, AchieveData>());
var achieves = AchievementSystemMemoryStone.GetInstance().Achievements[player.Serial];
//#else
//var achieves = (player as MythikPlayerMobile).Achievements;
#endif
```

3. Next open AchievementSystemMemoryStone.cs and at the top where it says:
```
public static AchievementSystemMemoryStone GetInstance()
{
if (m_instance == null)
m_instance = new AchievementSystemMemoryStone();
m_instance.MoveToWorld(new Point3D(0, 0, 0), Map.Felucca); //<----- CHANGE THESE LOCATION COORDS
return m_instance;
}
```
If you do not change these coords, every time a player uses the command Feats, the stone will move to those coordinates. If you move the stone to another location, it will move back. You do not have to change the coords, but the stone will be at 0,0,0 in Felucca, which is the top corner of the ocean on the map.

The system is dependent upon EventSinks, so those need to be added in the proper locations.
4a. For the HarvestSystem.cs file and InvokeResourceHarvestSuccess, those changes are in BonusHarvestResource (bonusItem does not exist outside this method):
```
BonusHarvestResource bonus = def.GetBonusResource();
if ( bonus != null && bonus.Type != null && skillBase >= bonus.ReqSkill )
{
Item bonusItem = Construct( bonus.Type, from );

if ( Give( from, bonusItem, true ) ) //Bonuses always allow placing at feet, even if pack is full irregrdless of def
{
bonus.SendSuccessTo( from );
}
else
{
item.Delete();
}
#region ServUO Pub 57 for Mythik Achievement System
EventSink.InvokeResourceHarvestSuccess(new ResourceHarvestSuccessEventArgs(from, tool, item, bonusItem, this)); //<--- This means every time players harvest a *bonus* resource while mining, it will increase the ore count for the Achievement for that attempt only.
#endregion
}
```
4b. For BaseCreature.cs and InvokeOnKilledBy, those changes are in OnKilledBy:
```
public virtual void OnKilledBy(Mobile mob)
{
#region Mondain's Legacy
if (GivesMinorArtifact && Paragon.CheckArtifactChance(mob, this))
GiveMinorArtifact(mob);
#endregion
#region SA
if (GivesSAArtifact && Paragon.CheckArtifactChance(mob, this))
GiveSAArtifact(mob);
#endregion
#region ServUO Pub 57 Mythik Achievement System
EventSink.InvokeOnKilledBy(new OnKilledByEventArgs(this, mob));
#endregion
}
```
4c. For Server->Region.cs and Invoke OnEnterRegion, those changes are in OnRegionChange:
```
//Region oldR = oldRegion;
//Region newR = newRegion;
#region ServUO Pub 57 Mythik Achievement System
var oldR = oldRegion;
var newR = newRegion;
while (oldR != newR)
{
var oldRChild = oldR != null ? oldR.ChildLevel : -1;
var newRChild = newR != null ? newR.ChildLevel : -1;

if (oldRChild >= newRChild && oldR != null)
{
oldR.OnExit(m);
oldR = oldR.Parent;
}
if (newRChild >= oldRChild && newR != null)
{
newR.OnEnter(m);
EventSink.InvokeOnEnterRegion(new OnEnterRegionEventArgs(m, oldRegion, newR));
newR = newR.Parent;
}
}
#endregion
/*
while ( oldR != newR )
{
int oldRChild = ( oldR != null ? oldR.ChildLevel : -1 );
int newRChild = ( newR != null ? newR.ChildLevel : -1 );

if ( oldRChild >= newRChild )
{
oldR.OnExit( m );
oldR = oldR.Parent;
}

if ( newRChild >= oldRChild )
{
newR.OnEnter( m );
newR = newR.Parent;
}
}
*/
```
4d. For Crafting and Scripts->Services->Craft->CraftItem.cs, those changes are inside CheckSkills->item !=null, which is part of CompleteCraft:
```
if (item != null)...

from.AddToBackpack(item);

#region ServUO Pub 57 Mythik Achievement System
EventSink.InvokeCraftSuccess(new CraftSuccessEventArgs(from, item, tool is Item ? (Item)tool : null));
#endregion

from.PlaySound( 0x57 );
```

5. Editing the AchievementGump:
A good example of the menu structure is more easily noticeable if the code is staggered.
```
Categories.Add(new AchievementCategory(1, 0, "Exploration"));
Categories.Add(new AchievementCategory(2, 1, "Towns"));
Categories.Add(new AchievementCategory(3, 1, "Dungeons"));
Achievements.Add(new DiscoveryAchievement(0, 2, 0x14EB, false, null, "Minoc", "Discover Minoc Township", 5, "Minoc"));
```
The hierarchy is Exploration -> Towns | Dungeons ->Minoc. Notice the integers in the code: 1, 0, Exploration, 2, 1, Towns, 3, 1, Dungeons, 0, 2, Minoc. This is how the menus are connected together. Each Child adopts the Parent's number, so Exploration is the Parent (1), Towns | Dungeons are each a Child and a Parent and inherit from Parent (1) and provide for Child (2) and (3), and Minoc is a Child of Towns (2). If a dungeon is added, it would be a Child of Dungeons (3).

There is limited space vertically on the whole interface, so use that space as wisely as possible by nesting Achievements, but also note that you can only nest so far as well.

Each Achievement is structured in a similar fashion, for example DiscoveryAchievement:
var achieve = new HarvestAchievement(100, 7, 0, false, null, 100, "100 Iron Ore", "Mine up a bonus resource and increase the Iron Ore total to reach the goal.", 5, typeof(IronOre), typeof(Lettuce));
AchievementType(AchieveMentNumber, MenuParent, MenuPosition, itemIcon, HiddenUntilComplete (true/false), Pre-requisite or null, "MenuEntry", "Achievement Title", 5 <- Points earned when completed, typeof(IronOre)<-required object to complete, typeof(Lettuce)<-item awarded when complete.

If linking achievements together, create an entry for each var, increasing the value by +1,var1, var2, var3...then call that var in the next linked achievement, for example:
var achieve = new HarvestAchievement(100, 7, 0, false, null, 100, "100 Iron Ore", "Mine up a bonus resource and increase the Iron Ore total to reach the goal.", 5, typeof(IronOre), typeof(Lettuce));
Achievements.Add(achieve); //<--Entry added for var achieve above
Achievements.Add(new HarvestAchievement(101, 7, 1, false, achieve, 500, "500 Iron Ore", "Mine 500 Iron Ore for each bonus received.", 5, typeof(IronOre), typeof(Peach))); //VAR ^

Hopefully a lot more folks can get this system installed, because DL (darklotus) knocked this out of the park! It is an incredible benefit to any 'shard!
 
Last edited:

Carlos_ar

Citizen
I really like this system. I'm working on adding it to my little home away from home.

There are two things that always stick me... and for some reason I can never puzzle them out quickly as it seems they are different depending on the script.

The line is
UnmoddedLine:
Achievements.Add(new HunterAchievement(1001, 3000, 0x25D1, false, null, 100, "Dragon Slayer", "Slay 100 Dragon", 5, typeof(Dragon)));

I want to give gold as well as an item so with the item it's
StatueModed:
Achievements.Add(new HunterAchievement(1001, 3000, 0x25D1, false, null, 100, "Dragon Slayer", "Slay 100 Dragon", 5, typeof(Dragon), typeof(DragonStatue)));

To add the gold with an amount?
GoldModded:
Achievements.Add(new HunterAchievement(1001, 3000, 0x25D1, false, null, 100, "Dragon Slayer", "Slay 100 Dragon", 5, typeof(Dragon), typeof(DragonStatue), typeof(Gold, 1000)));

I tried that and a few other things, but that's the type of stuff that I get stuck on... that and bypassing the label numbers on things to add my own titles or text.
 

Shazzy

Citizen
This is something that is in the pay releases here so we will have to figure this out as a team !
change "points" to an item across the board
so if your 'points' are gold or a sovereign, whatever, then it just happens with no additional scripting.
have someone work on areas
skills
etc
if we separate the sections our productivity increases!
I'm in, who is with me?!

Shazzy :)
 

Carlos_ar

Citizen
This is something that is in the pay releases here so we will have to figure this out as a team !
change "points" to an item across the board
so if your 'points' are gold or a sovereign, whatever, then it just happens with no additional scripting.
have someone work on areas
skills
etc
if we separate the sections our productivity increases!
I'm in, who is with me?!

Shazzy :)
I'm not sure what you mean, but I am certainly down for anything :)
 

Carlos_ar

Citizen
Still plugging away at this. For whatever reason it seems like these things should be so simple and I'm missing some key in my limited knowledge that isn't letting me see the solution.

Apparently simply calling typeof(DragonStatue) isnt going to work either... Still can't get the Sovereigns to show.

Completely stuck

Heh I've resorted to the only thing I know how to do, and that's to get books on C# and go learn. :) Wish me luck.
 

Carlos_ar

Citizen
Just discovered that this doesn't work. You never get more than the first typeof() item

Achievement Code:
Achievements.Add(new HunterAchievement(1001, 3000, 0x25D1, false, null, 1, "Dragon Slayer", "Slay 100 Dragon", 5, typeof(Dragon), typeof(MonsterStatuette), typeof(HeritageSovereign)));

Trying to grant a dragon statue and 10 sovereigns... cant figure how to do more than 1 sovereign and no matter how I changed the code I couldn't get it to do the dragon statue... this will drop the fiorst statue on the list (the aligator) but no sovereign. If I get rid of the typeof(MonsterStatuette) it will drop the sovereign.