public override void DropItem(Item dropped) { if (GetFlag(CorpseFlag.Instanced)) { List <Container> corpses = new List <Container>(); for (int i = 0; i < this.Items.Count; i++) { InstancedCorpse corpse = this.Items[i] as InstancedCorpse; if (corpse != null) { corpses.Add(corpse); } } if (corpses.Count > 0) { corpses[Utility.Random(corpses.Count)].DropItem(dropped); } else { dropped.Delete(); } } else { base.DropItem(dropped); } }
public override void DisplayTo(Mobile to) { if (GetFlag(CorpseFlag.Instanced) && to.AccessLevel < AccessLevel.GameMaster) // Staff always see the main corpse { InstancedCorpse corpse = GetInstancedCorpse(to); if (corpse != null) { corpse.DisplayTo(to); } } else { base.DisplayTo(to); } }
public void AddCarvedItem(Item carved, Mobile carver) { if (GetFlag(CorpseFlag.Instanced)) { InstancedCorpse corpse = GetInstancedCorpse(carver); if (corpse != null) { corpse.DropItem(carved); } } else { this.DropItem(carved); } }
private void UnsplitLoot_Callback() { SetFlag(CorpseFlag.Instanced, false); ArrayList corpses = new ArrayList(this.Items); for (int i = 0; i < corpses.Count; i++) { InstancedCorpse corpse = corpses[i] as InstancedCorpse; if (corpse != null) { corpse.OnUnsplitLoot(); } } }
private InstancedCorpse GetInstancedCorpse(Mobile m) { InstancedCorpse shared = null; for (int i = 0; i < this.Items.Count; i++) { InstancedCorpse corpse = this.Items[i] as InstancedCorpse; if (corpse != null) { if (corpse.IsOwner(m)) // we have precedence over the instance we own { return(corpse); } if (corpse.IsAccessibleTo(m)) { shared = corpse; } } } return(shared); }
public void AssignInstancedLoot() { /* * As per OSI tests: * - Each entity (player or party) gets their own instanced corpse. * - Even if no items are in the corpse or only one instance is created. * - Each instanced corpse is a 'virtual' container that is actually inside the real corpse. * - When a player opens an instanced corpse, it displays to him the instance he owns. */ if ( m_Owner.IsPlayer ) return; // Loot does not instance for players if ( m_Owner is BaseCreature && ( (BaseCreature) m_Owner ).Controlled ) return; // Same for player's pets if ( m_Aggressors.Count == 0 ) return; // Do not instantiate if nobody has looting rights // First of all, classify the items already existing inside the corpse List<Item> m_Stackables = new List<Item>(); List<Item> m_Unstackables = new List<Item>(); for ( int i = 0; i < this.Items.Count; i++ ) { Item item = (Item) this.Items[i]; if ( item.Stackable ) m_Stackables.Add( item ); else m_Unstackables.Add( item ); } // Randomize the attacker's list Mobile[] attackers = Utility.Shuffle( m_Aggressors.ToArray() ); // Create the instances for each player InstancedCorpse[] corpses = new InstancedCorpse[attackers.Length]; for ( int i = 0; i < attackers.Length; i++ ) { Party p = Party.Get( attackers[i] ); if ( p != null ) { for ( int j = 0; j < i; j++ ) { if ( p == Party.Get( attackers[j] ) ) { corpses[j].AddLooter( attackers[i] ); corpses[i] = corpses[j]; // Players in the same party share the same instanced corpse break; } } } if ( corpses[i] == null ) corpses[i] = new InstancedCorpse( this, attackers[i] ); } // stackables first, for the remaining stackables, have those be randomly added after for ( int i = 0; i < m_Stackables.Count; i++ ) { Item item = m_Stackables[i]; if ( item.Amount >= attackers.Length ) { int amountPerAttacker = ( item.Amount / attackers.Length ); int remainder = ( item.Amount % attackers.Length ); for ( int j = 0; j < ( ( remainder == 0 ) ? corpses.Length - 1 : corpses.Length ); j++ ) { Item splitItem = Mobile.LiftItemDupe( item, item.Amount - amountPerAttacker ); corpses[j].TryDropItem( splitItem ); // What happens to the remaining portion? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. } if ( remainder == 0 ) { corpses[corpses.Length - 1].TryDropItem( item ); // Add in the original item (which has an equal amount as the others) to the instance for the last attacker, cause it wasn't added above. } else { m_Unstackables.Add( item ); } } else { // What happens in this case? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. m_Unstackables.Add( item ); } } for ( int i = 0; i < m_Unstackables.Count; i++ ) { // Randomly distribute unstackable items corpses[i % corpses.Length].TryDropItem( m_Unstackables[i] ); } // Resend rummaged items to their owner's instance if ( m_Owner is BaseCreature ) { BaseCreature bcOwner = m_Owner as BaseCreature; foreach ( KeyValuePair<Item, Mobile> kvp in bcOwner.RummagedItems ) { InstancedCorpse corpse = GetInstancedCorpse( kvp.Value ); if ( corpse != null ) corpse.DropItem( kvp.Key ); } } SetFlag( CorpseFlag.Instanced, true ); m_UnsplitTimer = Timer.DelayCall( InstancedCorpseTime, new TimerCallback( UnsplitLoot_Callback ) ); }
public void AssignInstancedLoot() { /* * As per OSI tests: * - Each entity (player or party) gets their own instanced corpse. * - Even if no items are in the corpse or only one instance is created. * - Each instanced corpse is a 'virtual' container that is actually inside the real corpse. * - When a player opens an instanced corpse, it displays to him the instance he owns. */ if (m_Owner.IsPlayer) { return; // Loot does not instance for players } if (m_Owner is BaseCreature && ((BaseCreature)m_Owner).Controlled) { return; // Same for player's pets } if (m_Aggressors.Count == 0) { return; // Do not instantiate if nobody has looting rights } // First of all, classify the items already existing inside the corpse List <Item> m_Stackables = new List <Item>(); List <Item> m_Unstackables = new List <Item>(); for (int i = 0; i < this.Items.Count; i++) { Item item = (Item)this.Items[i]; if (item.Stackable) { m_Stackables.Add(item); } else { m_Unstackables.Add(item); } } // Randomize the attacker's list Mobile[] attackers = Utility.Shuffle(m_Aggressors.ToArray()); // Create the instances for each player InstancedCorpse[] corpses = new InstancedCorpse[attackers.Length]; for (int i = 0; i < attackers.Length; i++) { Party p = Party.Get(attackers[i]); if (p != null) { for (int j = 0; j < i; j++) { if (p == Party.Get(attackers[j])) { corpses[j].AddLooter(attackers[i]); corpses[i] = corpses[j]; // Players in the same party share the same instanced corpse break; } } } if (corpses[i] == null) { corpses[i] = new InstancedCorpse(this, attackers[i]); } } // stackables first, for the remaining stackables, have those be randomly added after for (int i = 0; i < m_Stackables.Count; i++) { Item item = m_Stackables[i]; if (item.Amount >= attackers.Length) { int amountPerAttacker = (item.Amount / attackers.Length); int remainder = (item.Amount % attackers.Length); for (int j = 0; j < ((remainder == 0) ? corpses.Length - 1 : corpses.Length); j++) { Item splitItem = Mobile.LiftItemDupe(item, item.Amount - amountPerAttacker); corpses[j].TryDropItem(splitItem); // What happens to the remaining portion? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. } if (remainder == 0) { corpses[corpses.Length - 1].TryDropItem(item); // Add in the original item (which has an equal amount as the others) to the instance for the last attacker, cause it wasn't added above. } else { m_Unstackables.Add(item); } } else { // What happens in this case? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. m_Unstackables.Add(item); } } for (int i = 0; i < m_Unstackables.Count; i++) { // Randomly distribute unstackable items corpses[i % corpses.Length].TryDropItem(m_Unstackables[i]); } // Resend rummaged items to their owner's instance if (m_Owner is BaseCreature) { BaseCreature bcOwner = m_Owner as BaseCreature; foreach (KeyValuePair <Item, Mobile> kvp in bcOwner.RummagedItems) { InstancedCorpse corpse = GetInstancedCorpse(kvp.Value); if (corpse != null) { corpse.DropItem(kvp.Key); } } } SetFlag(CorpseFlag.Instanced, true); m_UnsplitTimer = Timer.DelayCall(InstancedCorpseTime, new TimerCallback(UnsplitLoot_Callback)); }