- Added Scrolls of Transcendence and Scrolls of Alacrity. Scrolls of Transcendence, togheter with 105 Powerscrolls, will spawn while doing champion spawns.

(http://www.uodemise.com/discussion/showthread.php?t=116067)

- Rune Beetle Armor Corruption now works properly
(http://www.uodemise.com/discussion/showthread.php?t=123086)

- the Animal Trainer now will say only "Your pet has been stabled" when you stable a pet (won't affect Pre-AoS)
(http://www.uodemise.com/discussion/showthread.php?t=123113)

- Acid elementals now use the proper poison level, and are vulnerable to elemental slayers. When animated, they turn in wraith or banshee
(http://www.uodemise.com/discussion/showthread.php?t=125749)

- You can't drop items on the same tile a mobile (PC or NPC) is
(http://www.uodemise.com/discussion/showthread.php?t=116540)

- the Embrace Honor virtue ability now works as per OSI
(http://www.uodemise.com/discussion/showthread.php?t=125722)

- Woodland Belts now are dyable
(http://www.uodemise.com/discussion/showthread.php?t=128444)

- You can combine folded cloth and bottle of liquor to make firebombs
(http://www.uodemise.com/discussion/showthread.php?t=125257)

- SoS now are not anymore facet specific, as per OSI
(http://www.uodemise.com/discussion/showthread.php?t=115477)
This commit is contained in:
daedalus 2009-12-06 21:30:25 +00:00
parent e519ff2497
commit 37043076e0
19 changed files with 1236 additions and 17 deletions

View file

@ -387,6 +387,137 @@ namespace Server.Engines.CannedEvil
Start();
}
#region Scroll of Transcendence
private ScrollofTranscendence CreateRandomTramSoT()
{
int level;
double random = Utility.RandomDouble();
if (0.2 >= random)
level = 5;
else if (0.4 >= random)
level = 4;
else if (0.6 >= random)
level = 3;
else if (0.8 >= random)
level = 2;
else
level = 1;
return ScrollofTranscendence.CreateRandom(level, level);
}
private ScrollofTranscendence CreateRandomFelSoT()
{
int level;
double random = Utility.RandomDouble();
if (0.2 >= random)
level = 10;
else if (0.4 >= random)
level = 9;
else if (0.6 >= random)
level = 8;
else if (0.8 >= random)
level = 7;
else
level = 6;
return ScrollofTranscendence.CreateRandom(level, level);
}
private PowerScroll CreateRandomFelPS()
{
return PowerScroll.CreateRandomNoCraft(5, 5);
}
public static void GiveScrollOfTranscendenceFelTo ( Mobile killer, ScrollofTranscendence SoTF )
{
if( SoTF == null || killer == null ) //sanity
return;
killer.SendLocalizedMessage( 1094936 ); // You have received a Scroll of Transcendence!
if ( killer.Alive )
killer.AddToBackpack( SoTF );
else
{
if( killer.Corpse != null && !killer.Corpse.Deleted )
killer.Corpse.DropItem( SoTF );
else
killer.AddToBackpack( SoTF );
}
// Justice reward
PlayerMobile pm = (PlayerMobile)killer;
for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
{
Mobile prot = (Mobile)pm.JusticeProtectors[j];
if (prot.Map != killer.Map || prot.Kills >= 5 || prot.Criminal || !JusticeVirtue.CheckMapRegion(killer, prot))
continue;
int chance = 0;
switch (VirtueHelper.GetLevel(prot, VirtueName.Justice))
{
case VirtueLevel.Seeker: chance = 60; break;
case VirtueLevel.Follower: chance = 80; break;
case VirtueLevel.Knight: chance = 100; break;
}
if (chance > Utility.Random(100))
{
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
ScrollofTranscendence SoTFduplicate = new ScrollofTranscendence ( SoTF.Skill, SoTF.Value );
prot.AddToBackpack( SoTFduplicate );
}
}
}
public static void GivePowerScrollFelTo ( Mobile killer, PowerScroll PS )
{
if( PS == null || killer == null ) //sanity
return;
killer.SendLocalizedMessage(1049524); // You have received a scroll of power!
if ( killer.Alive )
killer.AddToBackpack( PS );
else
{
if( killer.Corpse != null && !killer.Corpse.Deleted )
killer.Corpse.DropItem( PS );
else
killer.AddToBackpack( PS );
}
// Justice reward
PlayerMobile pm = (PlayerMobile)killer;
for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
{
Mobile prot = (Mobile)pm.JusticeProtectors[j];
if (prot.Map != killer.Map || prot.Kills >= 5 || prot.Criminal || !JusticeVirtue.CheckMapRegion(killer, prot))
continue;
int chance = 0;
switch (VirtueHelper.GetLevel(prot, VirtueName.Justice))
{
case VirtueLevel.Seeker: chance = 60; break;
case VirtueLevel.Follower: chance = 80; break;
case VirtueLevel.Knight: chance = 100; break;
}
if (chance > Utility.Random(100))
{
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
PowerScroll PSduplicate = new PowerScroll ( PS.Skill, PS.Value );
prot.AddToBackpack( PSduplicate );
}
}
}
#endregion
public void OnSlice()
{
if( !m_Active || Deleted )
@ -445,6 +576,41 @@ namespace Server.Engines.CannedEvil
if( killer is PlayerMobile )
{
#region Scroll of Transcendence
if ( Core.ML )
{
if ( Map == Map.Felucca )
{
if ( Utility.RandomDouble() < 0.001 )
{
PlayerMobile pm = (PlayerMobile)killer;
double random = Utility.Random ( 49 );
if ( random <= 24 )
{
ScrollofTranscendence SoTF = CreateRandomFelSoT();
GiveScrollOfTranscendenceFelTo ( pm, SoTF );
}
else
{
PowerScroll PS = CreateRandomFelPS();
GivePowerScrollFelTo ( pm, PS );
}
}
}
if ( Map == Map.Ilshenar || Map == Map.Tokuno )
{
if ( Utility.RandomDouble() < 0.0015 )
{
killer.SendLocalizedMessage( 1094936 ); // You have received a Scroll of Transcendence!
ScrollofTranscendence SoTT = CreateRandomTramSoT();
killer.AddToBackpack( SoTT );
}
}
}
#endregion
int mobSubLevel = GetSubLevelFor( m ) + 1;
if( mobSubLevel >= 0 )

View file

@ -251,7 +251,7 @@ namespace Server.Engines.Harvest
{
SOS sos = messages[i];
if ( from.Map == sos.TargetMap && from.InRange( sos.TargetLocation, 60 ) )
if ( ( from.Map == Map.Felucca || from.Map == Map.Trammel ) && from.InRange( sos.TargetLocation, 60 ) )
{
Item preLoot = null;

View file

@ -0,0 +1,270 @@
using Server.Network;
using Server.Spells;
using Server.Targeting;
using System;
using System.Collections.Generic;
namespace Server.Items
{
public class Firebomb : Item
{
private Timer m_Timer;
private int m_Ticks = 0;
private Mobile m_LitBy;
[Constructable]
public Firebomb() : this( 0x99B )
{
}
[Constructable]
public Firebomb( int itemID ) : base( itemID )
{
//Name = "a firebomb";
Weight = 2.0;
Hue = 1260;
}
public Firebomb( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
}
public override void OnDoubleClick( Mobile from )
{
if ( !IsChildOf( from.Backpack ) )
{
from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it.
return;
}
if ( Core.AOS && (from.Paralyzed || from.Frozen || (from.Spell != null && from.Spell.IsCasting)) )
{
//to prevent exploiting for pvp
from.SendLocalizedMessage( 1075857 ); // You can not use that while paralyzed.
return;
}
if ( m_Timer == null )
{
m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 1 ), TimeSpan.FromSeconds( 1 ), new TimerCallback( OnFirebombTimerTick ) );
m_LitBy = from;
from.SendLocalizedMessage( 1060581 ); //You light the firebomb! Throw it now!
}
else
from.SendLocalizedMessage( 1060582 ); //You've already lit it! Better throw it now!
from.BeginTarget( 12, true, TargetFlags.None, new TargetCallback( OnFirebombTarget ) );
}
private void OnFirebombTimerTick()
{
if ( Deleted )
{
m_Timer.Stop();
return;
}
if ( Map == Map.Internal && HeldBy == null )
return;
switch ( m_Ticks )
{
case 0:
case 1:
case 2:
{
++m_Ticks;
if ( HeldBy != null )
HeldBy.PublicOverheadMessage( MessageType.Regular, 957, false, m_Ticks.ToString() );
else if ( RootParent == null )
PublicOverheadMessage( MessageType.Regular, 957, false, m_Ticks.ToString() );
else if ( RootParent is Mobile )
((Mobile)RootParent).PublicOverheadMessage( MessageType.Regular, 957, false, m_Ticks.ToString() );
break;
}
default:
{
if ( HeldBy != null )
HeldBy.DropHolding();
if ( RootParent is Mobile )
{
Mobile parent = (Mobile)RootParent;
parent.SendLocalizedMessage( 1060583 ); //The firebomb explodes in your hand!
AOS.Damage( parent, Utility.Random( 3 ) + 4, 0, 100, 0, 0, 0 );
}
else if ( RootParent == null )
{
List<Mobile> toDamage = new List<Mobile>();
IPooledEnumerable eable = Map.GetMobilesInRange( Location, 1 );
foreach ( Mobile m in eable )
{
toDamage.Add( m );
}
eable.Free();
Mobile victim;
for ( int i = 0; i < toDamage.Count; ++i )
{
victim = toDamage[i];
if ( m_LitBy == null || (SpellHelper.ValidIndirectTarget( m_LitBy, victim ) && m_LitBy.CanBeHarmful( victim, false )) )
{
if ( m_LitBy != null )
m_LitBy.DoHarmful( victim );
AOS.Damage( victim, m_LitBy, Utility.Random( 3 ) + 4, 0, 100, 0, 0, 0 );
}
}
(new FirebombField( m_LitBy, toDamage )).MoveToWorld( Location, Map );
}
m_Timer.Stop();
Delete();
break;
}
}
}
private void OnFirebombTarget( Mobile from, object obj )
{
if ( Deleted || Map == Map.Internal || !IsChildOf( from.Backpack ) )
return;
IPoint3D p = obj as IPoint3D;
if ( p == null )
return;
SpellHelper.GetSurfaceTop( ref p );
from.RevealingAction();
IEntity to;
if ( p is Mobile )
to = (Mobile)p;
else
to = new Entity( Serial.Zero, new Point3D( p ), Map );
Effects.SendMovingEffect( from, to, ItemID & 0x3FFF, 7, 0, false, false, Hue, 0 );
Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerStateCallback( FirebombReposition_OnTick ), new object[]{ p, Map } );
Internalize();
}
private void FirebombReposition_OnTick( object state )
{
if ( Deleted )
return;
object[] states = (object[])state;
IPoint3D p = (IPoint3D)states[0];
Map map = (Map)states[1];
MoveToWorld( new Point3D( p ), map );
}
}
public class FirebombField : Item
{
private List<Mobile> m_Burning;
private Timer m_Timer;
private Mobile m_LitBy;
private DateTime m_Expire;
public FirebombField( Mobile litBy, List<Mobile> toDamage ) : base( 0x376A )
{
Movable = false;
m_LitBy = litBy;
m_Expire = DateTime.Now + TimeSpan.FromSeconds( 10 );
m_Burning = toDamage;
m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ), new TimerCallback( OnFirebombFieldTimerTick ) );
}
public FirebombField( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
//Don't serialize these...
}
public override void Deserialize( GenericReader reader )
{
}
public override bool OnMoveOver( Mobile m )
{
if ( ItemID == 0x398C && m_LitBy == null || (SpellHelper.ValidIndirectTarget( m_LitBy, m ) && m_LitBy.CanBeHarmful( m, false )) )
{
if ( m_LitBy != null )
m_LitBy.DoHarmful( m );
AOS.Damage( m, m_LitBy, 2, 0, 100, 0, 0, 0 );
m.PlaySound( 0x208 );
if ( !m_Burning.Contains( m ) )
m_Burning.Add( m );
}
return true;
}
private void OnFirebombFieldTimerTick()
{
if ( Deleted )
{
m_Timer.Stop();
return;
}
if ( ItemID == 0x376A )
{
ItemID = 0x398C;
return;
}
Mobile victim;
for ( int i = 0; i < m_Burning.Count; )
{
victim = m_Burning[i];
if ( victim.Location == Location && victim.Map == Map && (m_LitBy == null || ( SpellHelper.ValidIndirectTarget( m_LitBy, victim ) && m_LitBy.CanBeHarmful( victim, false ) )) )
{
if ( m_LitBy != null )
m_LitBy.DoHarmful( victim );
AOS.Damage( victim, m_LitBy, Utility.Random( 3 ) + 4, 0, 100, 0, 0, 0 );
++i;
}
else
m_Burning.RemoveAt( i );
}
if ( DateTime.Now >= m_Expire )
{
m_Timer.Stop();
Delete();
}
}
}
}

View file

@ -106,6 +106,29 @@ namespace Server.Items
from.LocalOverheadMessage( Network.MessageType.Regular, 0x3B2, 1005422 ); // Hmmmm... this does not need to be cleaned.
}
}
//Added for Firebomb
else if ( obj is BaseBeverage )
{
BaseBeverage beverage = (BaseBeverage) obj;
if ( beverage.Content == BeverageType.Liquor )
{
Firebomb bomb = new Firebomb( beverage.ItemID );
bomb.Name = beverage.Name;
Point3D loc = beverage.Location;
beverage.Delete();
from.AddToBackpack( bomb );
bomb.Location = loc;
from.SendLocalizedMessage( 1060580 ); // You prepare a firebomb.
Consume();
}
}
else if ( obj is Firebomb )
{
from.SendLocalizedMessage( 1060579 ); // That is already a firebomb!
}
//Firebomb end
else
{
from.SendLocalizedMessage( 1005426 ); // The cloth will not work on that.

View file

@ -251,7 +251,7 @@ namespace Server.Items
from.PlaySound( 0x23E );
}
}
else if ( (item is BaseArmor && (((BaseArmor)item).MaterialType == ArmorMaterialType.Leather || ((BaseArmor)item).MaterialType == ArmorMaterialType.Studded) || item is ElvenBoots) && m_Tub.AllowLeather )
else if ( (item is BaseArmor && (((BaseArmor)item).MaterialType == ArmorMaterialType.Leather || ((BaseArmor)item).MaterialType == ArmorMaterialType.Studded) || item is ElvenBoots || item is WoodlandBelt) && m_Tub.AllowLeather )
{
if ( !from.InRange( m_Tub.GetWorldLocation(), 1 ) || !from.InRange( item.GetWorldLocation(), 1 ) )
{

View file

@ -5,6 +5,7 @@ using Server.Network;
using Server.Accounting;
using Server.Engines.VeteranRewards;
using Server.Multis;
using Server.Mobiles;
namespace Server.Items
{
@ -49,7 +50,7 @@ namespace Server.Items
this.ItemID = m_InactiveItemID;
}
}
public static readonly TimeSpan UseDelay = TimeSpan.FromDays( 1.0 );
private string m_Account;
@ -157,6 +158,8 @@ namespace Server.Items
{
DateTime now = DateTime.Now;
PlayerMobile pm = from as PlayerMobile;
if ( this.Deleted || !this.IsAccessibleTo( from ) )
{
return false;
@ -224,6 +227,15 @@ namespace Server.Items
return false;
}
#region Scroll of Alacrity
if ( pm.AcceleratedStart > DateTime.Now )
{
from.SendLocalizedMessage(1078115); // You may not use a soulstone while your character is under the effects of a Scroll of Alacrity.
return false;
}
#endregion
else
{
return true;
@ -591,6 +603,21 @@ namespace Server.Items
return;
}
#region Scroll of ALacrity
PlayerMobile pm = from as PlayerMobile;
if (pm.AcceleratedStart > DateTime.Now)
{
// <CENTER>Unable to Absorb Selected Skill from Soulstone</CENTER>
/*You may not use a soulstone while your character is under the effects of a Scroll of Alacrity.*/
// Wrong message?!
from.SendGump(new ErrorGump(m_Stone, 1070717, 1078115));
return;
}
#endregion
if ( requiredAmount > 0 )
{
for ( int i = 0; i < from.Skills.Length; ++i )

View file

@ -270,9 +270,12 @@ namespace Server.Items
{
if ( firstStage )
{
from.CloseGump( typeof( StatCapScroll.InternalGump ) );
from.CloseGump( typeof( PowerScroll.InternalGump ) );
from.SendGump( new InternalGump( from, this ) );
from.CloseGump(typeof(StatCapScroll.InternalGump));
from.CloseGump(typeof(PowerScroll.InternalGump));
#region Scroll of Alacrity
from.CloseGump(typeof(ScrollofAlacrity.InternalGump));
#endregion
from.SendGump(new InternalGump(from, this));
}
else
{

View file

@ -0,0 +1,324 @@
/***************************************************************************
* ScrollofAlacrity.cs
* -------------------
* begin : June 1, 2009
* copyright : (C) Shai'Tan Malkier aka Callandor2k
* email : ShaiTanMalkier@gmail.com
*
* $Id: ScrollofAlacrity.cs 1 2009-06-1 04:28:39Z Callandor2k $
*
***************************************************************************/
/***************************************************************************
*
* This Script/File is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using System.Collections;
using Server.Engines.Quests;
using System.Collections.Generic;
namespace Server.Items
{
public class ScrollofAlacrity : Item
{
public override int LabelNumber { get { return 1078604; } } // Scroll of Alacrity
private SkillName m_Skill;
private static SkillName[] m_Skills = new SkillName[]
{
SkillName.Alchemy,
SkillName.Anatomy,
SkillName.AnimalLore,
SkillName.ItemID,
SkillName.ArmsLore,
SkillName.Parry,
SkillName.Begging,
SkillName.Blacksmith,
SkillName.Fletching,
SkillName.Peacemaking,
SkillName.Camping,
SkillName.Carpentry,
SkillName.Cartography,
SkillName.Cooking,
SkillName.DetectHidden,
SkillName.Discordance,
SkillName.EvalInt,
SkillName.Healing,
SkillName.Fishing,
SkillName.Forensics,
SkillName.Herding,
SkillName.Hiding,
SkillName.Provocation,
SkillName.Inscribe,
SkillName.Lockpicking,
SkillName.Magery,
SkillName.MagicResist,
SkillName.Tactics,
SkillName.Snooping,
SkillName.Musicianship,
SkillName.Poisoning,
SkillName.Archery,
SkillName.SpiritSpeak,
SkillName.Stealing,
SkillName.Tailoring,
SkillName.AnimalTaming,
SkillName.TasteID,
SkillName.Tinkering,
SkillName.Tracking,
SkillName.Veterinary,
SkillName.Swords,
SkillName.Macing,
SkillName.Fencing,
SkillName.Wrestling,
SkillName.Lumberjacking,
SkillName.Mining,
SkillName.Meditation,
SkillName.Stealth,
SkillName.RemoveTrap,
SkillName.Necromancy,
SkillName.Focus,
SkillName.Chivalry,
SkillName.Bushido,
SkillName.Ninjitsu,
SkillName.Spellweaving
};
public static SkillName[] Skills { get { return (m_Skills); } }
[Constructable]
public ScrollofAlacrity(SkillName skill)
: base(0x14EF)
{
base.Hue = 0x4AB;
base.Weight = 1.0;
LootType = LootType.Cursed;
m_Skill = skill;
}
public ScrollofAlacrity(Serial serial)
: base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public SkillName Skill
{
get
{
return m_Skill;
}
set
{
m_Skill = value;
}
}
private string GetNameLocalized()
{
return String.Concat("#", (1044060 + (int)m_Skill).ToString());
}
private string GetName()
{
int index = (int)m_Skill;
SkillInfo[] table = SkillInfo.Table;
if (index >= 0 && index < table.Length)
return table[index].Name.ToLower();
else
return "???";
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(1071345, "{0} 15 Minutes", GetName());// Skill: ~1_val~
}
public void Use(Mobile from, bool firstStage)
{
PlayerMobile pm = from as PlayerMobile;
if (Deleted)
return;
/* to add when skillgain quests will be implemented
#region Mondain's Legacy
for (int i = pm.Quests.Count - 1; i >= 0; i--)
{
BaseQuest quest = pm.Quests[i];
for (int j = quest.Objectives.Count - 1; j >= 0; j--)
{
BaseObjective objective = quest.Objectives[j];
if (objective is ApprenticeObjective)
{
from.SendMessage("You are already under the effect of an enhanced skillgain quest.");
return;
}
}
}
#endregion
*/
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
else if (pm.AcceleratedStart > DateTime.Now)
{
from.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return;
}
else
{
if (firstStage)
{
from.CloseGump(typeof(StatCapScroll.InternalGump));
from.CloseGump(typeof(PowerScroll.InternalGump));
from.CloseGump(typeof(ScrollofTranscendence.InternalGump));
from.CloseGump(typeof(ScrollofAlacrity.InternalGump));
from.SendGump(new InternalGump(from, this));
}
else
{
double tskill = from.Skills[m_Skill].Base;
double tcap = from.Skills[m_Skill].Cap;
if (tskill >= tcap || from.Skills[m_Skill].Lock == SkillLock.Locked || from.Skills[m_Skill].Lock == SkillLock.Down)
{
from.SendLocalizedMessage(1094935); /*You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu.
*If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap.*/
return;
}
else
{
Effects.PlaySound(from.Location, from.Map, 0x1E9);
Effects.SendTargetParticles(from, 0x373A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100);
from.SendLocalizedMessage(1077956); // You are infused with intense energy. You are under the effects of an accelerated skillgain scroll.
pm.AcceleratedStart = DateTime.Now + TimeSpan.FromMinutes(15);
Timer t = (Timer)m_Table[from];
m_Table[from] = Timer.DelayCall(TimeSpan.FromMinutes(15), new TimerStateCallback(Expire_Callback), from);
pm.AcceleratedSkill = m_Skill;
Delete();
}
}
}
}
private static Hashtable m_Table = new Hashtable();
private static void Expire_Callback(object state)
{
Mobile m = (Mobile)state;
m_Table.Remove(m);
m.PlaySound(0x1F8);
m.SendLocalizedMessage(1077957);// The intense energy dissipates. You are no longer under the effects of an accelerated skillgain scroll.
}
public override void OnDoubleClick(Mobile from)
{
Use(from, true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write((int)m_Skill);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Skill = (SkillName)reader.ReadInt();
break;
}
}
LootType = LootType.Cursed;
if (Insured)
Insured = false;
}
public class InternalGump : Gump
{
private Mobile m_Mobile;
private ScrollofAlacrity m_Scroll;
public InternalGump(Mobile mobile, ScrollofAlacrity scroll)
: base(25, 50)
{
m_Mobile = mobile;
m_Scroll = scroll;
AddPage(0);
AddBackground(25, 10, 420, 200, 5054);
AddImageTiled(33, 20, 401, 181, 2624);
AddAlphaRegion(33, 20, 401, 181);
AddHtmlLocalized(40, 48, 387, 100, 1078602, true, true); /* Using a Scroll of Alacrity for a given skill will increase the amount of skillgain
* you receive for that skill. Once the Scroll of Alacrity duration has expired,
* skillgain will return to normal for that skill. */
AddHtmlLocalized(125, 148, 200, 20, 1049478, 0xFFFFFF, false, false); // Do you wish to use this scroll?
AddButton(100, 172, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(135, 172, 120, 20, 1046362, 0xFFFFFF, false, false); // Yes
AddButton(275, 172, 4005, 4007, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(310, 172, 120, 20, 1046363, 0xFFFFFF, false, false); // No
AddHtml(40, 20, 260, 20, String.Format("<basefont color=#FFFFFF>Scroll of Alacrity:</basefont>"), false, false);
AddHtmlLocalized(310, 20, 120, 20, 1044060 + (int)scroll.m_Skill, 0xFFFFFF, false, false);
}
public override void OnResponse(NetState state, RelayInfo info)
{
if (info.ButtonID == 1)
m_Scroll.Use(m_Mobile, false);
}
}
}
}

View file

@ -0,0 +1,352 @@
using System;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using Server.Engines.Quests;
namespace Server.Items
{
public class ScrollofTranscendence : Item
{
public override int LabelNumber { get { return 1094934; } } // Scroll of Transcendence
private SkillName m_Skill;
private double m_Value;
private static SkillName[] m_Skills = new SkillName[]
{
SkillName.Alchemy,
SkillName.Anatomy,
SkillName.AnimalLore,
SkillName.ItemID,
SkillName.ArmsLore,
SkillName.Parry,
SkillName.Begging,
SkillName.Blacksmith,
SkillName.Fletching,
SkillName.Peacemaking,
SkillName.Camping,
SkillName.Carpentry,
SkillName.Cartography,
SkillName.Cooking,
SkillName.DetectHidden,
SkillName.Discordance,
SkillName.EvalInt,
SkillName.Healing,
SkillName.Fishing,
SkillName.Forensics,
SkillName.Herding,
SkillName.Hiding,
SkillName.Provocation,
SkillName.Inscribe,
SkillName.Lockpicking,
SkillName.Magery,
SkillName.MagicResist,
SkillName.Tactics,
SkillName.Snooping,
SkillName.Musicianship,
SkillName.Poisoning,
SkillName.Archery,
SkillName.SpiritSpeak,
SkillName.Stealing,
SkillName.Tailoring,
SkillName.AnimalTaming,
SkillName.TasteID,
SkillName.Tinkering,
SkillName.Tracking,
SkillName.Veterinary,
SkillName.Swords,
SkillName.Macing,
SkillName.Fencing,
SkillName.Wrestling,
SkillName.Lumberjacking,
SkillName.Mining,
SkillName.Meditation,
SkillName.Stealth,
SkillName.RemoveTrap,
SkillName.Necromancy,
SkillName.Focus,
SkillName.Chivalry,
SkillName.Bushido,
SkillName.Ninjitsu,
SkillName.Spellweaving
};
public static SkillName[] Skills { get { return (m_Skills); } }
public static ScrollofTranscendence CreateRandom(int min, int max)
{
min /= 1;
max /= 1;
SkillName[] skills = ScrollofTranscendence.Skills;
return new ScrollofTranscendence(skills[Utility.Random(skills.Length)], Utility.RandomMinMax(min, max) * 0.1);
}
[Constructable]
public ScrollofTranscendence(SkillName skill, double value)
: base(0x14EF)
{
Hue = 0x490;
Weight = 1.0;
m_Skill = skill;
m_Value = value;
if (m_Value > 0.0)
LootType = LootType.Cursed;
}
public ScrollofTranscendence(Serial serial)
: base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public SkillName Skill
{
get
{
return m_Skill;
}
set
{
m_Skill = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public double Value
{
get
{
return m_Value;
}
set
{
m_Value = value;
}
}
private string GetNameLocalized()
{
return String.Concat("#", (1044060 + (int)m_Skill).ToString());
}
private string GetName()
{
int index = (int)m_Skill;
SkillInfo[] table = SkillInfo.Table;
if (index >= 0 && index < table.Length)
return table[index].Name.ToLower();
else
return "???";
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (m_Value == 1)
list.Add(1076759, "{0}\t{1}.0 Skill Points", GetName(), m_Value);
else
list.Add(1076759, "{0}\t{1} Skill Points", GetName(), m_Value);
}
public void Use(Mobile from, bool firstStage)
{
PlayerMobile pm = from as PlayerMobile;
if (Deleted)
return;
/* to uncomment when skillgain quests will be implementes
#region Mondain's Legacy
for (int i = pm.Quests.Count - 1; i >= 0; i--)
{
BaseQuest quest = pm.Quests[i];
for (int j = quest.Objectives.Count - 1; j >= 0; j--)
{
BaseObjective objective = quest.Objectives[j];
if (objective is ApprenticeObjective)
{
from.SendMessage("You are already under the effect of an enhanced skillgain quest.");
return;
}
}
}
#endregion
*/
if (!IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
}
#region Scroll of Alacrity
else if (pm.AcceleratedStart > DateTime.Now)
{
from.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll.
return;
}
#endregion
else
{
if (firstStage)
{
from.CloseGump(typeof(StatCapScroll.InternalGump));
from.CloseGump(typeof(PowerScroll.InternalGump));
from.CloseGump(typeof(ScrollofTranscendence.InternalGump));
from.CloseGump(typeof(ScrollofAlacrity.InternalGump));
from.SendGump(new InternalGump(from, this));
}
else
{
double tskill = from.Skills[m_Skill].Base;
double tcap = from.Skills[m_Skill].Cap;
bool canGain = true;
if (tskill >= tcap || from.Skills[m_Skill].Lock == SkillLock.Locked || from.Skills[m_Skill].Lock == SkillLock.Down)
{
from.SendLocalizedMessage(1094935); /*You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu.
*If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap.*/
return;
}
if ((tskill + m_Value) > tcap)
m_Value = tcap - tskill;
if ((from.SkillsTotal + m_Value * 10) > from.SkillsCap)
{
canGain = false;
for (int i = 0; i <= 54; i++)
{
if (from.Skills[i].Lock == SkillLock.Down && from.Skills[i].Base >= m_Value)
{
from.Skills[i].Base = from.Skills[i].Base - m_Value;
canGain = true;
break;
}
}
if (!canGain)
{
from.SendLocalizedMessage(1094935); /*You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu.
*If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap.*/
return;
}
}
if (tskill + m_Value > tcap)
{
from.Skills[m_Skill].Base = tcap;
}
else
{
from.Skills[m_Skill].Base = tskill + m_Value;
}
from.SendLocalizedMessage(1049513, GetNameLocalized()); // You feel a surge of magic as the scroll enhances your ~1_type~!
Effects.PlaySound(from.Location, from.Map, 0x1F7);
Effects.SendTargetParticles(from, 0x373A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100);
Effects.SendTargetParticles(from, 0x376A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100);
Delete();
}
}
}
public override void OnDoubleClick(Mobile from)
{
Use(from, true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write((int)m_Skill);
writer.Write((double)m_Value);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Skill = (SkillName)reader.ReadInt();
m_Value = reader.ReadDouble();
break;
}
}
if (m_Value >= 0.1)
{
LootType = LootType.Cursed;
if (Insured)
Insured = false;
}
if (Hue == 0x7E)
Hue = 0x490;
}
public class InternalGump : Gump
{
private Mobile m_Mobile;
private ScrollofTranscendence m_Scroll;
public InternalGump(Mobile mobile, ScrollofTranscendence scroll)
: base(25, 50)
{
m_Mobile = mobile;
m_Scroll = scroll;
AddPage(0);
AddBackground(25, 10, 420, 200, 5054);
AddImageTiled(33, 20, 401, 181, 2624);
AddAlphaRegion(33, 20, 401, 181);
AddHtmlLocalized(40, 48, 387, 100, 1094933, true, true); /*Using a Scroll of Transcendence for a given skill will permanently increase your current
*level in that skill by the amount of points displayed on the scroll.
*As you may not gain skills beyond your maximum skill cap, any excess points will be lost.*/
AddHtmlLocalized(125, 148, 200, 20, 1049478, 0xFFFFFF, false, false); // Do you wish to use this scroll?
AddButton(100, 172, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(135, 172, 120, 20, 1046362, 0xFFFFFF, false, false); // Yes
AddButton(275, 172, 4005, 4007, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(310, 172, 120, 20, 1046363, 0xFFFFFF, false, false); // No
double value = scroll.m_Value;
AddHtml(40, 20, 260, 20, String.Format("<basefont color=#FFFFFF>Scroll of Transcendence ({0} Skill):</basefont>", value), false, false);
AddHtmlLocalized(310, 20, 120, 20, 1044060 + (int)scroll.m_Skill, 0xFFFFFF, false, false);
}
public override void OnResponse(NetState state, RelayInfo info)
{
if (info.ButtonID == 1)
m_Scroll.Use(m_Mobile, false);
}
}
}
}

View file

@ -89,6 +89,9 @@ namespace Server.Items
{
from.CloseGump( typeof( StatCapScroll.InternalGump ) );
from.CloseGump( typeof( PowerScroll.InternalGump ) );
#region Scroll of Alacrity
from.CloseGump(typeof( ScrollofAlacrity.InternalGump ) );
#endregion
from.SendGump( new InternalGump( from, this ) );
}
else

View file

@ -85,7 +85,7 @@ namespace Server.Items
elemental.Opposition = new SlayerGroup[]{ abyss };
elemental.FoundOn = new Type[]{ typeof( Balron ), typeof( Daemon ) };
elemental.Super = new SlayerEntry( SlayerName.ElementalBan,/* typeof( AcidElemental ),*/ typeof( AgapiteElemental ), typeof( AirElemental ), typeof( SummonedAirElemental ), typeof( BloodElemental ), typeof( BronzeElemental ), typeof( CopperElemental ), typeof( CrystalElemental ), typeof( DullCopperElemental ), typeof( EarthElemental ), typeof( SummonedEarthElemental ), typeof( Efreet ), typeof( FireElemental ), typeof( SummonedFireElemental ), typeof( GoldenElemental ), typeof( IceElemental ), typeof( KazeKemono ), typeof( PoisonElemental ), typeof( RaiJu ), typeof( SandVortex ), typeof( ShadowIronElemental ), typeof( SnowElemental ), typeof( ValoriteElemental ), typeof( VeriteElemental ), typeof( WaterElemental ), typeof( SummonedWaterElemental ) );
elemental.Super = new SlayerEntry( SlayerName.ElementalBan, typeof( ToxicElemental ), typeof( AgapiteElemental ), typeof( AirElemental ), typeof( SummonedAirElemental ), typeof( BloodElemental ), typeof( BronzeElemental ), typeof( CopperElemental ), typeof( CrystalElemental ), typeof( DullCopperElemental ), typeof( EarthElemental ), typeof( SummonedEarthElemental ), typeof( Efreet ), typeof( FireElemental ), typeof( SummonedFireElemental ), typeof( GoldenElemental ), typeof( IceElemental ), typeof( KazeKemono ), typeof( PoisonElemental ), typeof( RaiJu ), typeof( SandVortex ), typeof( ShadowIronElemental ), typeof( SnowElemental ), typeof( ValoriteElemental ), typeof( VeriteElemental ), typeof( WaterElemental ), typeof( SummonedWaterElemental ) );
elemental.Entries = new SlayerEntry[]
{
new SlayerEntry( SlayerName.BloodDrinking, typeof( BloodElemental ) ),

View file

@ -221,6 +221,14 @@ namespace Server.Misc
}
}
#region Scroll of Alacrity
PlayerMobile pm = from as PlayerMobile;
if ( from is PlayerMobile )
if (pm != null && skill.SkillName == pm.AcceleratedSkill && pm.AcceleratedStart > DateTime.Now)
toGain *= Utility.RandomMinMax(2, 5);
#endregion
if ( !from.Player || (skills.Total + toGain) <= skills.Cap )
{
skill.BaseFixedPoint += toGain;

View file

@ -2494,6 +2494,10 @@ namespace Server.Mobiles
if( TransformationSpellHelper.UnderTransformation( m, typeof( EtherealVoyageSpell ) ) )
continue;
// Ignore players with activated honor
if ( m is PlayerMobile && ( (PlayerMobile)m ).HonorActive )
continue;
if( acqType == FightMode.Aggressor || acqType == FightMode.Evil )
{
// Only acquire this mobile if it attacked us, or if it's evil.

View file

@ -769,6 +769,9 @@ namespace Server.Mobiles
if( TransformationSpellHelper.UnderTransformation( m, typeof( EtherealVoyageSpell ) ) )
return false;
if ( m is PlayerMobile && ( (PlayerMobile)m ).HonorActive )
return false;
BaseCreature c = (BaseCreature)m;
return ( m_iTeam != c.m_iTeam || ( (m_bSummoned || m_bControlled) != (c.m_bSummoned || c.m_bControlled) )/* || c.Combatant == this*/ );

View file

@ -134,19 +134,19 @@ namespace Server.Mobiles
if ( Core.ML )
{
if ( defender.PhysicalResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Physical, defender.PhysicalResistance / 2 ) );
mods.Add( new ResistanceMod( ResistanceType.Physical, -(defender.PhysicalResistance / 2) ) );
if ( defender.FireResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Fire, defender.FireResistance / 2 ) );
mods.Add( new ResistanceMod( ResistanceType.Fire, -(defender.FireResistance / 2) ) );
if ( defender.ColdResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Cold, defender.ColdResistance / 2 ) );
mods.Add( new ResistanceMod( ResistanceType.Cold, -(defender.ColdResistance / 2) ) );
if ( defender.PoisonResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Poison, defender.PoisonResistance / 2 ) );
mods.Add( new ResistanceMod( ResistanceType.Poison, -(defender.PoisonResistance / 2) ) );
if ( defender.EnergyResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Energy, defender.EnergyResistance / 2 ) );
mods.Add( new ResistanceMod( ResistanceType.Energy, -(defender.EnergyResistance / 2) ) );
}
else
{

View file

@ -45,7 +45,11 @@ namespace Server.Mobiles
Young = 0x00000400,
AcceptGuildInvites = 0x00000800,
DisplayChampionTitle = 0x00001000,
HasStatReward = 0x00002000
HasStatReward = 0x00002000,
#region Scroll of Alacrity
AcceleratedSkill = 0x00080000,
#endregion
}
public enum NpcGuild
@ -318,6 +322,27 @@ namespace Server.Mobiles
set{ m_AnkhNextUse = value; }
}
#region Scroll of Alacrity
private DateTime m_AcceleratedStart;
[CommandProperty(AccessLevel.GameMaster)]
public DateTime AcceleratedStart
{
get { return m_AcceleratedStart; }
set { m_AcceleratedStart = value; }
}
private SkillName m_AcceleratedSkill;
[CommandProperty(AccessLevel.GameMaster)]
public SkillName AcceleratedSkill
{
get { return m_AcceleratedSkill; }
set { m_AcceleratedSkill = value; }
}
#endregion
public static Direction GetDirection4( Point3D from, Point3D to )
{
int dx = from.X - to.X;
@ -345,6 +370,16 @@ namespace Server.Mobiles
if ( !base.OnDroppedItemToWorld( item, location ) )
return false;
IPooledEnumerable mobiles = Map.GetMobilesInRange( location, 0 );
if ( mobiles.GetEnumerator().MoveNext() )
{
mobiles.Free();
return false;
}
else
mobiles.Free();
BounceInfo bi = item.GetBounce();
if ( bi != null )

View file

@ -251,7 +251,7 @@ namespace Server.Mobiles
}
else
{
SayTo( from, 1042558 ); /* I charge 30 gold per pet for a real week's stable time.
from.SendLocalizedMessage( 1042558 ); /* I charge 30 gold per pet for a real week's stable time.
* I will withdraw it from thy bank account.
* Which animal wouldst thou like to stable here?
*/
@ -313,7 +313,7 @@ namespace Server.Mobiles
from.Stabled.Add( pet );
SayTo( from, 502679 ); // Very well, thy pet is stabled. Thou mayst recover it by saying 'claim' to me. In one real world week, I shall sell it off if it is not claimed!
SayTo( from, Core.AOS ? 1049677 : 502679 ); // [AOS: Your pet has been stabled.] Very well, thy pet is stabled. Thou mayst recover it by saying 'claim' to me. In one real world week, I shall sell it off if it is not claimed!
}
else
{

View file

@ -180,7 +180,8 @@ namespace Server.SkillHandlers
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502805, from.NetState ); // You seem to anger the beast!
creature.PlaySound( creature.GetAngerSound() );
creature.Direction = creature.GetDirectionTo( from );
creature.Combatant = from;
if ( from is PlayerMobile && !( (PlayerMobile)from ).HonorActive )
creature.Combatant = from;
}
else
{

View file

@ -116,7 +116,7 @@ namespace Server.Spells.Necromancy
typeof( ValoriteElemental ), typeof( VeriteElemental ), typeof( PoisonElemental ),
typeof( FireElemental ), typeof( SummonedFireElemental ), typeof( SnowElemental ),
typeof( AirElemental ), typeof( SummonedAirElemental ), typeof( WaterElemental ),
typeof( SummonedAirElemental )
typeof( SummonedAirElemental ), typeof ( ToxicElemental )
}, new SummonEntry[]
{
new SummonEntry( 5000, typeof( WailingBanshee ) ),