I am a bit stuck with passing enums.
Any help would be greatly appreciated. I'm ripping my hair out :)
I have a UOR/T2A mix shard.
I am tackling the problem of not having lockable internal house doors with separate locks and keys/type of key and I have done the following:

House doors have new properties for the type of key (Gold, Iron etc.), a name for the key and description for the key. These are added to the doors on house creation from a deed.
I have it working apart from the KeyType. Although I have a [props gump showing the KeyType with a drop-down selection list of Gold, Iron, Rusty or Copper, I am having trouble passing this to the door, or anywhere for that matter with errors about converting types. I worked around this on key creation by converting to INT on the pass and back again in the key making method I created called MakeKeys() but it seems very clunky and I am wondering if I have missed the point somewhere. I can't find much useful information on the use of enums.
I am including parts of the pre-existing KeyValue code to show position of my bits in the script. I have also modified RemoveKeys() to remove all keys for each door in the players backpack and bank, not just the front door as default. This works fine as it stands.

BaseDoor.cs:
definitions...
Code:
 private uint m_KeyValue;
 private string HouseKeyName = "";
 private string HouseKeyDescription = "";
 private string m_KeyName = "";
 private string m_KeyDescription = "";
 
 public HouseKeyType m_KeyType;
 public enum HouseKeyType
 {
 Copper = 0x100E,
 Gold  = 0x100F,
 Iron  = 0x1010,
 Rusty  = 0x1013
 }
and the command properties:
Code:
 [CommandProperty( AccessLevel.GameMaster )]
 public uint KeyValue
 {
 get
 {
 return m_KeyValue;
 }
 set
 {
 m_KeyValue = value;
 }
 }
 [CommandProperty( AccessLevel.GameMaster )]
 public HouseKeyType KeyType
 {
 get
 {
 return m_KeyType;
 }
 set
 {
 m_KeyType = value;
 }
 }
 [CommandProperty( AccessLevel.GameMaster )]
 public string KeyDescription
 {
 get
 {
 return m_KeyDescription;
 }
 set
 {
 m_KeyDescription = value;
 }
 }
 [CommandProperty( AccessLevel.GameMaster )]
 public string KeyName
 {
 get
 {
 return m_KeyName;
 }
 set
 {
 m_KeyName = value;
 }
 }
Serialise/Desreialise... Hopefully I created a new version correctly to avoid conflicts with any existing doors. KeyType commented out as it throws the conversion error.
Code:
 public override void Serialize( GenericWriter writer )
 {
 base.Serialize( writer );
 writer.Write( (int) 1 ); // version
 writer.Write( m_KeyValue );
 writer.Write( m_KeyName );
 writer.Write( m_KeyDescription );
// writer.Write( m_KeyType );
 writer.Write( m_Open );
 writer.Write( m_Locked );
 writer.Write( m_OpenedID );
 writer.Write( m_ClosedID );
 writer.Write( m_OpenedSound );
 writer.Write( m_ClosedSound );
 writer.Write( m_Offset );
 writer.Write( m_Link );
 }
 public override void Deserialize( GenericReader reader )
 {
 base.Deserialize( reader );
 int version = reader.ReadInt();
 switch ( version )
 {
 case 0:
 {
 m_KeyValue = reader.ReadUInt();
 m_Open = reader.ReadBool();
 m_Locked = reader.ReadBool();
 m_OpenedID = reader.ReadInt();
 m_ClosedID = reader.ReadInt();
 m_OpenedSound = reader.ReadInt();
 m_ClosedSound = reader.ReadInt();
 m_Offset = reader.ReadPoint3D();
 m_Link = reader.ReadItem() as BaseDoor;
 m_Timer = new InternalTimer( this );
 if ( m_Open )
 m_Timer.Start();
 break;
 }
 case 1:
 {
 m_KeyValue = reader.ReadUInt();
 m_KeyName = reader.ReadString();
 m_KeyDescription = reader.ReadString();
// m_KeyType = reader.ReadEnum();
 m_Open = reader.ReadBool();
 m_Locked = reader.ReadBool();
 m_OpenedID = reader.ReadInt();
 m_ClosedID = reader.ReadInt();
 m_OpenedSound = reader.ReadInt();
 m_ClosedSound = reader.ReadInt();
 m_Offset = reader.ReadPoint3D();
 m_Link = reader.ReadItem() as BaseDoor;
 m_Timer = new InternalTimer( this );
 if ( m_Open )
 m_Timer.Start();
 break;
 }
I think the only other mod I made to BaseDoor.cs was to refresh a house by double-clicking the door even without a key (if friended). And that works fine:
Code:
 public override void OnDoubleClick( Mobile from )
 {
 if ( from.AccessLevel == AccessLevel.Player && (/*!from.InLOS( this ) || */!from.InRange( GetWorldLocation(), 2 )) )
 from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
// David: Refresh house just by doubleclicking door even without key if friended
 else
 { 
 BaseHouse house = BaseHouse.FindHouseAt( this );
// BaseHouse house = FindHouse();
 if ( house != null && house.IsFriend( from ) && from.AccessLevel == AccessLevel.Player && house.RefreshDecay() )
 from.SendLocalizedMessage( 1043293 ); // Your house's age and contents have been refreshed.
 Use( from );
 }
 
 }

Now onto BaseHouse.cs:
This is the new MakeKeys() which is called instead of CreateKeys() in order to include the key name, type and description and shows the method of passing KeyType. This works fine.
Code:
 public uint MakeKeys( Mobile m, int keyType, string keyName, string keyDescription )
 {
 uint value = Key.RandomValue();
 if ( !IsAosRules )
 {
 Key packKey = new Key( (KeyType)Enum.ToObject(typeof(KeyType), keyType) );
 Key bankKey = new Key( (KeyType)Enum.ToObject(typeof(KeyType), keyType) );
 packKey.KeyValue = value;
 bankKey.KeyValue = value;
 packKey.Name = keyName;
 bankKey.Name = keyName;
 packKey.Description = keyDescription;
 bankKey.Description = keyDescription;
 BankBox box = m.BankBox;
 if ( !box.TryDropItem( m, bankKey, false ) )
 bankKey.Delete();
 m.AddToBackpack( packKey );
 }
 return value;
 }
Here is the new ChangeLocks() which takes the KeyName and KeyDescription from the door being changed. I want to take KeyType from here too, but for the moment I am just assuming the first two doors are front doors and making the keys gold and the lock the same. The subsequent leys I just make iron although I need to be able to drag the KeyType off the door to make the right key. Obviously these are currently just null as I can't add the KeyType to the door in Houses.cs
I know this will have an issue with houses with only a single door, but I have done this just to get something working for a Tower which is what I am testing with. I will fix that against m_Doors.Count later.
Code:
 public void ChangeLocks( Mobile m )
 {
 if ( m_Doors != null && m_Doors.Count >= 1 )
 {
 uint keyValue = 0;
 string keyName = "";
 string keyDescription = "";
 for ( int i = 0; i < m_Doors.Count; ++i )
 {
 BaseDoor door = m_Doors[i] as BaseDoor;
 
 if (door != null)
 {
 keyName = door.KeyName;
 keyDescription = door.KeyDescription;
 if ( i < 2 )
 {
 keyValue = MakeKeys( m, (int)KeyType.Gold, keyName, keyDescription);
 door.KeyValue = keyValue;
 door.Locked = true;
 ++i;
 door = m_Doors[i] as BaseDoor;
 door.KeyValue = keyValue;
 door.Locked = true;
 
 }
 else
 {
 keyValue = MakeKeys( m, (int)KeyType.Iron, keyName, keyDescription);
 door.KeyValue = keyValue;
 door.Locked = true;
 }
 }
 }
 }
 }
And finally the Tower section from Houses.cs:
I have no houses on my shard yet so Serialise version is left at 0
KeyType is again commented out as this does not work as shown.
Code:
 public class Tower : BaseHouse
 {
 public static Rectangle2D[] AreaArray = new Rectangle2D[]{ new Rectangle2D( -7, -7, 16, 14 ), new Rectangle2D( -1, 7, 4, 2 ), new Rectangle2D( -11, 0, 4, 7 ), new Rectangle2D( 9, 0, 4, 7 ) };
 public override int DefaultPrice{ get{ return 433200; } }
 public override HousePlacementEntry ConvertEntry{ get{ return HousePlacementEntry.ThreeStoryFoundations[37]; } }
 public override int ConvertOffsetY{ get{ return -1; } }
 public override Rectangle2D[] Area{ get{ return AreaArray; } }
 public override Point3D BaseBanLocation{ get{ return new Point3D( 5, 8, 0 ); } }
 public Tower( Mobile owner ) : base( 0x7A, owner, 2119, 15 )
 {
 SetSign( 5, 8, 16 );
 string keyName = "a tower key";
 string keyDescription = "";
 uint keyValue = MakeKeys( owner, (int)KeyType.Gold, keyName, keyDescription);
 
 BaseDoor westDoor = MakeDoor( false, DoorFacing.WestCW );
 BaseDoor eastDoor = MakeDoor( false, DoorFacing.EastCCW );
 westDoor.Locked = true;
 eastDoor.Locked = true;
 westDoor.KeyValue = keyValue;
 eastDoor.KeyValue = keyValue;
 westDoor.KeyName = keyName;
 eastDoor.KeyName = keyName;
 westDoor.KeyDescription = keyDescription;
 eastDoor.KeyDescription = keyDescription;
 
 AddDoor( westDoor, 0, 6, 6 );
 AddDoor( eastDoor, 1, 6, 6 );
 keyName = "an interior key";
 keyDescription = "1st Floor";
 keyValue = MakeKeys( owner, (int)KeyType.Iron, keyName, keyDescription);
 BaseDoor door = MakeDoor( false, DoorFacing.WestCW );
 door.Locked = true;
 door.KeyValue = keyValue;
 door.KeyName = keyName;
 door.KeyDescription = keyDescription;
// door.KeyType = KeyType.Iron;
 AddDoor( door, 3, -2, 6 );
 keyName = "an interior key";
 keyDescription = "2nd Floor";
 keyValue = MakeKeys( owner, (int)KeyType.Iron, keyName, keyDescription);
 door = MakeDoor( false, DoorFacing.SouthCW );
 door.Locked = true;
 door.KeyValue = keyValue;
 door.KeyName = keyName;
 door.KeyDescription = keyDescription;
// door.KeyType = KeyType.Iron;
 AddDoor( door, 1, 4, 26 );
 keyName = "an interior key";
 keyDescription = "3rd Floor";
 keyValue = MakeKeys( owner, (int)KeyType.Iron, keyName, keyDescription);
 door = MakeDoor( false, DoorFacing.SouthCW );
 door.Locked = true;
 door.KeyValue = keyValue;
 door.KeyName = keyName;
 door.KeyDescription = keyDescription;
// door.KeyType = KeyType.Iron;
 AddDoor( door, 1, 4, 46 );
 }
 public Tower( Serial serial ) : base( serial )
 {
 }
 public override HouseDeed GetDeed() { return new TowerDeed(); }
 public override void Serialize( GenericWriter writer )
 {
 base.Serialize( writer );
 writer.Write( (int)0 );//version
 }
 public override void Deserialize( GenericReader reader )
 {
 base.Deserialize( reader );
 int version = reader.ReadInt();
 }
 }

Removing one of the // from the commented out KeyType codes in Houses.cs or anywhere else produces the following error:
Code:
Errors:
 + Multis/Houses.cs:
  CS0266: Line 186: Cannot implicitly convert type 'Server.Items.KeyType' to '
Server.Items.BaseDoor.HouseKeyType'. An explicit conversion exists (are you miss
ing a cast?)

Soooo....
Can I please have some help from one of you very knowledgable people as to how to add the KeyType to the door?
Thank you so much.
David/FB
 
Thank you Lokai,

I removed the // from the front doors changed to door.KeyType = HouseKeyType.Gold and I get the following error:

Errors:
+ Multis/Houses.cs:
CS0103: Line 186: The name 'HouseKeyType' does not exist in the current context
CS0103: Line 187: The name 'HouseKeyType' does not exist in the current context



enum KeyType is already defined in Key.cs I believe. I added the definition enum HouseKeyType in BaseHouse.cs because I couldn't get the original KeyType to work.

Both of these are public, so why is it saying it does not exist?

Changed to BaseDoor.HouseKeyType.Gold and now testing... compiles OK...

Thanks
 
Last edited:
Thank you this now appears to be working as planned with the necessary adjustments to MakeKeys().

I am sure I am being incredibly thick, but when KeyType from key.cs and my HouseKeyType from BaseDoor.cs are both declared public, why can I call KeyType.Gold from anywhere but for HouseKeyType I have to use BaseDoor.HouseKeyType.Gold?

thanks
 
Because you have declared the HouseKeyType enum from within BaseDoor, instead of just residing in the namespace. If you look at other enums like KeyType, you will see that they are placed directly within the namespace, not inside a class like Door, BaseDoor, etc.
 
Ahh thank you. It seems odd though because to me public means just that, yet it is treating it as private.
 
It's public, but it still resides within BaseDoor, not within Items or Mobiles or Server. Your House does not know you mean BaseDoor.HouseKeyType, because it is nested inside the class, not standing on its own, so it is part of the class.
 
OK. Got it - Thanks for the explanation.

I think I am just about there now. Just confused with serialize/deserialize on these new items which I think is threatening to delete all dark wood doors on my server! :) If I comment out the new serialize/deserialize for the KeyTypes only then it works fine. It does the KeyName and KeyDescription without complaint.

Like with the the addkey() method previously, I am unable to just use the enum because serialize/deserialize doesn't know what to do with it, so I convert to int for serialilze and then back again to enum for deserialize. On running at that point I get the following:

awww.uosp.net_images_SerializeError.jpg

Here is the code:

Code:
public BaseDoor( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
	base.Serialize( writer );
	writer.Write( (int) 1 ); // version
	writer.Write( m_KeyValue );
	writer.Write( m_Open );
	 writer.Write( m_Locked );
	writer.Write( m_OpenedID );
	writer.Write( m_ClosedID );
	writer.Write( m_OpenedSound );
	writer.Write( m_ClosedSound );
	writer.Write( m_Offset );
	writer.Write( m_Link );
	writer.Write( m_KeyName );
	writer.Write( m_KeyDescription );
	writer.Write( (int)m_HouseKeyType );
}
public override void Deserialize( GenericReader reader )
{
	base.Deserialize( reader );
	int version = reader.ReadInt();
	switch ( version )
	{
  		case 0:
		{
			m_KeyValue = reader.ReadUInt();
			m_Open = reader.ReadBool();
			m_Locked = reader.ReadBool();
			m_OpenedID = reader.ReadInt();
			m_ClosedID = reader.ReadInt();
			m_OpenedSound = reader.ReadInt();
			m_ClosedSound = reader.ReadInt();
			m_Offset = reader.ReadPoint3D();
			m_Link = reader.ReadItem() as BaseDoor;
			m_Timer = new InternalTimer( this );
			if ( m_Open )
				m_Timer.Start();
			break;
  		}
		case 1:
		{
			m_KeyValue = reader.ReadUInt();
  			m_Open = reader.ReadBool();
			m_Locked = reader.ReadBool();
			m_OpenedID = reader.ReadInt();
			m_ClosedID = reader.ReadInt();
			m_OpenedSound = reader.ReadInt();
			m_ClosedSound = reader.ReadInt();
			m_Offset = reader.ReadPoint3D();
   			m_Link = reader.ReadItem() as BaseDoor;
			m_KeyName = reader.ReadString();
			m_KeyDescription = reader.ReadString();
			m_HouseKeyType = (HouseKeyType)reader.ReadInt();
			m_Timer = new InternalTimer( this );
			if ( m_Open )
				m_Timer.Start();
			 break;
		 }
}

and the commandproperty:

Code:
[CommandProperty( AccessLevel.GameMaster )]
public HouseKeyType KeyType
{
	get
	{
		return m_HouseKeyType;
	 }
	set
	{
		m_HouseKeyType = value;
	}
}

What am I doing wrong?

Thanks in advance.
 
First load the server one time using the OLD Deserialize method and the NEW Serialize method. Then SAVE and EXIT.

Then edit it with the NEW Deserialize method, and start it up.
 
That didn't work, but I guess I corrupted the data by an earlier save. So I copied the live system back into my test environment and then applied the new scripts etc., ran it up with the old deserialise, saved, and reloaded with the new Deserialise and it seems to be working.

Is there some way I can test or look to see if it is doing what it should?

So thanks again for your help. I guess now I need to add the new key stuff to the rest of the houses in houses.cs and I'm ready to go live.

Just the small matter of a website to write now! :)

Cheers
 
Back