This commit is contained in:
mark 2009-06-28 03:36:42 +00:00
parent c63a5f13fa
commit 2204d5fb86
86 changed files with 1077 additions and 257 deletions

View file

@ -272,7 +272,33 @@ namespace Server.Commands
public static void GetFollowers_OnTarget( Mobile from, object obj )
{
if ( obj is Mobile && ((Mobile)obj).Player )
if ( obj is PlayerMobile )
{
PlayerMobile master = (PlayerMobile)obj;
List<Mobile> pets = master.AllFollowers;
if ( pets.Count > 0 )
{
CommandLogging.WriteLine( from, "{0} {1} getting all followers of {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( master ) );
from.SendMessage( "That player has {0} pet{1}.", pets.Count, pets.Count != 1 ? "s" : "" );
for ( int i = 0; i < pets.Count; ++i )
{
Mobile pet = (Mobile)pets[i];
if ( pet is IMount )
((IMount)pet).Rider = null; // make sure it's dismounted
pet.MoveToWorld( from.Location, from.Map );
}
}
else
{
from.SendMessage( "There were no pets found for that player." );
}
}
else if ( obj is Mobile && ((Mobile)obj).Player )
{
Mobile master = (Mobile)obj;
ArrayList pets = new ArrayList();

View file

@ -1096,6 +1096,7 @@ namespace Server.Mobiles
case OrderType.Stop:
m_Mobile.ControlMaster.RevealingAction();
m_Mobile.Home = m_Mobile.Location;
m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed;
m_Mobile.PlaySound( m_Mobile.GetIdleSound() );
m_Mobile.Warmode = false;
@ -1476,13 +1477,9 @@ namespace Server.Mobiles
Mobile newCombatant = null;
double newScore = 0.0;
List<AggressorInfo> list = m_Mobile.Aggressors;
for( int i = 0; i < list.Count; ++i )
foreach( Mobile aggr in m_Mobile.GetMobilesInRange( m_Mobile.RangePerception ) )
{
Mobile aggr = list[i].Attacker;
if( aggr.Map != m_Mobile.Map || !aggr.InRange( m_Mobile.Location, m_Mobile.RangePerception ) || !m_Mobile.CanSee( aggr ) )
if( !m_Mobile.CanSee( aggr ) || aggr.Combatant != m_Mobile )
continue;
if( aggr.IsDeadBondedPet || !aggr.Alive )
@ -1571,7 +1568,15 @@ namespace Server.Mobiles
m_Mobile.Home = m_Mobile.Location;
m_Mobile.ControlTarget = null;
m_Mobile.ControlOrder = OrderType.None;
if( Core.ML )
{
WalkRandomInHome( 3, 2, 1 );
}
else
{
m_Mobile.ControlOrder = OrderType.None;
}
return true;
}

View file

@ -55,9 +55,10 @@ namespace Server.Mobiles
[Flags]
public enum FoodType
{
None = 0x0000,
Meat = 0x0001,
FruitsAndVegies = 0x0002,
GrainsAndHay = 0x0004,
FruitsAndVegies = 0x0002,
GrainsAndHay = 0x0004,
Fish = 0x0008,
Eggs = 0x0010,
Gold = 0x0020
@ -170,39 +171,39 @@ namespace Server.Mobiles
#region Var declarations
private BaseAI m_AI; // THE AI
private AIType m_CurrentAI; // The current AI
private AIType m_DefaultAI; // The default AI
private AIType m_CurrentAI; // The current AI
private AIType m_DefaultAI; // The default AI
private Mobile m_FocusMob; // Use focus mob instead of combatant, maybe we don't whan to fight
private FightMode m_FightMode; // The style the mob uses
private FightMode m_FightMode; // The style the mob uses
private int m_iRangePerception; // The view area
private int m_iRangeFight; // The fight distance
private bool m_bDebugAI; // Show debug AI messages
private int m_iTeam; // Monster Team
private bool m_bDebugAI; // Show debug AI messages
private double m_dActiveSpeed; // Timer speed when active
private double m_dPassiveSpeed; // Timer speed when not active
private double m_dCurrentSpeed; // The current speed, lets say it could be changed by something;
private int m_iTeam; // Monster Team
private Point3D m_pHome; // The home position of the creature, used by some AI
private double m_dActiveSpeed; // Timer speed when active
private double m_dPassiveSpeed; // Timer speed when not active
private double m_dCurrentSpeed; // The current speed, lets say it could be changed by something;
private Point3D m_pHome; // The home position of the creature, used by some AI
private int m_iRangeHome = 10; // The home range of the creature
List<Type> m_arSpellAttack; // List of attack spell/power
List<Type> m_arSpellDefense; // List of defensive spell/power
private bool m_bControlled; // Is controlled
private Mobile m_ControlMaster; // My master
private Mobile m_ControlTarget; // My target mobile
private Point3D m_ControlDest; // My target destination (patrol)
private OrderType m_ControlOrder; // My order
private bool m_bControlled; // Is controlled
private Mobile m_ControlMaster; // My master
private Mobile m_ControlTarget; // My target mobile
private Point3D m_ControlDest; // My target destination (patrol)
private OrderType m_ControlOrder; // My order
private int m_Loyalty;
private int m_Loyalty;
private double m_dMinTameSkill;
private bool m_bTamable;
private double m_dMinTameSkill;
private bool m_bTamable;
private bool m_bSummoned = false;
private DateTime m_SummonEnd;
@ -218,20 +219,20 @@ namespace Server.Mobiles
private Mobile m_SummonMaster;
private int m_HitsMax = -1;
private int m_StamMax = -1;
private int m_ManaMax = -1;
private int m_DamageMin = -1;
private int m_DamageMax = -1;
private int m_HitsMax = -1;
private int m_StamMax = -1;
private int m_ManaMax = -1;
private int m_DamageMin = -1;
private int m_DamageMax = -1;
private int m_PhysicalResistance, m_PhysicalDamage = 100;
private int m_FireResistance, m_FireDamage;
private int m_ColdResistance, m_ColdDamage;
private int m_PoisonResistance, m_PoisonDamage;
private int m_EnergyResistance, m_EnergyDamage;
private int m_PhysicalResistance, m_PhysicalDamage = 100;
private int m_FireResistance, m_FireDamage;
private int m_ColdResistance, m_ColdDamage;
private int m_PoisonResistance, m_PoisonDamage;
private int m_EnergyResistance, m_EnergyDamage;
private List<Mobile> m_Owners;
private List<Mobile> m_Friends;
private List<Mobile> m_Owners;
private List<Mobile> m_Friends;
private bool m_IsStabled;
@ -239,6 +240,10 @@ namespace Server.Mobiles
private bool m_Paragon;
private bool m_IsPrisoner;
private Timer m_GhostDeletionTimer;
#endregion
public virtual InhumanSpeech SpeechType{ get{ return null; } }
@ -246,9 +251,20 @@ namespace Server.Mobiles
public bool IsStabled
{
get{ return m_IsStabled; }
set{ m_IsStabled = value; }
set
{
m_IsStabled = value;
SetGhostDeletionTimer( !m_IsStabled );
}
}
[CommandProperty( AccessLevel.GameMaster )]
public bool IsPrisoner
{
get{ return m_IsPrisoner; }
set{ m_IsPrisoner = value; }
}
protected DateTime SummonEnd
{
get { return m_SummonEnd; }
@ -402,6 +418,7 @@ namespace Server.Mobiles
public virtual bool BardImmune{ get{ return false; } }
public virtual bool Unprovokable{ get{ return BardImmune || m_IsDeadPet; } }
public virtual bool Uncalmable{ get{ return BardImmune || m_IsDeadPet; } }
public virtual bool AreaPeaceImmune { get { return BardImmune || m_IsDeadPet; } }
public virtual bool BleedImmune{ get{ return false; } }
public virtual double BonusPetDamageScalar{ get{ return 1.0; } }
@ -824,16 +841,38 @@ namespace Server.Mobiles
int taming = (int)((useBaseSkill ? m.Skills[SkillName.AnimalTaming].Base : m.Skills[SkillName.AnimalTaming].Value ) * 10);
int lore = (int)((useBaseSkill ? m.Skills[SkillName.AnimalLore].Base : m.Skills[SkillName.AnimalLore].Value )* 10);
int bonus = 0, chance = 700;
int difficulty = (int)(dMinTameSkill * 10);
int weighted = ((taming * 4) + lore) / 5;
int bonus = weighted - difficulty;
int chance;
if( Core.ML )
{
int SkillBonus = taming - (int)(dMinTameSkill * 10);
int LoreBonus = lore - (int)(dMinTameSkill * 10);
if ( bonus <= 0 )
chance = 700 + (bonus * 14);
int SkillMod = 6, LoreMod = 6;
if( SkillBonus < 0 )
SkillMod = 28;
if( LoreBonus < 0 )
LoreMod = 14;
SkillBonus *= SkillMod;
LoreBonus *= LoreMod;
bonus = (SkillBonus + LoreBonus ) / 2;
}
else
chance = 700 + (bonus * 6);
{
int difficulty = (int)(dMinTameSkill * 10);
int weighted = ((taming * 4) + lore) / 5;
bonus = weighted - difficulty;
if ( bonus <= 0 )
bonus *= 14;
else
bonus *= 6;
}
chance += bonus;
if ( chance >= 0 && chance < 200 )
chance = 200;
@ -1693,6 +1732,8 @@ namespace Server.Mobiles
if ( IsAnimatedDead )
Spells.Necromancy.AnimateDeadSpell.Register( m_SummonMaster, this );
SetGhostDeletionTimer( true );
}
public virtual bool IsHumanInTown()
@ -2215,9 +2256,23 @@ namespace Server.Mobiles
public void RemoveFollowers()
{
if ( m_ControlMaster != null )
{
m_ControlMaster.Followers -= ControlSlots;
if( m_ControlMaster is PlayerMobile )
{
((PlayerMobile)m_ControlMaster).AllFollowers.Remove( this );
if( ((PlayerMobile)m_ControlMaster).AutoStabled.Contains( this ) )
((PlayerMobile)m_ControlMaster).AutoStabled.Remove( this );
}
}
else if ( m_SummonMaster != null )
{
m_SummonMaster.Followers -= ControlSlots;
if( m_SummonMaster is PlayerMobile )
{
((PlayerMobile)m_SummonMaster).AllFollowers.Remove( this );
}
}
if ( m_ControlMaster != null && m_ControlMaster.Followers < 0 )
m_ControlMaster.Followers = 0;
@ -2229,9 +2284,21 @@ namespace Server.Mobiles
public void AddFollowers()
{
if ( m_ControlMaster != null )
{
m_ControlMaster.Followers += ControlSlots;
if( m_ControlMaster is PlayerMobile )
{
((PlayerMobile)m_ControlMaster).AllFollowers.Add( this );
}
}
else if ( m_SummonMaster != null )
{
m_SummonMaster.Followers += ControlSlots;
if( m_SummonMaster is PlayerMobile )
{
((PlayerMobile)m_SummonMaster).AllFollowers.Add( this );
}
}
}
[CommandProperty( AccessLevel.GameMaster )]
@ -2833,8 +2900,22 @@ namespace Server.Mobiles
{
base.AggressiveAction( aggressor, criminal );
OrderType ct = m_ControlOrder;
if ( m_AI != null )
m_AI.OnAggressiveAction( aggressor );
{
if( !Core.ML || ( ct != OrderType.Follow && ct != OrderType.Stop ) )
{
m_AI.OnAggressiveAction( aggressor );
}
else
{
DebugSay( "I'm being attacked but my master told me not to fight." );
Warmode = false;
Combatant = null;
return;
}
}
StopFlee();
@ -2848,9 +2929,7 @@ namespace Server.Mobiles
pl.FinishShield();
}
OrderType ct = m_ControlOrder;
if ( aggressor.ChangingCombatant && (m_bControlled || m_bSummoned) && (ct == OrderType.Come || ct == OrderType.Stay || ct == OrderType.Stop || ct == OrderType.None || ct == OrderType.Follow) )
if ( aggressor.ChangingCombatant && (m_bControlled || m_bSummoned) && (ct == OrderType.Come || ( !Core.ML && ct == OrderType.Stay ) || ct == OrderType.Stop || ct == OrderType.None || ct == OrderType.Follow) )
{
ControlTarget = aggressor;
ControlOrder = OrderType.Attack;
@ -2874,7 +2953,7 @@ namespace Server.Mobiles
{
}
public virtual bool CanDrop { get { return !Summoned; } }
public virtual bool CanDrop { get { return IsBonded; } }
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
@ -4182,6 +4261,8 @@ namespace Server.Mobiles
GiftOfLifeSpell.HandleDeath( this );
CheckStatTimers();
SetGhostDeletionTimer( true );
}
else
{
@ -4801,8 +4882,26 @@ namespace Server.Mobiles
}
CheckStatTimers();
SetGhostDeletionTimer( false );
}
private void SetGhostDeletionTimer( bool running )
{
if( running && ( !IsDeadBondedPet || !Core.ML ) )
return;
if( m_GhostDeletionTimer != null )
m_GhostDeletionTimer.Stop();
if( !running )
return;
m_GhostDeletionTimer = new GhostDeletionTimer( this, TimeSpan.FromMinutes( 120 + Utility.Random( 120 ) ) );
m_GhostDeletionTimer.Start();
}
public override bool CanBeDamaged()
{
if ( IsDeadPet )
@ -4839,6 +4938,26 @@ namespace Server.Mobiles
[CommandProperty( AccessLevel.GameMaster )]
public int RemoveStep { get { return m_RemoveStep; } set { m_RemoveStep = value; } }
private class GhostDeletionTimer : Timer
{
private BaseCreature m_Creature;
public GhostDeletionTimer( BaseCreature Creature, TimeSpan delay ) : base( delay )
{
Priority = TimerPriority.FiveSeconds;
m_Creature = Creature;
}
protected override void OnTick()
{
if( Core.ML && m_Creature.IsDeadBondedPet );
{
m_Creature.Delete();
}
Stop();
}
}
}
public class LoyaltyTimer : Timer

View file

@ -118,7 +118,7 @@ namespace Server
typeof( SnowElemental ), typeof( WhiteWyrm ), typeof( Wisp ),
typeof( DemonKnight ), typeof( GiantBlackWidow ), typeof( SummonedAirElemental ),
typeof( LesserHiryu ), typeof( Hiryu ), typeof( LadyOfTheSnow ),
typeof( RaiJu ), typeof( Ronin )
typeof( RaiJu ), typeof( Ronin ), typeof( RuneBeetle )
} ),
/* Very Fast */
new SpeedInfo( 0.175, 0.350, new Type[]
@ -206,7 +206,7 @@ namespace Server
typeof( Kappa ), typeof( KazeKemono ), typeof( DeathwatchBeetle ),
typeof( TsukiWolf ), typeof( YomotsuElder ), typeof( YomotsuPriest ),
typeof( YomotsuWarrior ), typeof( RevenantLion ), typeof( Oni ),
typeof( RuneBeetle ), typeof( Gaman ), typeof( Crane )
typeof( Gaman ), typeof( Crane )
} )
};
}

View file

@ -7,6 +7,7 @@ using Server.Multis;
using Server.Prompts;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Items;
namespace Server.Engines.BulkOrders
{
@ -63,6 +64,34 @@ namespace Server.Engines.BulkOrders
from.SendGump( new BOBGump( (PlayerMobile)from, this ) );
}
public override void OnDoubleClickSecureTrade( Mobile from )
{
if ( !from.InRange( GetWorldLocation(), 2 ) )
{
from.SendLocalizedMessage( 500446 ); // That is too far away.
}
else if ( m_Entries.Count == 0 )
{
from.SendLocalizedMessage( 1062381 ); // The book is empty.
}
else
{
from.SendGump( new BOBGump( (PlayerMobile)from, this ) );
SecureTradeContainer cont = GetSecureTradeCont();
if ( cont != null )
{
SecureTrade trade = cont.Trade;
if ( trade != null && trade.From.Mobile == from )
trade.To.Mobile.SendGump( new BOBGump( (PlayerMobile)(trade.To.Mobile), this ) );
else if ( trade != null && trade.To.Mobile == from )
trade.From.Mobile.SendGump( new BOBGump( (PlayerMobile)(trade.From.Mobile), this ) );
}
}
}
public override bool OnDragDrop( Mobile from, Item dropped )
{
if ( dropped is LargeBOD )

View file

@ -56,12 +56,10 @@ namespace Server.Engines.Harvest
if ( m_Definition.RandomizeVeins )
{
m_Vein = m_Definition.GetVeinFrom( Utility.RandomDouble() );
}
else
{
m_Vein = m_DefaultVein;
m_DefaultVein = m_Definition.GetVeinFrom( Utility.RandomDouble() );
}
m_Vein = m_DefaultVein;
}
public void Consume( int amount, Mobile from )

View file

@ -91,6 +91,15 @@ namespace Server.Engines.Harvest
fish.Resources = res;
fish.Veins = veins;
if ( Core.ML )
{
fish.BonusResources = new BonusHarvestResource[]
{
new BonusHarvestResource( 0, 99.4, null, null ), //set to same chance as mining ml gems
new BonusHarvestResource( 80.0, .6, 1072597, typeof( WhitePearl ) )
};
}
m_Definition = fish;
Definitions.Add( fish );
#endregion

View file

@ -114,13 +114,13 @@ namespace Server.Engines.Harvest
{
oreAndStone.BonusResources = new BonusHarvestResource[]
{
new BonusHarvestResource( 0, 99.8998, null, null ), //Nothing //Note: Rounded the below to .0167 instead of 1/6th of a %. Close enough
new BonusHarvestResource( 100, .0167, 1072562, typeof( BlueDiamond ) ),
new BonusHarvestResource( 100, .0167, 1072567, typeof( DarkSapphire ) ),
new BonusHarvestResource( 100, .0167, 1072570, typeof( EcruCitrine ) ),
new BonusHarvestResource( 100, .0167, 1072564, typeof( FireRuby ) ),
new BonusHarvestResource( 100, .0167, 1072566, typeof( PerfectEmerald ) ),
new BonusHarvestResource( 100, .0167, 1072568, typeof( Turquoise ) )
new BonusHarvestResource( 0, 99.4, null, null ), //Nothing
new BonusHarvestResource( 100, .1, 1072562, typeof( BlueDiamond ) ),
new BonusHarvestResource( 100, .1, 1072567, typeof( DarkSapphire ) ),
new BonusHarvestResource( 100, .1, 1072570, typeof( EcruCitrine ) ),
new BonusHarvestResource( 100, .1, 1072564, typeof( FireRuby ) ),
new BonusHarvestResource( 100, .1, 1072566, typeof( PerfectEmerald ) ),
new BonusHarvestResource( 100, .1, 1072568, typeof( Turquoise ) )
};
}

View file

@ -166,13 +166,13 @@ namespace Server.PathAlgorithms.FastAStar
int newCost = m_Nodes[bestNode].cost + 1;
int newTotal = newCost + Heuristic( newNode % AreaSize, (newNode / AreaSize) % AreaSize, m_Nodes[newNode].z );
if ( m_Nodes[newNode].total > newTotal )
if ( !wasTouched || m_Nodes[newNode].total > newTotal )
{
m_Nodes[newNode].parent = bestNode;
m_Nodes[newNode].cost = newCost;
m_Nodes[newNode].total = newTotal;
if ( !m_OnOpen[newNode] )
if ( !wasTouched || !m_OnOpen[newNode] )
{
AddToChain( newNode );

View file

@ -149,8 +149,8 @@ namespace Server
{
alg = FastAStarAlgorithm.Instance;
if ( !alg.CheckCondition( m, map, start, goal ) )
alg = SlowAStarAlgorithm.Instance;
//if ( !alg.CheckCondition( m, map, start, goal ) ) // SlowAstar is still broken
// alg = SlowAStarAlgorithm.Instance; // TODO: Fix SlowAstar
}
if ( alg != null && alg.CheckCondition( m, map, start, goal ) )

View file

@ -92,6 +92,8 @@ namespace Server.Gumps
if ( m_Mobile.AccessLevel >= AccessLevel.GameMaster )
{
m_Mobile.SendMessage( "You do not get a refund for your house as you are not a player" );
m_House.RemoveKeys(m_Mobile);
m_House.Delete();
}
else
{

View file

@ -59,6 +59,8 @@ namespace Server.Items
public class BarrelHoops : Item
{
public override int LabelNumber { get { return 1011228; } } // Barrel hoops
[Constructable]
public BarrelHoops() : base(0x1DB7)
{

View file

@ -194,7 +194,7 @@ namespace Server.Items
get {
if ( Core.ML ) {
Mobile m = ParentEntity as Mobile;
if ( m != null && m.Backpack == this ) {
if ( m != null && m.Player && m.Backpack == this ) {
return 550;
} else {
return base.DefaultMaxWeight;

View file

@ -106,7 +106,9 @@ namespace Server.Items
public void EndPlace( Mobile from, HolidayTreeType type, Point3D loc )
{
this.Delete();
new HolidayTree( from, type, loc );
HolidayTree tree = new HolidayTree( from, type, loc );
BaseHouse house = BaseHouse.FindHouseAt( tree );
house.Addons.Add( tree );
}
public override void OnDoubleClick( Mobile from )

View file

@ -157,7 +157,7 @@ namespace Server.Items
[Constructable]
public SushiPlatter() : base( 0x2840 )
{
Stackable = false;
Stackable = Core.ML;
Weight = 3.0;
FillFactor = 2;
}

View file

@ -26,6 +26,7 @@ namespace Server.Items
[Constructable]
public Dough() : base( 0x103d )
{
Stackable = Core.ML;
Weight = 1.0;
}
@ -124,6 +125,7 @@ namespace Server.Items
[Constructable]
public SweetDough() : base( 0x103d )
{
Stackable = Core.ML;
Weight = 1.0;
Hue = 150;
}

View file

@ -688,7 +688,7 @@ namespace Server.Items
[Constructable]
public Cookies() : base( 0x160b )
{
Stackable = false;
Stackable = Core.ML;
this.Weight = 1.0;
this.FillFactor = 4;
}
@ -997,7 +997,7 @@ namespace Server.Items
[Constructable]
public Quiche() : base( 0x1041 )
{
Stackable = false;
Stackable = Core.ML;
this.Weight = 1.0;
this.FillFactor = 5;
}

View file

@ -16,6 +16,7 @@ namespace Server.Items
[Constructable]
public ArcaneGem() : base( 0x1EA7 )
{
Stackable = Core.ML;
Weight = 1.0;
}

View file

@ -929,6 +929,16 @@ namespace Server.Items
public void Carve( Mobile from, Item item )
{
if ( IsCriminalAction( from ) && this.Map != null && (this.Map.Rules & MapRules.HarmfulRestrictions) != 0 )
{
if ( m_Owner == null || !m_Owner.Player )
from.SendLocalizedMessage( 1005035 ); // You did not earn the right to loot this creature!
else
from.SendLocalizedMessage( 1010049 ); // You may not loot this corpse.
return;
}
Mobile dead = m_Owner;
if ( m_Carved || dead == null )

View file

@ -14,6 +14,7 @@ namespace Server.Items
{
Hue = 2101;
Weight = 2.0;
Stackable = Core.ML;
}
public TribalPaint( Serial serial ) : base( serial )

View file

@ -26,7 +26,7 @@ namespace Server.Items
public BigFish() : base( 0x09CC )
{
Weight = Utility.RandomMinMax( 3, 200 ); //TODO: Find correct formula. max on OSI currently 200, OSI dev says it's not 200 as max, and ~ 1/1,000,000 chance to get highest
Hue = 0x847;
Hue = Utility.RandomBool() ? 0x847 : 0x58C;
}
public override void GetProperties( ObjectPropertyList list )

View file

@ -71,6 +71,7 @@ namespace Server.Items
else
list.Add( CraftResources.GetName( m_Resource ) );
}
Stackable = Core.ML;
}
}

View file

@ -146,6 +146,8 @@ namespace Server.Items
public class TrophyAddon : Item, IAddon
{
public override bool ForceShowProperties { get { return ObjectPropertyList.Enabled; } }
private int m_WestID;
private int m_NorthID;
private int m_DeedNumber;

View file

@ -134,12 +134,20 @@ namespace Server.Items
m.Animate( 34, 5, 1, true, false, 0 );
}
public static int EnhancePotions( Mobile m )
{
int EP = AosAttributes.GetValue( m, AosAttribute.EnhancePotions );
if ( Core.ML && EP > 50 )
EP = 50;
return EP;
}
public static TimeSpan Scale( Mobile m, TimeSpan v )
{
if ( !Core.AOS )
return v;
double scalar = 1.0 + (0.01 * AosAttributes.GetValue( m, AosAttribute.EnhancePotions ));
double scalar = 1.0 + ( 0.01 * EnhancePotions( m ) );
return TimeSpan.FromSeconds( v.TotalSeconds * scalar );
}
@ -149,7 +157,7 @@ namespace Server.Items
if ( !Core.AOS )
return v;
double scalar = 1.0 + (0.01 * AosAttributes.GetValue( m, AosAttribute.EnhancePotions ));
double scalar = 1.0 + ( 0.01 * EnhancePotions( m ) );
return v * scalar;
}
@ -159,7 +167,7 @@ namespace Server.Items
if ( !Core.AOS )
return v;
return AOS.Scale( v, 100 + AosAttributes.GetValue( m, AosAttribute.EnhancePotions ) );
return AOS.Scale( v, 100 + EnhancePotions( m ) );
}
public override bool StackWith( Mobile from, Item dropped, bool playSound )

View file

@ -276,7 +276,7 @@ namespace Server.Items
public override void OnDoubleClick( Mobile from )
{
if ( from.InRange( GetWorldLocation(), 1 ) )
if ( from.InRange( GetWorldLocation(), (Core.ML ? 3 : 1) ) )
{
if ( DateTime.Now < NextUse )
{
@ -294,22 +294,22 @@ namespace Server.Items
NextUse = DateTime.Now + UseDelay;
}
public override void OnAfterDuped( Item newItem )
{
Runebook book = newItem as Runebook;
public override void OnAfterDuped( Item newItem )
{
Runebook book = newItem as Runebook;
if ( book == null )
return;
if ( book == null )
return;
book.m_Entries = new List<RunebookEntry>();
for ( int i = 0; i < m_Entries.Count; i++ )
{
RunebookEntry entry = m_Entries[i];
for ( int i = 0; i < m_Entries.Count; i++ )
{
RunebookEntry entry = m_Entries[i];
book.m_Entries.Add( new RunebookEntry( entry.Location, entry.Map, entry.Description, entry.House ) );
}
}
book.m_Entries.Add( new RunebookEntry( entry.Location, entry.Map, entry.Description, entry.House ) );
}
}
public bool CheckAccess( Mobile m )
{

View file

@ -16,6 +16,7 @@ namespace Server.Items
public ArcaneCircleScroll( int amount )
: base( 600, 0x2D51, amount )
{
Hue = 0x8FD;
}
public ArcaneCircleScroll( Serial serial )
@ -50,6 +51,7 @@ namespace Server.Items
public GiftOfRenewalScroll( int amount )
: base( 601, 0x2D52, amount )
{
Hue = 0x8FD;
}
public GiftOfRenewalScroll( Serial serial )
@ -84,6 +86,7 @@ namespace Server.Items
public ImmolatingWeaponScroll( int amount )
: base( 602, 0x2D53, amount )
{
Hue = 0x8FD;
}
public ImmolatingWeaponScroll( Serial serial )
@ -118,6 +121,7 @@ namespace Server.Items
public AttuneWeaponScroll( int amount )
: base( 603, 0x2D54, amount )
{
Hue = 0x8FD;
}
public AttuneWeaponScroll( Serial serial )
@ -152,6 +156,7 @@ namespace Server.Items
public ThunderstormScroll( int amount )
: base( 604, 0x2D55, amount )
{
Hue = 0x8FD;
}
public ThunderstormScroll( Serial serial )
@ -186,6 +191,7 @@ namespace Server.Items
public NatureFuryScroll( int amount )
: base( 605, 0x2D56, amount )
{
Hue = 0x8FD;
}
public NatureFuryScroll( Serial serial )
@ -220,6 +226,7 @@ namespace Server.Items
public SummonFeyScroll( int amount )
: base( 606, 0x2D57, amount )
{
Hue = 0x8FD;
}
public SummonFeyScroll( Serial serial )
@ -254,6 +261,7 @@ namespace Server.Items
public SummonFiendScroll( int amount )
: base( 607, 0x2D58, amount )
{
Hue = 0x8FD;
}
public SummonFiendScroll( Serial serial )
@ -288,6 +296,7 @@ namespace Server.Items
public ReaperFormScroll( int amount )
: base( 608, 0x2D59, amount )
{
Hue = 0x8FD;
}
public ReaperFormScroll( Serial serial )
@ -322,6 +331,7 @@ namespace Server.Items
public WildfireScroll( int amount )
: base( 609, 0x2D5A, amount )
{
Hue = 0x8FD;
}
public WildfireScroll( Serial serial )
@ -356,6 +366,7 @@ namespace Server.Items
public EssenceOfWindScroll( int amount )
: base( 610, 0x2D5B, amount )
{
Hue = 0x8FD;
}
public EssenceOfWindScroll( Serial serial )
@ -390,6 +401,7 @@ namespace Server.Items
public DryadAllureScroll( int amount )
: base( 611, 0x2D5C, amount )
{
Hue = 0x8FD;
}
public DryadAllureScroll( Serial serial )
@ -424,6 +436,7 @@ namespace Server.Items
public EtherealVoyageScroll( int amount )
: base( 612, 0x2D5D, amount )
{
Hue = 0x8FD;
}
public EtherealVoyageScroll( Serial serial )
@ -458,6 +471,7 @@ namespace Server.Items
public WordOfDeathScroll( int amount )
: base( 613, 0x2D5E, amount )
{
Hue = 0x8FD;
}
public WordOfDeathScroll( Serial serial )
@ -492,6 +506,7 @@ namespace Server.Items
public GiftOfLifeScroll( int amount )
: base( 614, 0x2D5F, amount )
{
Hue = 0x8FD;
}
public GiftOfLifeScroll( Serial serial )
@ -526,6 +541,7 @@ namespace Server.Items
public ArcaneEmpowermentScroll( int amount )
: base( 615, 0x2D60, amount )
{
Hue = 0x8FD;
}
public ArcaneEmpowermentScroll( Serial serial )

View file

@ -8,6 +8,7 @@ namespace Server.Items
[Constructable]
public EggBomb() : base( 0x2809 )
{
Stackable = Core.ML;
Weight = 1.0;
}

View file

@ -8,6 +8,7 @@ namespace Server.Items
[Constructable]
public SmokeBomb() : base( 0x2808 )
{
Stackable = Core.ML;
Weight = 1.0;
}

View file

@ -26,7 +26,7 @@ namespace Server.Items
[Constructable]
public Sand( int amount ) : base( 0x11EA )
{
Stackable = false;
Stackable = Core.ML;
Weight = 1.0;
}

View file

@ -492,7 +492,13 @@ namespace Server.Items
/* Begin Sheilds */
case 0: ApplyAttribute( primary, min, max, AosAttribute.SpellChanneling, 1, 1 ); break;
case 1: ApplyAttribute( primary, min, max, AosAttribute.DefendChance, 1, 15 ); break;
case 2: ApplyAttribute( primary, min, max, AosAttribute.AttackChance, 1, 15 ); break;
case 2:
if (Core.ML) {
ApplyAttribute( primary, min, max, AosAttribute.ReflectPhysical, 1, 15 );
} else {
ApplyAttribute( primary, min, max, AosAttribute.AttackChance, 1, 15 );
}
break;
case 3: ApplyAttribute( primary, min, max, AosAttribute.CastSpeed, 1, 1 ); break;
/* Begin Armor */
case 4: ApplyAttribute( secondary, min, max, AosArmorAttribute.LowerStatReq, 10, 100, 10 ); break;

View file

@ -2,6 +2,7 @@ using System;
using System.Collections;
using Server.Network;
using Server.Items;
using Server.Multis;
namespace Server.Items
{
@ -11,7 +12,7 @@ namespace Server.Items
Modern
}
public class HolidayTree : Item
public class HolidayTree : Item, IAddon
{
private ArrayList m_Components;
private Mobile m_Placer;
@ -208,6 +209,16 @@ namespace Server.Items
{
}
public bool CouldFit( IPoint3D p, Map map )
{
return map.CanFit( (Point3D)p, 20 );
}
Item IAddon.Deed
{
get{ return new HolidayTreeDeed(); }
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
@ -253,8 +264,22 @@ namespace Server.Items
break;
}
}
ValidatePlacement();
}
public void ValidatePlacement()
{
BaseHouse house = BaseHouse.FindHouseAt( this );
if ( house == null )
{
HolidayTreeDeed deed = new HolidayTreeDeed();
deed.MoveToWorld( Location, Map );
Delete();
}
}
public override void OnDoubleClick( Mobile from )
{
if ( from.InRange( this.GetWorldLocation(), 1 ) )
@ -265,6 +290,13 @@ namespace Server.Items
this.Delete();
BaseHouse house = BaseHouse.FindHouseAt( this );
if ( house != null && house.Addons.Contains( this ) )
{
house.Addons.Remove( this );
}
from.SendLocalizedMessage( 503393 ); // A deed for the tree has been placed in your backpack.
}
else

View file

@ -7,6 +7,8 @@ using Server.Targeting;
using Server.ContextMenus;
using Server.Network;
using Server.Regions;
using Server.Spells;
using Server.Spells.Ninjitsu;
namespace Server.Items
{
@ -144,20 +146,27 @@ namespace Server.Items
public override void OnDoubleClick( Mobile from )
{
if ( this.RootParent == from ) // TODO: Previous implementation allowed use on ground, without house protection checks. What is the correct behavior?
if ( this.RootParent != from ) // TODO: Previous implementation allowed use on ground, without house protection checks. What is the correct behavior?
{
if ( Pet == null )
{
LinkPet( from );
}
else
{
SummonPet( from );
}
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1042001 ); // That must be in your pack for you to use it.
return;
}
AnimalFormContext animalContext = AnimalForm.GetContext( from );
if( Core.ML && animalContext != null )
{
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1080073 ); // You cannot use a Crystal Ball of Pet Summoning while in animal form.
return;
}
if ( Pet == null )
{
LinkPet( from );
}
else
{
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1042001 ); // That must be in your pack for you to use it.
CastSummonPet( from );
}
}
@ -220,7 +229,7 @@ namespace Server.Items
}
}
public void SummonPet( Mobile from )
public void CastSummonPet( Mobile from )
{
BaseCreature pet = this.Pet;
@ -251,27 +260,48 @@ namespace Server.Items
{
from.Send( new AsciiMessage( this.Serial, this.ItemID, MessageType.Regular, 0x22, 3, "", "You cannot summon your pet to this location." ) );
}
else if ( Core.ML && from is PlayerMobile && DateTime.Now < ((PlayerMobile)from).LastPetBallTime.AddSeconds( 15.0 ) )
{
MessageHelper.SendLocalizedMessageTo( this, from, 1080072, 0x22 ); // You must wait a few seconds before you can summon your pet.
}
else
{
Charges--;
if( Core.ML )
new PetSummoningSpell( this, from ).Cast();
else
SummonPet( from );
}
if ( pet.IsStabled )
{
pet.SetControlMaster( from );
}
if ( pet.Summoned )
pet.SummonMaster = from;
public void SummonPet( Mobile from )
{
BaseCreature pet = this.Pet;
pet.ControlTarget = from;
pet.ControlOrder = OrderType.Follow;
Charges--;
pet.IsStabled = false;
from.Stabled.Remove( pet );
}
if ( pet.IsStabled )
{
pet.SetControlMaster( from );
pet.MoveToWorld( from.Location, from.Map );
if ( pet.Summoned )
pet.SummonMaster = from;
MessageHelper.SendLocalizedMessageTo( this, from, 1054128, 0x43 ); // The Crystal Ball fills with a green mist. Your pet has been summoned.
pet.ControlTarget = from;
pet.ControlOrder = OrderType.Follow;
pet.IsStabled = false;
from.Stabled.Remove( pet );
}
pet.MoveToWorld( from.Location, from.Map );
MessageHelper.SendLocalizedMessageTo( this, from, 1054128, 0x43 ); // The Crystal Ball fills with a green mist. Your pet has been summoned.
if ( from is PlayerMobile )
{
((PlayerMobile)from).LastPetBallTime = DateTime.Now;
}
}
@ -341,5 +371,94 @@ namespace Server.Items
}
}
}
private class PetSummoningSpell : Spell
{
private static SpellInfo m_Info = new SpellInfo( "Ball Of Summoning", "", 230 );
private BallOfSummoning m_Ball;
private Mobile m_Caster;
public PetSummoningSpell( BallOfSummoning ball, Mobile caster )
: base( caster, null, m_Info )
{
m_Caster = caster;
m_Ball = ball;
}
public override bool ClearHandsOnCast { get { return false; } }
public override bool RevealOnCast { get { return true; } }
public override TimeSpan GetCastRecovery()
{
return TimeSpan.Zero;
}
public override double CastDelayFastScalar { get { return 0; } }
public override TimeSpan CastDelayBase
{
get
{
return TimeSpan.FromSeconds( 2.0 );
}
}
public override int GetMana()
{
return 0;
}
public override bool ConsumeReagents()
{
return true;
}
public override bool CheckFizzle()
{
return true;
}
private bool m_Stop;
public void Stop()
{
m_Stop = true;
Disturb( DisturbType.Hurt, false, false );
}
public override bool CheckDisturb( DisturbType type, bool checkFirst, bool resistable )
{
if( type == DisturbType.EquipRequest || type == DisturbType.UseRequest/* || type == DisturbType.Hurt*/ )
return false;
return true;
}
public override void DoHurtFizzle()
{
if( !m_Stop )
base.DoHurtFizzle();
}
public override void DoFizzle()
{
if( !m_Stop )
base.DoFizzle();
}
public override void OnDisturb( DisturbType type, bool message )
{
if( message && !m_Stop )
Caster.SendLocalizedMessage( 1080074 ); // You have been disrupted while attempting to summon your pet!
}
public override void OnCast()
{
m_Ball.SummonPet( m_Caster );
FinishSequence();
}
}
}
}

View file

@ -24,6 +24,22 @@ namespace Server.Items
public abstract class BaseWand : BaseBashing
{
public override WeaponAbility PrimaryAbility { get { return WeaponAbility.Dismount; } }
public override WeaponAbility SecondaryAbility { get { return WeaponAbility.Disarm; } }
public override int AosStrengthReq { get { return 5; } }
public override int AosMinDamage { get { return 9; } }
public override int AosMaxDamage { get { return 11; } }
public override int AosSpeed { get { return 40; } }
public override int OldStrengthReq { get { return 0; } }
public override int OldMinDamage { get { return 2; } }
public override int OldMaxDamage { get { return 6; } }
public override int OldSpeed { get { return 35; } }
public override int InitMinHits { get { return 31; } }
public override int InitMaxHits { get { return 110; } }
private WandEffect m_WandEffect;
private int m_Charges;

View file

@ -33,6 +33,16 @@ namespace Server.Items
return false;
}*/
public override bool RequiresTactics( Mobile from )
{
BaseWeapon weapon = from.Weapon as BaseWeapon;
if ( weapon == null )
return false;
return weapon.Skill != SkillName.Wrestling;
}
public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds( 5.0 );
public override void OnHit( Mobile attacker, Mobile defender, int damage )
@ -53,7 +63,7 @@ namespace Server.Items
{
attacker.SendLocalizedMessage( 1004001 ); // You cannot disarm your opponent.
}
else if ( toDisarm == null || toDisarm is BaseShield || toDisarm is Spellbook )
else if (toDisarm == null || toDisarm is BaseShield || toDisarm is Spellbook && !Core.ML )
{
attacker.SendLocalizedMessage( 1060849 ); // Your target is already unarmed!
}

View file

@ -58,6 +58,11 @@ namespace Server.Items
if ( !CheckMana( attacker, true ) )
return;
if ( Core.ML && attacker is LesserHiryu && 0.8 >= Utility.RandomDouble() )
{
return; //Lesser Hiryu have an 80% chance of missing this attack
}
attacker.SendLocalizedMessage( 1060082 ); // The force of your attack has dislodged them from their mount!
if ( attacker.Mounted )
@ -71,8 +76,15 @@ namespace Server.Items
mount.Rider = null;
BaseMount.SetMountPrevention( defender, BlockMountType.Dazed, DefenderRemountDelay );
BaseMount.SetMountPrevention( attacker, BlockMountType.DismountRecovery, AttackerRemountDelay );
if( Core.ML && attacker is BaseCreature && ((BaseCreature)attacker).ControlMaster != null )
{
BaseMount.SetMountPrevention( ((BaseCreature)attacker).ControlMaster, BlockMountType.DismountRecovery, AttackerRemountDelay );
}
else
{
BaseMount.SetMountPrevention( attacker, BlockMountType.DismountRecovery, AttackerRemountDelay );
}
if ( !attacker.Mounted )
AOS.Damage( defender, attacker, Utility.RandomMinMax( 15, 25 ), 100, 0, 0, 0, 0 );
}

View file

@ -20,6 +20,11 @@ namespace Server.Items
public override int BaseMana{ get{ return 15; } }
public override bool RequiresTactics( Mobile from )
{
return false;
}
public override void OnHit( Mobile attacker, Mobile defender, int damage )
{
if ( !Validate( attacker ) )

View file

@ -13,7 +13,7 @@ namespace Server.Items
}
public override int BaseMana{ get{ return 15; } }
public override double AccuracyScalar{ get{ return 0.75; } }
public override int AccuracyBonus{ get{ return -25; } }
public override bool OnBeforeSwing( Mobile attacker, Mobile defender )
{

View file

@ -38,6 +38,16 @@ namespace Server.Items
return false;
}*/
public override bool RequiresTactics( Mobile from )
{
BaseWeapon weapon = from.Weapon as BaseWeapon;
if ( weapon == null )
return true;
return weapon.Skill != SkillName.Wrestling;
}
public override bool OnBeforeSwing( Mobile attacker, Mobile defender )
{
if( defender.Paralyzed )

View file

@ -16,6 +16,11 @@ namespace Server.Items
public override int BaseMana{ get{ return 20; } }
public override double DamageScalar{ get{ return 1.25; } }
public override bool RequiresTactics( Mobile from )
{
return false;
}
public override bool CheckSkills( Mobile from )
{
if ( !base.CheckSkills( from ) )

View file

@ -11,7 +11,7 @@ namespace Server.Items
{
public virtual int BaseMana{ get{ return 0; } }
public virtual double AccuracyScalar{ get{ return 1.0; } }
public virtual int AccuracyBonus{ get{ return 0; } }
public virtual double DamageScalar{ get{ return 1.0; } }
public virtual bool RequiresSE { get { return false; } }
@ -35,6 +35,11 @@ namespace Server.Items
return true;
}
public virtual bool RequiresTactics( Mobile from )
{
return true;
}
public virtual double GetRequiredSkill( Mobile from )
{
BaseWeapon weapon = from.Weapon as BaseWeapon;
@ -87,6 +92,13 @@ namespace Server.Items
Skill skill = from.Skills[weapon.Skill];
double reqSkill = GetRequiredSkill( from );
bool reqTactics = Core.ML && RequiresTactics( from );
if ( Core.ML && reqTactics && from.Skills[SkillName.Tactics].Base < reqSkill )
{
from.SendLocalizedMessage( 1079308, reqSkill.ToString() ); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
return false;
}
if ( skill != null && skill.Base >= reqSkill )
return true;
@ -96,7 +108,14 @@ namespace Server.Items
return true;
/* </UBWS> */
from.SendLocalizedMessage( 1060182, reqSkill.ToString() ); // You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
if ( reqTactics )
{
from.SendLocalizedMessage( 1079308, reqSkill.ToString() ); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
}
else
{
from.SendLocalizedMessage( 1060182, reqSkill.ToString() ); // You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
}
return false;
}
@ -160,6 +179,11 @@ namespace Server.Items
from.SendLocalizedMessage( 1063024 ); // You cannot perform this special move right now.
return false;
}
if ( Core.ML && from.Spell != null )
{
from.SendLocalizedMessage( 1063024 ); // You cannot perform this special move right now.
return false;
}
return CheckSkills( from ) && CheckMana( from, false );
}

View file

@ -750,9 +750,6 @@ namespace Server.Items
double atkValue = atkWeapon.GetAttackSkillValue( attacker, defender );
double defValue = defWeapon.GetDefendSkillValue( attacker, defender );
//attacker.CheckSkill( atkSkill.SkillName, defValue - 20.0, 120.0 );
//defender.CheckSkill( defSkill.SkillName, atkValue - 20.0, 120.0 );
double ourValue, theirValue;
int bonus = GetHitChanceBonus();
@ -765,12 +762,7 @@ namespace Server.Items
if ( defValue <= -20.0 )
defValue = -19.9;
// Hit Chance Increase = 45%
int atkChance = AosAttributes.GetValue( attacker, AosAttribute.AttackChance );
if ( atkChance > 45 )
atkChance = 45;
bonus += atkChance;
bonus += AosAttributes.GetValue( attacker, AosAttribute.AttackChance );
if ( Spells.Chivalry.DivineFurySpell.UnderEffect( attacker ) )
bonus += 10; // attacker gets 10% bonus when they're under divine fury
@ -781,13 +773,24 @@ namespace Server.Items
if ( HitLower.IsUnderAttackEffect( attacker ) )
bonus -= 25; // Under Hit Lower Attack effect -> 25% malus
ourValue = (atkValue + 20.0) * (100 + bonus);
WeaponAbility ability = WeaponAbility.GetCurrentAbility( attacker );
// Defense Chance Increase = 45%
bonus = AosAttributes.GetValue( defender, AosAttribute.DefendChance );
if ( ability != null )
bonus += ability.AccuracyBonus;
SpecialMove move = SpecialMove.GetCurrentMove( attacker );
if ( move != null )
bonus += move.GetAccuracyBonus( attacker );
// Max Hit Chance Increase = 45%
if ( bonus > 45 )
bonus = 45;
ourValue = (atkValue + 20.0) * (100 + bonus);
bonus = AosAttributes.GetValue( defender, AosAttribute.DefendChance );
if ( Spells.Chivalry.DivineFurySpell.UnderEffect( defender ) )
bonus -= 20; // defender loses 20% bonus when they're under divine fury
@ -810,6 +813,10 @@ namespace Server.Items
if ( SkillHandlers.Discordance.GetEffect( attacker, ref discordanceEffect ) )
bonus -= discordanceEffect;
// Defense Chance Increase = 45%
if ( bonus > 45 )
bonus = 45;
theirValue = (defValue + 20.0) * (100 + bonus);
bonus = 0;
@ -833,19 +840,7 @@ namespace Server.Items
if ( Core.AOS && chance < 0.02 )
chance = 0.02;
WeaponAbility ability = WeaponAbility.GetCurrentAbility( attacker );
if ( ability != null )
chance *= ability.AccuracyScalar;
SpecialMove move = SpecialMove.GetCurrentMove( attacker );
if ( move != null )
chance *= move.GetAccuracyScalar( attacker );
return attacker.CheckSkill( atkSkill.SkillName, chance );
//return ( chance >= Utility.RandomDouble() );
}
public virtual TimeSpan GetDelay( Mobile m )

View file

@ -6,6 +6,9 @@ namespace Server.Items
{
public class MagicWand : BaseBashing
{
public override WeaponAbility PrimaryAbility { get { return WeaponAbility.Dismount; } }
public override WeaponAbility SecondaryAbility { get { return WeaponAbility.Disarm; } }
public override int AosStrengthReq{ get{ return 5; } }
public override int AosMinDamage{ get{ return 9; } }
public override int AosMaxDamage{ get{ return 11; } }

View file

@ -100,7 +100,7 @@ namespace Server
}
#region Dragon Barding
if( (!Core.AOS || from == null || !from.Player) && m.Player && m.Mount is SwampDragon )
if( (from == null || !from.Player) && m.Player && m.Mount is SwampDragon )
{
SwampDragon pet = m.Mount as SwampDragon;

View file

@ -281,6 +281,16 @@ namespace Server.Misc
if ( master != null && master.AccessLevel > AccessLevel.Player )
return Notoriety.CanBeAttacked;
master = bc.ControlMaster;
if ( Core.ML && master != null )
{
if( source == master && CheckAggressor( target.Aggressors, source ) )
return Notoriety.CanBeAttacked;
else
return MobileNotoriety( source, master );
}
if( !bc.Summoned && !bc.Controlled && ((PlayerMobile)source).EnemyOfOneType == target.GetType() )
return Notoriety.Enemy;
}

View file

@ -129,7 +129,7 @@ namespace Server.Misc
CheckBonusSkill( from, from.Mana, from.ManaMax, SkillName.Focus );
double focusPoints = (int)(from.Skills[SkillName.Focus].Value * 0.05);
double focusPoints = (from.Skills[SkillName.Focus].Value * 0.05);
if ( armorPenalty > 0 )
medPoints = 0; // In AOS, wearing any meditation-blocking armor completely removes meditation bonus
@ -154,7 +154,10 @@ namespace Server.Misc
if ( totalPoints < -1 )
totalPoints = -1;
rate = 1.0 / (0.1 * (2 + (int)totalPoints));
if ( Core.ML )
totalPoints = Math.Floor( totalPoints );
rate = 1.0 / (0.1 * (2 + totalPoints));
}
else
{

View file

@ -235,7 +235,7 @@ namespace Server.Mobiles
Timer.DelayCall( TimeSpan.Zero, delegate { Hue = GetHue(); } );
if( version <= 1 )
Timer.DelayCall( TimeSpan.Zero, delegate { InternalItem.Hue = this.Hue; } );
Timer.DelayCall( TimeSpan.Zero, delegate { if( InternalItem != null ) { InternalItem.Hue = this.Hue; } } );
}
}
}

View file

@ -118,12 +118,26 @@ namespace Server.Mobiles
public override double GetControlChance( Mobile m, bool useBaseSkill )
{
double tamingChance = base.GetControlChance( m, useBaseSkill );
if( tamingChance >= 0.95 )
{
return tamingChance;
}
double skill = (useBaseSkill? m.Skills.Bushido.Base : m.Skills.Bushido.Value);
if( skill >= 90.0 )
return 1.0;
if( skill < 90.0 )
{
return tamingChance;
}
return base.GetControlChance( m, useBaseSkill );
double bushidoChance = ( skill - 30.0 ) / 100;
if( m.Skills.Bushido.Base >= 120 )
bushidoChance += 0.05;
return bushidoChance > tamingChance ? bushidoChance : tamingChance;
}
public override int TreasureMapLevel { get { return 3; } }
@ -217,7 +231,7 @@ namespace Server.Mobiles
Timer.DelayCall( TimeSpan.Zero, delegate { Hue = GetHue(); } );
if( version <= 1 )
Timer.DelayCall( TimeSpan.Zero, delegate { InternalItem.Hue = this.Hue; } );
Timer.DelayCall( TimeSpan.Zero, delegate { if( InternalItem != null ) { InternalItem.Hue = this.Hue; } } );
}
}
}

View file

@ -45,7 +45,7 @@ namespace Server.Mobiles
if ( pack != null )
pack.Delete();
pack = new StrongBackpack();
pack = new Backpack();
pack.Movable = false;
AddItem( pack );

View file

@ -66,7 +66,7 @@ namespace Server.Mobiles
public override bool BardImmune{ get{ return !Core.SE; } }
public override bool Unprovokable{ get{ return Core.SE; } }
public override bool Uncalmable{ get{ return Core.SE; } }
public override bool AreaPeaceImmune { get { return Core.SE; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override int TreasureMapLevel{ get{ return 1; } }

View file

@ -50,8 +50,9 @@ namespace Server.Mobiles
AddLoot( LootPack.FilthyRich, 8 );
}
public override bool Unprovokable{ get{ return true; } }
public override bool Uncalmable{ get{ return true; } }
public override bool BardImmune { get { return !Core.SE; } }
public override bool Unprovokable { get { return Core.SE; } }
public override bool AreaPeaceImmune { get { return Core.SE; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override int TreasureMapLevel{ get{ return 1; } }

View file

@ -63,7 +63,7 @@ namespace Server.Mobiles
public override bool BardImmune{ get{ return !Core.SE; } }
public override bool Unprovokable{ get{ return Core.SE; } }
public override bool Uncalmable{ get{ return Core.SE; } }
public override bool AreaPeaceImmune { get { return Core.SE; } }
public override bool BleedImmune{ get{ return true; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override Poison HitPoison{ get{ return Poison.Lethal; } }

View file

@ -213,7 +213,7 @@ namespace Server.Mobiles
public override bool BardImmune{ get{ return !Core.SE; } }
public override bool Unprovokable{ get{ return Core.SE; } }
public override bool Uncalmable{ get{ return Core.SE; } }
public override bool AreaPeaceImmune { get { return Core.SE; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override int TreasureMapLevel{ get{ return 1; } }

View file

@ -63,8 +63,9 @@ namespace Server.Mobiles
}
public override bool AutoDispel{ get{ return true; } }
public override bool Unprovokable{ get{ return true; } }
public override bool Uncalmable{ get{ return true; } }
public override bool BardImmune { get { return !Core.SE; } }
public override bool Unprovokable { get { return Core.SE; } }
public override bool AreaPeaceImmune { get { return Core.SE; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override int TreasureMapLevel{ get{ return 1; } }

View file

@ -66,7 +66,7 @@ namespace Server.Mobiles
public override bool AutoDispel{ get{ return true; } }
public override bool BardImmune{ get{ return !Core.SE; } }
public override bool Unprovokable{ get{ return Core.SE; } }
public override bool Uncalmable{ get{ return Core.SE; } }
public override bool AreaPeaceImmune { get { return Core.SE; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override Poison HitPoison{ get{ return (0.8 >= Utility.RandomDouble() ? Poison.Greater : Poison.Deadly); } }

View file

@ -167,7 +167,9 @@ namespace Server.Mobiles
base.OnThink();
}
public override bool BardImmune{ get{ return true; } }
public override bool BardImmune{ get{ return !Core.SE; } }
public override bool Unprovokable{ get{ return Core.SE; } }
public override bool AreaPeaceImmune{ get{ return Core.SE; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override int TreasureMapLevel{ get{ return 1; } }

View file

@ -14,6 +14,8 @@ namespace Server.Mobiles
public override bool IsBondable{ get{ return false; } }
public override FoodType FavoriteFood { get { return FoodType.None; } }
[Constructable]
public Golem() : this( false, 1.0 )
{
@ -81,7 +83,7 @@ namespace Server.Mobiles
PackItem( new Gears() );
}
ControlSlots = 4;
ControlSlots = 3;
}
public override bool DeleteOnRelease{ get{ return true; } }

View file

@ -131,20 +131,40 @@ namespace Server.Mobiles
List<ResistanceMod> mods = new List<ResistanceMod>();
if ( defender.PhysicalResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Physical, (defender.PhysicalResistance > 70) ? -70 : -defender.PhysicalResistance ) );
if ( Core.ML )
{
if ( defender.PhysicalResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Physical, defender.PhysicalResistance / 2 ) );
if ( defender.FireResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Fire, (defender.FireResistance > 70) ? -70 : -defender.FireResistance ) );
if ( defender.FireResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Fire, defender.FireResistance / 2 ) );
if ( defender.ColdResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Cold, (defender.ColdResistance > 70) ? -70 : -defender.ColdResistance ) );
if ( defender.ColdResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Cold, defender.ColdResistance / 2 ) );
if ( defender.PoisonResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Poison, (defender.PoisonResistance > 70) ? -70 : -defender.PoisonResistance ) );
if ( defender.PoisonResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Poison, defender.PoisonResistance / 2 ) );
if ( defender.EnergyResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Energy, (defender.EnergyResistance > 70) ? -70 : -defender.EnergyResistance ) );
if ( defender.EnergyResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Energy, defender.EnergyResistance / 2 ) );
}
else
{
if ( defender.PhysicalResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Physical, (defender.PhysicalResistance > 70) ? -70 : -defender.PhysicalResistance ) );
if ( defender.FireResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Fire, (defender.FireResistance > 70) ? -70 : -defender.FireResistance ) );
if ( defender.ColdResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Cold, (defender.ColdResistance > 70) ? -70 : -defender.ColdResistance ) );
if ( defender.PoisonResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Poison, (defender.PoisonResistance > 70) ? -70 : -defender.PoisonResistance ) );
if ( defender.EnergyResistance > 0 )
mods.Add( new ResistanceMod( ResistanceType.Energy, (defender.EnergyResistance > 70) ? -70 : -defender.EnergyResistance ) );
}
for ( int i = 0; i < mods.Count; ++i )
defender.AddResistanceMod( mods[i] );

View file

@ -105,7 +105,22 @@ namespace Server.Mobiles
private int m_GuildMessageHue, m_AllianceMessageHue;
private List<Mobile> m_AutoStabled;
private List<Mobile> m_AllFollowers;
#region Getters & Setters
public List<Mobile> AutoStabled { get { return m_AutoStabled; } }
public List<Mobile> AllFollowers
{
get
{
if( m_AllFollowers == null )
m_AllFollowers = new List<Mobile>();;
return m_AllFollowers;
}
}
public Server.Guilds.RankDefinition GuildRank
{
get
@ -516,7 +531,11 @@ namespace Server.Mobiles
}
from.SendGump( new NoticeGump( 1060637, 30720, notice, 0xFFC000, 300, 140, null, null ) );
return;
}
if( from is PlayerMobile )
((PlayerMobile)from).ClaimAutoStabledPets();
}
private bool m_NoDeltaRecursion;
@ -768,6 +787,8 @@ namespace Server.Mobiles
private static void OnLogout( LogoutEventArgs e )
{
if( e.Mobile is PlayerMobile )
((PlayerMobile)e.Mobile).AutoStablePets();
}
private static void EventSink_Connected( ConnectedEventArgs e )
@ -989,6 +1010,9 @@ namespace Server.Mobiles
strBase = this.Str; //this.Str already includes GetStatOffset/str
strOffs = AosAttributes.GetValue( this, AosAttribute.BonusHits );
if ( Core.ML && strOffs > 25 )
strOffs = 25;
if ( AnimalForm.UnderTransformation( this, typeof( BakeKitsune ) ) || AnimalForm.UnderTransformation( this, typeof( GreyWolf ) ) )
strOffs += 20;
}
@ -1998,6 +2022,7 @@ namespace Server.Mobiles
private TimeSpan m_LongTermElapse;
private DateTime m_SessionStart;
private DateTime m_LastEscortTime;
private DateTime m_LastPetBallTime;
private DateTime m_NextSmithBulkOrder;
private DateTime m_NextTailorBulkOrder;
private DateTime m_SavagePaintExpiration;
@ -2072,8 +2097,17 @@ namespace Server.Mobiles
set{ m_LastEscortTime = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public DateTime LastPetBallTime
{
get{ return m_LastPetBallTime; }
set{ m_LastPetBallTime = value; }
}
public PlayerMobile()
{
m_AutoStabled = new List<Mobile>();
m_VisList = new List<Mobile>();
m_PermaFlags = new List<Mobile>();
m_AntiMacroTable = new Hashtable();
@ -2260,6 +2294,9 @@ namespace Server.Mobiles
if ( target is BaseCreature && ((BaseCreature)target).InitialInnocent && !((BaseCreature)target).Controlled )
return false;
if ( Core.ML && target is BaseCreature && ((BaseCreature)target).Controlled && this == ((BaseCreature)target).ControlMaster )
return false;
return base.IsHarmfulCriminal( target );
}
@ -2319,6 +2356,11 @@ namespace Server.Mobiles
switch ( version )
{
case 26:
{
m_AutoStabled = reader.ReadStrongMobileList();
goto case 25;
}
case 25:
{
int recipeCount = reader.ReadInt();
@ -2520,6 +2562,8 @@ namespace Server.Mobiles
}
case 0:
{
if( version < 26 )
m_AutoStabled = new List<Mobile>();
break;
}
}
@ -2598,7 +2642,9 @@ namespace Server.Mobiles
base.Serialize( writer );
writer.Write( (int) 25 ); // version
writer.Write( (int) 26 ); // version
writer.Write( m_AutoStabled, true );
if( m_AcquiredRecipes == null )
{
@ -3855,5 +3901,99 @@ namespace Server.Mobiles
m_BuffTable = null;
}
#endregion
public void AutoStablePets()
{
if ( Core.SE && AllFollowers.Count > 0 )
{
for ( int i = 0; i < m_AllFollowers.Count; ++i )
{
BaseCreature pet = AllFollowers[i] as BaseCreature;
if ( pet == null || pet.ControlMaster == null || ( pet.Summoned && !Core.ML ) )
continue;
if ( pet is IMount && ((IMount)pet).Rider != null )
continue;
if ( (pet is PackLlama || pet is PackHorse || pet is Beetle || pet is HordeMinionFamiliar) && (pet.Backpack != null && pet.Backpack.Items.Count > 0) )
continue;
if ( !pet.Summoned && !pet.IsBonded )
continue;
pet.ControlTarget = null;
pet.ControlOrder = OrderType.Stay;
pet.Internalize();
pet.SetControlMaster( null );
pet.SummonMaster = null;
pet.IsStabled = true;
pet.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully happy
Stabled.Add( pet );
m_AutoStabled.Add( pet );
--i;
}
}
}
public void ClaimAutoStabledPets()
{
if( !Core.SE || m_AutoStabled.Count <= 0 )
return;
if( !Alive )
{
SendLocalizedMessage( 1076251 ); // Your pet was unable to join you while you are a ghost. Please re-login once you have ressurected to claim your pets.
return;
}
for ( int i = 0; i < m_AutoStabled.Count; ++i )
{
BaseCreature pet = m_AutoStabled[i] as BaseCreature;
if ( pet == null || pet.Deleted )
{
pet.IsStabled = false;
m_AutoStabled.RemoveAt( i );
if( Stabled.Contains( pet ) )
Stabled.Remove( pet );
--i;
continue;
}
if ( (Followers + pet.ControlSlots) <= FollowersMax )
{
m_AutoStabled.RemoveAt( i );
--i;
pet.SetControlMaster( this );
if ( pet.Summoned )
pet.SummonMaster = this;
pet.ControlTarget = this;
pet.ControlOrder = OrderType.Follow;
pet.MoveToWorld( Location, Map );
pet.IsStabled = false;
pet.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully Happy
if( Stabled.Contains( pet ) )
Stabled.Remove( pet );
}
else
{
SendMessage( 1049612, pet.Name ); // ~1_NAME~ remained in the stables because you have too many followers.
}
}
m_AutoStabled.Clear();
}
}
}

View file

@ -332,7 +332,7 @@ namespace Server.Mobiles
{
pm.SendLocalizedMessage( 1053004 ); // You must wait about a day before you can gain in compassion again.
}
else if ( VirtueHelper.Award( pm, VirtueName.Compassion, 200, ref gainedPath ) )
else if ( VirtueHelper.Award( pm, VirtueName.Compassion, this.IsPrisoner ? 400 : 200, ref gainedPath ) )
{
if ( gainedPath )
pm.SendLocalizedMessage( 1053005 ); // You have achieved a path in compassion!

View file

@ -17,6 +17,8 @@ namespace Server.Multis
public override void AddComponents()
{
BaseCreature bc;
IronGate gate = new IronGate( DoorFacing.EastCCW );
m_Gate = gate;
@ -46,6 +48,8 @@ namespace Server.Multis
case 1: m_Prisoner = new SeekerOfAdventure(); break;
}
bc = (BaseCreature)m_Prisoner;
bc.IsPrisoner = true;
m_Prisoner.YellHue = Utility.RandomList( 0x57, 0x67, 0x77, 0x87, 0x117 );
AddMobile( m_Prisoner, 2, -2, 0, 0 );

View file

@ -17,6 +17,8 @@ namespace Server.Multis
public override void AddComponents()
{
BaseCreature bc;
IronGate gate = new IronGate( DoorFacing.EastCCW );
m_Gate = gate;
@ -46,6 +48,8 @@ namespace Server.Multis
case 1: m_Prisoner = new SeekerOfAdventure(); break;
}
bc = (BaseCreature)m_Prisoner;
bc.IsPrisoner = true;
m_Prisoner.YellHue = Utility.RandomList( 0x57, 0x67, 0x77, 0x87, 0x117 );
AddMobile( m_Prisoner, 2, -2, 0, 0 );

View file

@ -82,7 +82,7 @@ namespace Server.SkillHandlers
public static void ScaleSkills( BaseCreature bc, double scalar )
{
int totalCapIncrease = 0;
int totalCapIncrease = Core.SE ? 2000 : 0; // 2000 points for GM Anatomy and Meditation
for ( int i = 0; i < bc.Skills.Length; ++i )
{
@ -246,7 +246,7 @@ namespace Server.SkillHandlers
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502796, m_Tamer.NetState ); // You are dead, and cannot continue taming.
Stop();
}
else if ( !m_Tamer.CanSee( m_Creature ) || !m_Tamer.InLOS( m_Creature ) )
else if ( !m_Tamer.CanSee( m_Creature ) || !m_Tamer.InLOS( m_Creature ) || !CanPath() )
{
m_BeingTamed.Remove( m_Creature );
m_Tamer.NextSkillTime = DateTime.Now;
@ -356,6 +356,21 @@ namespace Server.SkillHandlers
}
}
}
private bool CanPath()
{
IPoint3D p = m_Tamer as IPoint3D;
if ( p == null )
return false;
if( m_Creature.InRange( new Point3D( p ), 1 ) )
return true;
MovementPath path = new MovementPath( m_Creature, new Point3D( p ) );
return path.Success;
}
}
}
}

View file

@ -23,12 +23,17 @@ namespace Server.SkillHandlers
public static TimeSpan OnUse( Mobile m )
{
if ( m.Target != null || m.Spell != null )
if ( m.Spell != null )
{
m.SendLocalizedMessage( 501238 ); // You are busy doing something else and cannot hide.
return TimeSpan.FromSeconds( 1.0 );
}
if ( Core.ML && m.Target != null )
{
Targeting.Target.Cancel( m );
}
double bonus = 0.0;
BaseHouse house = BaseHouse.FindHouseAt( m );

View file

@ -95,7 +95,7 @@ namespace Server.SkillHandlers
foreach ( Mobile m in from.GetMobilesInRange( range ) )
{
if ( (m is BaseCreature && ((BaseCreature)m).Uncalmable) || m == from || !from.CanBeHarmful( m, false ) )
if ((m is BaseCreature && ((BaseCreature)m).Uncalmable) || (m is BaseCreature && ((BaseCreature)m).AreaPeaceImmune) || m == from || !from.CanBeHarmful ( m, false ))
continue;
calmed = true;

View file

@ -21,9 +21,9 @@ namespace Server.Spells
public virtual bool BlockedByAnimalForm{ get{ return true; } }
public virtual bool DelayedContext{ get{ return false; } }
public virtual double GetAccuracyScalar( Mobile attacker )
public virtual int GetAccuracyBonus( Mobile attacker )
{
return 1.0;
return 0;
}
public virtual double GetDamageScalar( Mobile attacker, Mobile defender )

View file

@ -532,6 +532,9 @@ namespace Server.Spells
if ( ClearHandsOnCast )
m_Caster.ClearHands();
if ( Core.ML )
WeaponAbility.ClearCurrentAbility( m_Caster );
m_CastTimer = new CastTimer( this, castDelay );
m_CastTimer.Start();

View file

@ -18,14 +18,6 @@ namespace Server.Spells.Bushido
public override TextDefinition AbilityMessage{ get{ return new TextDefinition( 1063122 ); } } // You better kill your enemy with your next hit or you'll be rather sorry...
public override double GetAccuracyScalar( Mobile attacker )
{
double bushido = attacker.Skills[SkillName.Bushido].Value;
// TODO: 4 -> Perfection / 5
return 1.0 + ( bushido / 10.0 + 4 ) / 100.0;
}
public override double GetDamageScalar( Mobile attacker, Mobile defender )
{
double bushido = attacker.Skills[SkillName.Bushido].Value;

View file

@ -20,12 +20,9 @@ namespace Server.Spells.Bushido
public override bool DelayedContext{ get{ return true; } }
public override double GetAccuracyScalar( Mobile attacker )
public override int GetAccuracyBonus( Mobile attacker )
{
if ( GetContext( attacker, typeof( Bushido.LightningStrike ) ) )
return 1.1;
return 1.5;
return 50;
}
public override bool IgnoreArmor( Mobile attacker )

View file

@ -41,6 +41,8 @@ namespace Server.Spells.Bushido
public override bool CheckCast()
{
int mana = ScaleMana ( RequiredMana );
if ( !base.CheckCast() )
return false;
@ -56,9 +58,9 @@ namespace Server.Spells.Bushido
Caster.SendLocalizedMessage( 1063013, args ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability.
return false;
}
else if ( Caster.Mana < ScaleMana( RequiredMana ) )
else if ( Caster.Mana < mana )
{
Caster.SendLocalizedMessage( 1060174, RequiredMana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
Caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
return false;
}

View file

@ -52,6 +52,8 @@ namespace Server.Spells.Chivalry
m_Table[Caster] = t = Timer.DelayCall( TimeSpan.FromSeconds( delay ), new TimerStateCallback( Expire_Callback ), Caster );
Caster.Delta( MobileDelta.WeaponDamage );
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.DivineFury, 1060589, 1075634, TimeSpan.FromSeconds(delay), Caster));
}
FinishSequence();

View file

@ -56,6 +56,8 @@ namespace Server.Spells.Chivalry
{
((PlayerMobile)Caster).EnemyOfOneType = null;
((PlayerMobile)Caster).WaitingForEnemy = true;
BuffInfo.AddBuff ( Caster, new BuffInfo ( BuffIcon.EnemyOfOne, 1075653, 1044111, TimeSpan.FromMinutes ( delay ), Caster ) );
}
}

View file

@ -26,6 +26,8 @@ namespace Server.Spells.Chivalry
public override bool CheckCast()
{
int mana = ScaleMana( RequiredMana );
if ( !base.CheckCast() )
return false;
@ -39,9 +41,9 @@ namespace Server.Spells.Chivalry
Caster.SendLocalizedMessage( 1060173, RequiredTithing.ToString() ); // You must have at least ~1_TITHE_REQUIREMENT~ Tithing Points to use this ability,
return false;
}
else if ( Caster.Mana < ScaleMana( RequiredMana ) )
else if ( Caster.Mana < mana )
{
Caster.SendLocalizedMessage( 1060174, RequiredMana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
Caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
return false;
}
@ -69,7 +71,7 @@ namespace Server.Spells.Chivalry
}
else if ( Caster.Mana < mana )
{
Caster.SendLocalizedMessage( 1060174, RequiredMana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
Caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
return false;
}

View file

@ -86,12 +86,16 @@ namespace Server.Spells.Chivalry
CorpseSkinSpell.RemoveCurse( m );
CurseSpell.RemoveEffect( m );
MortalStrike.EndWound( m );
if (Core.ML) { BloodOathSpell.RemoveCurse ( m ); }
MindRotSpell.ClearMindRotScalar ( m );
BuffInfo.RemoveBuff( m, BuffIcon.Clumsy );
BuffInfo.RemoveBuff( m, BuffIcon.FeebleMind );
BuffInfo.RemoveBuff( m, BuffIcon.Weaken );
BuffInfo.RemoveBuff ( m, BuffIcon.Curse );
BuffInfo.RemoveBuff( m, BuffIcon.MassCurse );
BuffInfo.RemoveBuff( m, BuffIcon.MortalStrike );
BuffInfo.RemoveBuff ( m, BuffIcon.Mindrot );
// TODO: Should this remove blood oath? Pain spike?
}

View file

@ -79,6 +79,11 @@ namespace Server.Spells.First
for ( int i = 0; i < mods.Length; ++i )
targ.AddResistanceMod( mods[i] );
int physresist = 15 + (int)(targ.Skills[SkillName.Inscribe].Value / 20);
string args = String.Format("{0}\t{1}\t{2}\t{3}\t{4}", physresist, 5, 5, 5, 5);
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.ReactiveArmor, 1075812, 1075813, args.ToString()));
}
else
{
@ -89,6 +94,8 @@ namespace Server.Spells.First
for ( int i = 0; i < mods.Length; ++i )
targ.RemoveResistanceMod( mods[i] );
BuffInfo.RemoveBuff(Caster, BuffIcon.ReactiveArmor);
}
}

View file

@ -75,6 +75,13 @@ namespace Server.Spells.Fourth
m.FixedParticles( 0x374A, 10, 15, 5028, EffectLayer.Waist );
m.PlaySound( 0x1EA );
int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
TimeSpan length = SpellHelper.GetDuration(Caster, m);
string args = String.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", percentage, percentage, percentage, 10, 10, 10, 10);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, length, m, args.ToString()));
}
FinishSequence();

View file

@ -58,6 +58,10 @@ namespace Server.Spells.Necromancy
* ((ss-rm)/8)+8
*/
ExpireTimer timer = (ExpireTimer)m_Table[m];
if ( timer != null )
timer.DoExpire();
m_OathTable[Caster] = Caster;
m_OathTable[m] = Caster;
@ -72,13 +76,32 @@ namespace Server.Spells.Necromancy
TimeSpan duration = TimeSpan.FromSeconds( ((GetDamageSkill( Caster ) - GetResistSkill( m )) / 8) + 8 );
m.CheckSkill( SkillName.MagicResist, 0.0, 120.0 ); //Skill check for gain
new ExpireTimer( Caster, m, duration ).Start();
timer = new ExpireTimer ( Caster, m, duration );
timer.Start ();
BuffInfo.AddBuff ( Caster, new BuffInfo ( BuffIcon.BloodOathCaster, 1075659, duration, Caster, m.Name.ToString () ) );
BuffInfo.AddBuff ( m, new BuffInfo ( BuffIcon.BloodOathCurse, 1075661, duration, m, Caster.Name.ToString () ) );
m_Table[m] = timer;
}
FinishSequence();
}
public static bool RemoveCurse( Mobile m )
{
ExpireTimer t = (ExpireTimer)m_Table[m];
if ( t == null )
return false;
t.DoExpire();
return true;
}
private static Hashtable m_OathTable = new Hashtable();
private static Hashtable m_Table = new Hashtable ();
public static Mobile GetBloodOath( Mobile m )
{
@ -112,15 +135,24 @@ namespace Server.Spells.Necromancy
{
if ( m_Caster.Deleted || m_Target.Deleted || !m_Caster.Alive || !m_Target.Alive || DateTime.Now >= m_End )
{
m_Caster.SendLocalizedMessage( 1061620 ); // Your Blood Oath has been broken.
m_Target.SendLocalizedMessage( 1061620 ); // Your Blood Oath has been broken.
m_OathTable.Remove( m_Caster );
m_OathTable.Remove( m_Target );
Stop();
DoExpire ();
}
}
public void DoExpire()
{
m_Caster.SendLocalizedMessage( 1061620 ); // Your Blood Oath has been broken.
m_Target.SendLocalizedMessage( 1061620 ); // Your Blood Oath has been broken.
m_OathTable.Remove ( m_Caster );
m_OathTable.Remove ( m_Target );
Stop ();
BuffInfo.RemoveBuff ( m_Caster, BuffIcon.BloodOathCaster );
BuffInfo.RemoveBuff ( m_Target, BuffIcon.BloodOathCurse );
m_Table.Remove ( m_Caster );
}
}
private class InternalTarget : Target

View file

@ -66,56 +66,42 @@ namespace Server.Spells.Necromancy
public static void ClearMindRotScalar( Mobile m )
{
m_Table.Remove( m );
if (!m_Table.ContainsKey(m))
return;
BuffInfo.RemoveBuff( m, BuffIcon.Mindrot );
MRBucket tmpB = (MRBucket)m_Table[m];
MRExpireTimer tmpT = (MRExpireTimer)tmpB.m_MRExpireTimer;
tmpT.Stop();
m_Table.Remove(m);
m.SendLocalizedMessage(1060872); // Your mind feels normal again.
}
public static bool HasMindRotScalar( Mobile m )
{
return m_Table.Contains( m );
return m_Table.ContainsKey(m);
}
public static bool GetMindRotScalar( Mobile m, ref double scalar )
{
object obj = m_Table[m];
if ( obj == null )
if (!m_Table.ContainsKey(m))
return false;
scalar = (double)obj;
MRBucket tmpB = (MRBucket)m_Table[m];
scalar = tmpB.m_Scalar;
return true;
}
public static void SetMindRotScalar( Mobile caster, Mobile target, double scalar, TimeSpan duration )
{
m_Table[target] = scalar;
BuffInfo.AddBuff( target, new BuffInfo( BuffIcon.Mindrot, 1075665, duration, target ) );
new ExpireTimer( caster, target, duration ).Start();
}
private class ExpireTimer : Timer
{
private Mobile m_Caster;
private Mobile m_Target;
private DateTime m_End;
public ExpireTimer( Mobile caster, Mobile target, TimeSpan delay ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) )
if (!m_Table.ContainsKey(target))
{
m_Caster = caster;
m_Target = target;
m_End = DateTime.Now + delay;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
if ( m_Target.Deleted || !m_Target.Alive || DateTime.Now >= m_End )
{
m_Target.SendLocalizedMessage( 1060872 ); // Your mind feels normal again.
ClearMindRotScalar( m_Target );
Stop();
}
m_Table.Add(target, new MRBucket(scalar, new MRExpireTimer(caster, target, duration)));
BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Mindrot, 1075665, duration, target));
MRBucket tmpB = (MRBucket)m_Table[target];
MRExpireTimer tmpT = (MRExpireTimer)tmpB.m_MRExpireTimer;
tmpT.Start();
target.SendLocalizedMessage(1074384);
}
}
@ -142,4 +128,50 @@ namespace Server.Spells.Necromancy
}
}
}
public class MRExpireTimer : Timer
{
private Mobile m_Caster;
private Mobile m_Target;
private DateTime m_End;
public MRExpireTimer( Mobile caster, Mobile target, TimeSpan delay ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) )
{
m_Caster = caster;
m_Target = target;
m_End = DateTime.Now + delay;
Priority = TimerPriority.TwoFiftyMS;
}
public void RenewDelay(TimeSpan delay)
{
m_End = DateTime.Now + delay;
}
public void Halt()
{
Stop();
}
protected override void OnTick()
{
if ( m_Target.Deleted || !m_Target.Alive || DateTime.Now >= m_End )
{
MindRotSpell.ClearMindRotScalar( m_Target );
Stop();
}
}
}
public class MRBucket
{
public MRBucket(double theScalar, MRExpireTimer theTimer)
{
m_Scalar = theScalar;
m_MRExpireTimer = theTimer;
}
public double m_Scalar;
public MRExpireTimer m_MRExpireTimer;
}
}

View file

@ -74,9 +74,7 @@ namespace Server.Spells.Necromancy
new InternalTimer( m, damage ).Start();
}
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.PainSpike, 1075667, buffTime, m, (int)damage ) );
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.PainSpike, 1075667, buffTime, m, Convert.ToString( (int)damage ) ) );
Misc.WeightOverloading.DFA = Misc.DFAlgorithm.PainSpike;
m.Damage( (int) damage, Caster );

View file

@ -49,6 +49,13 @@ namespace Server.Spells.Necromancy
Effects.PlaySound( m.Location, m.Map, 0x229 );
double damage = Utility.RandomMinMax( (Core.ML ? 32 : 36), 40 ) * ((300 + (GetDamageSkill( Caster ) * 9)) / 1000);
double sdiBonus = (double)AosAttributes.GetValue( Caster, AosAttribute.SpellDamage )/100;
double pvmDamage = damage * (1 + sdiBonus);
if ( Core.ML && sdiBonus > 0.15 )
sdiBonus = 0.15;
double pvpDamage = damage * (1 + sdiBonus);
Map map = m.Map;
@ -57,7 +64,7 @@ namespace Server.Spells.Necromancy
List<Mobile> targets = new List<Mobile>();
foreach( Mobile targ in m.GetMobilesInRange( 2 ) )
if( (Caster == targ || SpellHelper.ValidIndirectTarget( Caster, targ )) && Caster.CanBeHarmful( targ, false ) )
if( (Caster == targ || m == targ || SpellHelper.ValidIndirectTarget( Caster, targ )) && Caster.CanBeHarmful( targ, false ) )
targets.Add( targ );
for( int i = 0; i < targets.Count; ++i )
@ -74,7 +81,7 @@ namespace Server.Spells.Necromancy
num = 3;
Caster.DoHarmful( targ );
SpellHelper.Damage( this, targ, damage / num, 0, 0, 0, 100, 0 );
SpellHelper.Damage( this, targ, ((m.Player && Caster.Player) ? pvpDamage : pvmDamage) / num, 0, 0, 0, 100, 0 );
}
}
}

View file

@ -135,6 +135,9 @@ namespace Server.Spells.Ninjitsu
// This bonus is 8 at most. That brings the cap up to 70/30.
damage += info.m_DamageBonus;
if ( info.m_Attacker.Weapon is BaseWeapon && ((BaseWeapon)info.m_Attacker.Weapon).MaxRange > 1 )
damage /= 2;
// Damage is direct.
//info.m_Target.Damage( damage, info.m_Attacker );

View file

@ -43,6 +43,8 @@ namespace Server.Spells.Ninjitsu
public override bool CheckCast()
{
int mana = ScaleMana( RequiredMana );
if ( !base.CheckCast() )
return false;
@ -58,9 +60,9 @@ namespace Server.Spells.Ninjitsu
Caster.SendLocalizedMessage( 1063013, args ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability.
return false;
}
else if ( Caster.Mana < ScaleMana( RequiredMana ) )
else if ( Caster.Mana < mana )
{
Caster.SendLocalizedMessage( 1060174, RequiredMana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
Caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
return false;
}

View file

@ -49,8 +49,8 @@ namespace Server.Spells.Second
public static void Toggle( Mobile caster, Mobile target )
{
/* Players under the protection spell effect can no longer have their spells "disrupted" when hit.
* Players under the protection spell have decreased physical resistance stat value,
* a decreased "resisting spells" skill value by -35,
* Players under the protection spell have decreased physical resistance stat value (-15 + (Inscription/20),
* a decreased "resisting spells" skill value by -35 + (Inscription/20),
* and a slower casting speed modifier (technically, a negative "faster cast speed") of 2 points.
* The protection spell has an indefinite duration, becoming active when cast, and deactivated when re-cast.
* Reactive Armor, Protection, and Magic Reflection will stay oneven after logging out,
@ -75,6 +75,11 @@ namespace Server.Spells.Second
target.AddResistanceMod( (ResistanceMod)mods[0] );
target.AddSkillMod( (SkillMod)mods[1] );
int physloss = -15 + (int) (caster.Skills[SkillName.Inscribe].Value / 20);
int resistloss = -35 + (int) (caster.Skills[SkillName.Inscribe].Value / 20);
string args = String.Format("{0}\t{1}", physloss, resistloss);
BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Protection, 1075814, 1075815, args.ToString()));
}
else
{
@ -86,6 +91,8 @@ namespace Server.Spells.Second
target.RemoveResistanceMod( (ResistanceMod)mods[0] );
target.RemoveSkillMod( (SkillMod)mods[1] );
BuffInfo.RemoveBuff(target, BuffIcon.Protection);
}
}

View file

@ -130,7 +130,7 @@ namespace Server.Spells.Spellweaving
public virtual bool CheckResisted( Mobile m )
{
double percent = (50 + 2*(GetResistSkill( m ) - GetDamageSkill( m )))/100; //TODO: According to the guide this is it.. but.. is it correct per OSI?
double percent = (50 + 2*(GetResistSkill( m ) - GetDamageSkill( Caster )))/100; //TODO: According to the guide this is it.. but.. is it correct per OSI?
if( percent <= 0 )
return false;

View file

@ -70,6 +70,13 @@ namespace Server.Spells.Spellweaving
{
Caster.SendLocalizedMessage( 501942 ); // That location is blocked.
}
//say "Target can not be seen" if you target directly a mobile, like in OSI
if (m != null)
{
Caster.SendLocalizedMessage(500237); // Target can not be seen.
}
else if( SpellHelper.CheckTown( p, Caster ) && (m_MobileTarg ? CheckHSequence( m ) : CheckSequence()) )
{
TimeSpan duration = TimeSpan.FromSeconds( Caster.Skills.Spellweaving.Value/24 + 25 + FocusLevel*2 );

View file

@ -27,8 +27,22 @@ namespace Server.Spells.Spellweaving
{
Caster.PlaySound( 0x5CE );
double skill = Caster.Skills[SkillName.Spellweaving].Value;
int damage = Math.Max( 11, 10 + (int)(skill / 24) ) + FocusLevel;
int sdiBonus = AosAttributes.GetValue( Caster, AosAttribute.SpellDamage );
int pvmDamage = damage * ( 100 + sdiBonus );
pvmDamage /= 100;
if ( sdiBonus > 15 )
sdiBonus = 15;
int pvpDamage = damage * ( 100 + sdiBonus );
pvpDamage /= 100;
int range = 2 + FocusLevel;
int damage = 15 + FocusLevel;
TimeSpan duration = TimeSpan.FromSeconds( 5 + FocusLevel );
List<Mobile> targets = new List<Mobile>();
@ -47,7 +61,7 @@ namespace Server.Spells.Spellweaving
Spell oldSpell = m.Spell as Spell;
SpellHelper.Damage( this, m, damage, 0, 0, 0, 0, 100 );
SpellHelper.Damage( this, m, ( m.Player && Caster.Player ) ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100 );
if( oldSpell != null && oldSpell != m.Spell )
{

View file

@ -41,6 +41,13 @@ namespace Server.Spells.Third
m.FixedParticles( 0x373A, 10, 15, 5018, EffectLayer.Waist );
m.PlaySound( 0x1EA );
int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
TimeSpan length = SpellHelper.GetDuration(Caster, m);
string args = String.Format("{0}\t{1}\t{2}", percentage, percentage, percentage);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Bless, 1075847, 1075848, length, m, args.ToString()));
}
FinishSequence();