Resource icon

Ultima Odyssey 2019-03-12

No permission to download

Djeryv

Well-Known Member
Oct 2, 2014
419
84
Sounds like a neat idea.

I think they come from Initializer.cs. I see the numbers match up. Add one and find out.

If it works, maybe you want to add to the book text below so players know the new spell recipes.
 
Last edited:

FaceMelter

Well-Known Member
May 31, 2014
80
6
38
Shard Name
Altima
Since many of the power words match up, I should be able to add everything in Necromancy and Mysticism, though I don't believe Mystic magic is part of this core as it's older. Spell weaving is though, so I may be able to add the effects of the spells with new power words.

Looking at Initializer.cs everything is spelled out for me, so all I have to do is add the associations! I've got some typing to do.

Now, I only started looking into rune magic because of a Rune Dragon that I found.... He only dropped the bag though. Without any spoilers, do the runes drop somewhere by default? Or do I need to add them to the loot table to get the runes? A yes or no answer is fine.

I just need to know if I need to add these to drop.

*Edit*
Looks like it's working just fine! I'll have to do some testing, but it's looking like it's working as intended! I've attached the RuneMagic.cs file for those who would like to let Necromancer's use the system.

I'm going to continue to add types of magic to it and see where it goes. So far, it seems that so long as the spell is in Initializer.cs and you associate a power word to it, it works. Very easy to add new rune combos. Even got some Bushido spells to work with it. Come to think of it, it's also possible to just make new runes with this too if necessary.
 

Attachments

Last edited:

Djeryv

Well-Known Member
Oct 2, 2014
419
84
I remember "not" telling players the combinations in the book so they had to mix and match on their own. That is why you can write in the actual book if you find it. That is a bit of a "duh" moment on my part because I just took your script for myself. When I read over the actual book section, it only describes about 3 combinations to get the players thinking about more.

Now...I noticed only 2 creatures drop runic stuff using the RandomRuneMagic() function which is this list...

C#:
private static Type[] m_RuneMagic = new Type[]
    {
        typeof( RuneMagicBook ),    typeof( Runebook ),        typeof( RuneBag ),        typeof( RecallRune),
        typeof( An ),                typeof( Bet ),            typeof( Corp ),            typeof( Des ),            typeof( Ex ),     
        typeof( Flam ),                typeof( Grav ),            typeof( Hur ),            typeof( In ),            typeof( Jux ),            typeof( Kal ),     
        typeof( Lor ),                typeof( Mani ),            typeof( Nox ),            typeof( Ort ),            typeof( Por ),            typeof( Quas ),     
        typeof( Rel ),                typeof( Sanct ),        typeof( Tym ),            typeof( Uus ),            typeof( Vas ),            typeof( Wis ),     
        typeof( Xen ),                typeof( Ylem ),            typeof( Zu ) 
    };

public static Type[] RuneMagic{ get{ return m_RuneMagic; } }

public static Item RandomRuneMagic()
{
    return Construct( m_RuneMagic );
}
These are Runic Dragons and Runic Golems. So to expand onto it (which I did today) was to add this around line 360 in ContainerFunctions.cs

C#:
if ( iRich > Utility.Random( 1000 ) && IgnoreThisFiller != 2 )
{
    box.DropItem( Server.Items.DungeonLoot.RandomRuneMagic() );
}
I then changed this section at line 446 in DropRelic.cs so only wizard-type monsters would have about a 5% to drop this stuff...

C#:
SlayerEntry wizardrykiller = SlayerGroup.GetEntryByName( SlayerName.WizardSlayer );
if ( wizardrykiller.Slays(from) )
{
    if ( Utility.Random( 4 ) == 1 )
    {
        if ( DifficultyLevel.GetUnidentifiedChance() >= Utility.RandomMinMax( 1, 100 ) ){ Item wand = new UnknownWand(); c.DropItem(wand); }
        else{ Item wand = Loot.RandomWand(); Server.Misc.MaterialInfo.ColorMetal( wand, 0 ); string wandOwner = ""; if ( Utility.RandomMinMax( 1, 3 ) == 1 ){ wandOwner = Server.LootPackEntry.MagicWandOwner() + " "; } wand.Name = wandOwner + wand.Name; c.DropItem(wand); }
    }

    if ( Utility.Random( 20 ) == 1 )
    {
        c.DropItem( Server.Items.DungeonLoot.RandomRuneMagic() );
    }
}
Thanks for the necro adds, but be aware that someone needs to be good at necromancy to cast those spells. I kept it that way as not to ruin the magery skill for example. You need the skill but you don't need the reagents and such. Really, I mainly have it in the game because it hearkens back to the Ultima Underworld spell casting system. Also keep in mind that if someone GMs magery and necromancy...and they set their skill title to either one of those...their title actually becomes Grandmaster Archmage.

So if you add the Spellweaving spells (as an example) make sure you edit those so they don't need the Spellweaving skill because it doesn't exist.
 
Last edited:

FaceMelter

Well-Known Member
May 31, 2014
80
6
38
Shard Name
Altima
Awesome!
So If I wanted certain power words to not check a skill level, I'd just have to go into that spell and remove the skill check. Nice.

I may expand upon this system a little bit with custom runes and spells. The only thing I'd like to do is change the way you interact with the Rune Bag.

I'd like to make it so that to cast the spell, you double click the bag, and to open it use the context menu.

I'm familiar with override on doubleclick, but I'm not familiar with context menus at all.

Since there are going to be many rune bags and runes around, I'd like to have a few bags set up with spells, and then just have to double click them for ease of use.

would it be tough to switch the functions on the bag?

Also, thanks for all of the help! I know everyone has a vision of what they want to play, and that often our visions differ greatly. So I appreciate you taking the time to support!
 

Djeryv

Well-Known Member
Oct 2, 2014
419
84
I just took your idea and changed my bag to do that. I have to single click to open it but double click it to cast.

I even changed the text in the book to mention that you have to do these things with the single and double clicks.

ALSO: It would be a cool idea to add spells that are ONLY available through the rune bag system. It just adds a bit of flavor for a spellcaster character. There are many rune graphics available in the game but I think I used many of them. There are 29 in total if you have Fiddler you can see them. But 29 is alot where you can use hues to differentiate them after that.
 

Attachments

Last edited:

FaceMelter

Well-Known Member
May 31, 2014
80
6
38
Shard Name
Altima
Yeah, I was going to just hue them differently. But that's the direction that I was going with it!

Thanks for updating the bag!
 

Violet Joy

Member
Sep 29, 2018
10
3
Issue with 'Coldhall Depths' starter dungeon. Sparklies at (2716, 3540, 0) teleports you inside the structure of 'Stonewall' at (1824, 760, 20). Rather unpleasant when you are a player without recall, since the entire room is black-floored (and cannot move around).
 

Djeryv

Well-Known Member
Oct 2, 2014
419
84
Open CreateTreasureChests.cs and delete these 3 lines...

2936
2935
2934

...which place treasure chests at these coordinates...

1827,758,0
1825,756,0
1824,761,0

These exist because a long time ago you could walk into the building itself before it became a public region so these three chests are useless now.

Then open up this file...

C:\UO\Data\Decoration\Sosaria\decorate.cfg

Find line 2446

Replace that teleporter with these two. They just lead back and forth between two starter dungeons. I just picked them on a whim and thought it would be a fun secret to move back and forth between the island and the mainland.

Code:
Teleporter 7107 (PointDest=(2393, 3253, 0); MapDest=Trammel; Creatures=False; SourceEffect=False; DestEffect=False; SoundID=509; Delay=00:00:00)
2716 3540 0

Teleporter 7107 (PointDest=(2716, 3540, 0); MapDest=Trammel; Creatures=False; SourceEffect=False; DestEffect=False; SoundID=509; Delay=00:00:00)
2393 3253 0
...then reboot the server and do a [buildworld command. Then this little mess will be cleaned up.

Also remember that the "I am stuck" option in HELP does work...in case you play in a multi-player environment and another character gets stuck with no admin online to help. Meaning that they don't need recall spells to get out of such a jam if something similar happens in the future. It is possible to happen accidentally like the teleport trap. It finds some random land tile in the world and throws the character at that spot. If they happen to be thrown onto a land tile that is oddly placed in some mountain (as a made up example) they can get free using the HELP option.
 
Last edited:

Violet Joy

Member
Sep 29, 2018
10
3
Made this for solo or lan playing. I play solo. It initiates world save.
Drop into Scripts folder (Mine's in 'Scripts\Server\Commands' folder)
Command is AccessLevel.Player: [playersave
Post automatically merged:

Tome of Relics (got from Volturnus Ruler of the Waves)... I click on any of the trinkets, and none reward me, but the book/charges do not get consumed.
 

Attachments

Last edited:

Djeryv

Well-Known Member
Oct 2, 2014
419
84
Tome of Relics (got from Volturnus Ruler of the Waves)... I click on any of the trinkets, and none reward me, but the book/charges do not get consumed.
These two files will fix that issue. I had the counts wrong for the number of items available so the talismans and torch were at the bottom of this list and would never get picked. I tested it by killing Talos and I got a torch as that is what I picked.
 

Attachments

Djeryv

Well-Known Member
Oct 2, 2014
419
84
I have newer appearing runebooks in this game, but I also wanted the classic look to appear when searching treasure. I had a flaw in the script that sometimes made the runebook look like the bard song book so just change the line in the file below. Again, it is just cosmetic but you won't find any of the newer style runebooks with the partial hues...

ContainerFunctions.cs Line 309

else if ( idropped is Runebook ){ idropped.ItemID = Utility.RandomList( 0x22C5, 0x0F3D ); }
 

Djeryv

Well-Known Member
Oct 2, 2014
419
84
Although these sharpening stones "work", their message sending design was flawed. They would tell you that you can only sharpen edged weapons when in fact you targeted one but it wasn't in your pack. So I cleaned up this stuff so if someone uses them they will not have to fuddle with these vague messages and have a clearer look on what they need to do to sharpen weapons. So just replace your files with these.

I also changed the color palette for the new metal armor colors (not the classic) because they looked strange when you get royal armor or chaos shields (for example). I only changed a few like dull copper, verite, etc. If you replace your Materials.cs with this one. Anything already colored will not be updated by this. Just future items made of some of these metals.
 

Attachments

Last edited:

Joshua

Well-Known Member
Sep 13, 2014
591
74
34
Bountiful, Utah
Shard Name
My Own Shard
Although these sharpening stones "work", their message sending design was flawed. They would tell you that you can only sharpen edged weapons when in fact you targeted one but it wasn't in your pack. So I cleaned up this stuff so if someone uses them they will not have to fuddle with these vague messages and have a clearer look on what they need to do to sharpen weapons. So just replace your files with these.

I also changed the color palette for the new metal armor colors (not the classic) because they looked strange when you get royal armor or chaos shields (for example). I only changed a few like dull copper, verite, etc. If you replace your Materials.cs with this one. Anything already colored will not be updated by this. Just future items made of some of these metals.
Are you by chance updating your main download as you update the files mentioned?
 

zerodowned

Moderator
ServUO Developer
Jun 28, 2014
1,770
221
Just wondering if this features a Pause type system? Since it's more geared toward single player.
I've scripted a Pause feature myself but not sure how drag/drop it would be without a little tweaking.

C#:
using System;
using System.Collections;
using Server;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Regions;
using Server.Engines.CannedEvil;
using Server.Items;
using System.Xml;
using Server.Commands;
using Server.Network;
using Server.Gumps;
using Server.Engines.XmlSpawner2;


// This allows players to Pause in most situations. It will prevent them from moving and disable combat mode. It also hides the player so that other players can't "camp" them.
// Note: Several changes have been made since the original release. This is now an Xml attachment, and is no longer based on the AFK script.


namespace Server.Engines.XmlSpawner2
{
  
   public class Pause : XmlAttachment
   {
      
      private bool mPaused;
      private bool mCanPause = true;
        
        [CommandProperty(AccessLevel.GameMaster)]
        public bool Paused
        {
            get { return mPaused; }
            set { mPaused = value;  }
        }
        
        [CommandProperty(AccessLevel.GameMaster)]
        public bool CanPause
        {
            get { return mCanPause; }
            set { mCanPause = value;  }
        }
    

      public static void Initialize()
      {
         CommandSystem.Register( "pause", AccessLevel.Player, new CommandEventHandler( Pause_OnCommand ) );
         EventSink.Login += new LoginEventHandler( OnLogin );
         EventSink.CharacterCreated += new CharacterCreatedEventHandler(EventSink_CharacterCreated);
      }

      public static void OnLogin( LoginEventArgs e )
      {
         Pause pauseatt = (Pause)XmlAttach.FindAttachment(e.Mobile, typeof(Pause));
        
          if ( pauseatt == null )
            {
                XmlAttach.AttachTo(e.Mobile, new Pause());
                
                return;
            
            }
        
        if ( pauseatt.Paused == true )
        {
            e.Mobile.SendGump( new Pausegump( e.Mobile) );
            e.Mobile.Blessed = true;
            e.Mobile.Hidden = true;
            e.Mobile.Paralyzed = true;
            e.Mobile.Frozen = true;
        }
 
      }
      
      private static void EventSink_CharacterCreated(CharacterCreatedEventArgs e)
        {
             Pause pauseatt = (Pause)XmlAttach.FindAttachment(e.Mobile, typeof(Pause));
        
          if ( pauseatt == null )
            {
                XmlAttach.AttachTo(e.Mobile, new Pause());
                
                return;
            
            }
        }
      
      
       [Usage("Pause")]
        [Description("Pauses your character")]
      public static void Pause_OnCommand( CommandEventArgs e )
      {
         Pause pauseatt = (Pause)XmlAttach.FindAttachment(e.Mobile, typeof(Pause));
        
         if ( pauseatt == null )
            {
                XmlAttach.AttachTo(e.Mobile, new Pause());
                
                return;
            
            }
        
            if ( pauseatt.Paused == true )
            {
                pauseatt.Paused = false;
                e.Mobile.Hidden = false;
                e.Mobile.Paralyzed = false;
                e.Mobile.Frozen = false;
                e.Mobile.Blessed = false;
                
                if (e.Mobile.HasGump(typeof(Pausegump)) );
                {
                    e.Mobile.CloseGump(typeof(Pausegump));
                }
            
                
                PlayerMobile pm = (PlayerMobile)e.Mobile;
                ((PlayerMobile)pm).ClaimAutoStabledPets();
                
             }
            
             else
             {
                // region check only requires player to be about 30 steps away from the altar. this still puts them too close to the altar and could allow players to "steal" a champion spawn from another player. so I've used range check instead.
                    //if (e.Mobile.Region.IsPartOf(typeof(ChampionSpawnRegion)) )
                foreach ( Item item in e.Mobile.GetItemsInRange( 50 ) ) // 50 = range.
                {
                    if ( item is ChampionAltar  )
                    {
                        // if you change the range above or if you use Region check instead of range, you'll want to change the message below
                        e.Mobile.SendMessage( "You must be more than 50 steps away from the Champion's altar to use Pause." );
                        return;
                    }
                }
                // prevents players from using pause if they're paralyzed, frozen, holding a faction sigil, "holding" a spell target, in the middle of casting a spell, or currently attacking something.
                
                if( e.Mobile.Paralyzed == true || e.Mobile.Frozen == true || Factions.Sigil.ExistsOn( e.Mobile ) || Server.Spells.SpellHelper.CheckCombat( e.Mobile ) || e.Mobile.Spell != null || e.Mobile.Combatant != null )
                {
                  e.Mobile.SendMessage( "You cannot pause at this time." );
                  return;
                }
                
                 if (e.Mobile is PlayerMobile && (e.Mobile as PlayerMobile).DuelContext != null)
                {
                    e.Mobile.SendMessage( "You cannot pause while duelling!" );
                    return;
                
                }
                if ( e.Mobile.Region.IsPartOf(typeof(Engines.ConPVP.SafeZone) ) )
                {
                    e.Mobile.SendMessage( "You cannot pause while duelling!" );
                    return;
                }
                if ( pauseatt.CanPause == false )
                {
                    e.Mobile.SendMessage( "Your ability to Pause has been deactivated." );
                    return;
                }
                
                pauseatt.Paused = true;
                e.Mobile.Hidden = true;
                e.Mobile.Paralyzed = true;
                e.Mobile.Frozen = true;
                e.Mobile.Warmode = false;
                e.Mobile.Blessed = true;
                
                e.Mobile.SendGump( new Pausegump( e.Mobile) );
                
                PlayerMobile pm = (PlayerMobile)e.Mobile;
            
                if (((!pm.Mounted || (pm.Mount != null && pm.Mount is EtherealMount)) && (pm.AllFollowers.Count > pm.AutoStabled.Count)) || (pm.Mounted && (pm.AllFollowers.Count > (pm.AutoStabled.Count + 1))))
                    {
                        pm.AutoStablePets(); /* autostable checks summons, et al: no need here */
                    }
                    
                for (int i = pm.AllFollowers.Count - 1; i >= 0; --i)
                {
                    BaseCreature pet = pm.AllFollowers[i] as BaseCreature;
                    if (pet.Summoned)
                        {
                            //if (pet.Map != Map)
                            //{
                                pet.PlaySound(pet.GetAngerSound());
                                Timer.DelayCall(TimeSpan.Zero, pet.Delete);
                            //}
                            
                        }
                }
             }
            
        
      }
      
      
      public Pause( ASerial serial ) : base( serial )
        {
        }
        
        [Attachable]
        public Pause()
        {
        }
        
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
            writer.Write( (int) 0 ); // version
            
            writer.Write(mPaused);
            writer.Write(mCanPause);
        }
        
         public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
            int version = reader.ReadInt();
            
            mPaused = reader.ReadBool();
            mCanPause = reader.ReadBool();
        
        }
        
   }
}


namespace Server.Gumps
{
    public class Pausegump : Gump
    {
    
        
        
        public Pausegump(Mobile from) : base(200, 200)
        {
            
        
            Closable=false;
            Disposable=false;
            Dragable=false;
            Resizable=false;
            
            AddPage(0);
            
            AddBackground(0, 0, 625, 450, 2600);
            
            AddHtml( 49, 46, 525, 306, @"<BASEFONT SIZE=5><div align=center>Your character has been paused</BASEFONT><br><br><div align=left>Any pets have been stabled and any summons have been dispelled.<br><br>You cannot be seen or harmed while paused. <br><br>When you are ready to continue playing use the command [pause again or press the button below.", (bool)true, (bool)false);
            
            AddButton(55, 373, 247, 248, 1, GumpButtonType.Reply, 0);
            AddLabel(122, 373, 1153, @"I am ready to continue playing");
        }

        
        public override void OnResponse( NetState sender, RelayInfo info )
        {
            Mobile from = sender.Mobile;
            
            Pause pauseatt = (Pause)XmlAttach.FindAttachment(from, typeof(Pause));
            
            switch(info.ButtonID)
            {
                case 0:
                {
                    from.CloseGump( typeof( Pausegump ) );     
                    break;
                }
            
                case 1:
                {
                    
                    from.CloseGump( typeof( Pausegump ) );     
                    
                    if( pauseatt.Paused == true )
                    {
                        pauseatt.Paused = false;
                        from.Hidden = false;
                        from.Paralyzed = false;
                        from.Frozen = false;
                        from.Blessed = false;
                        
                        from.SendMessage( "Pause deactivated." );
                        
                        PlayerMobile pm = (PlayerMobile)from;
                        ((PlayerMobile)pm).ClaimAutoStabledPets();
                    }
                    break;
                    
                    
                }
                
                
            }
        }
    }
}
 
  • Like
Reactions: TheDoc

Djeryv

Well-Known Member
Oct 2, 2014
419
84
To fix a secret door color to match the wall: On line 11061 of Data\Decoration\Lodor\decorate.cfg...change the hue to 2500

To fix a book from having the wrong title: On line 992 of DynamicBook.cs...change...

Name = BookTitle;

...to...

BookTitle = "The Golden Rangers";
Name = BookTitle;


To remove a rogue spawner of a Chaos Shield, open Data\Monsters\dangers.map and delete it at line 3563.
 
Last edited:

Djeryv

Well-Known Member
Oct 2, 2014
419
84
I would suggest opening BaseCreature.cs and change the mummy wrap breath attack to the 5 seconds shown below. I ran into a situation where the time between moving and attack were neck and neck and I was at a stalemate.

C#:
else if ( form == 37 ) // MUMMY WRAP ----------------------------------------------------------------------------------------------------
{
    Point3D wrapped = new Point3D( ( target.X ), ( target.Y ), (target.Z+2) );
    Effects.SendLocationEffect( wrapped, target.Map, 0x23AF, 30, 10, 0, 0 );
    target.PlaySound( 0x5D2 );
    target.Paralyze( TimeSpan.FromSeconds( 5.0 ) );
}
 

Wanderer

Well-Known Member
Apr 18, 2019
148
5
Hi Djeryv, having a blast playing Odyssey, really awesome project! Thanks for releasing it, it is a lot of fun to play. I searched the forums and on both Odyssey and Dawn of Ultima postings, but I could not find some info. The loot system is most excellent, a lot of interesting gear to be found in this game, the variety is awesome! However, all the vendors I have found so far buy very little of the generated loot, am I missing a specific vendor to unload some of the loot I find? Also, I tried using the map for plotting a course for a boat, but the map is only a partial map, showing only the left part of the map. I tried DM item generated worldmap, and a GM skill level created map, both only show the left side of the map. The other world map shows the entire map, but I cannot plot a course on it. Other than that, this is an outstanding game! I appreciate all the effort and time you put into this. Hail!
 

PyrO

Well-Known Member
Jan 27, 2015
1,167
95
Regarding your selling to npcs, the npcs only buy certain items, but those may change after a while. It is random what they actually buy, some items though dont get bought at all if I saw it right ;)
 

Djeryv

Well-Known Member
Oct 2, 2014
419
84
all the vendors I have found so far buy very little of the generated loot, am I missing a specific vendor to unload some of the loot I find?
Many decorative treasure items (like clocks, rugs, vases, statues, cloth, leather, etc) are not sellable to vendors. If you use Item ID on them, you may find out what it is worth and to what type of merchant. So if something is worth 200 gold to a mage, give the item to a mage and they will give you 200 gold. This is explained in the skills section, that describes the skills in the game.

Also, I tried using the map for plotting a course for a boat, but the map is only a partial map, showing only the left part of the map. I tried DM item generated worldmap, and a GM skill level created map, both only show the left side of the map. The other world map shows the entire map, but I cannot plot a course on it.
There are "world maps" in the game and they are just a map gump showing the entire land. The UO cartography system does not provide a way to give you an entire map of a world because they can only be so big...so I added these world maps. Then you have the cartography maps where I renamed world maps to "huge". So if you can plot a map course (it will show the PLOT COURSE on the top) do that and close the map. Then drop the map on the tillerman where he will say "a map". The map will appear in your pack again. Say "start" and he will sail on that course. I never included instructions for this in-game because it is standard UO boat stuff...in hindsight...I should have (or still should).