#W# Source and Scripts added. Added Scripts/Settings.cs to expose some basic tweak able settings.
This commit is contained in:
parent
b51c58f514
commit
3045c83799
3512 changed files with 627673 additions and 0 deletions
47
Scripts/Engines/Virtues/Compassion.cs
Normal file
47
Scripts/Engines/Virtues/Compassion.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class CompassionVirtue
|
||||
{
|
||||
private static TimeSpan LossDelay = TimeSpan.FromDays( 7.0 );
|
||||
private const int LossAmount = 500;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
VirtueGump.Register( 105, new OnVirtueUsed( OnVirtueUsed ) );
|
||||
}
|
||||
|
||||
public static void OnVirtueUsed( Mobile from )
|
||||
{
|
||||
from.SendLocalizedMessage( 1053001 ); // This virtue is not activated through the virtue menu.
|
||||
}
|
||||
|
||||
public static void CheckAtrophy( Mobile from )
|
||||
{
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if ( pm == null )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if ( (pm.LastCompassionLoss + LossDelay) < DateTime.UtcNow )
|
||||
{
|
||||
VirtueHelper.Atrophy( from, VirtueName.Compassion, LossAmount );
|
||||
//OSI has no cliloc message for losing compassion. Weird.
|
||||
pm.LastCompassionLoss = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
433
Scripts/Engines/Virtues/Honor.cs
Normal file
433
Scripts/Engines/Virtues/Honor.cs
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Gumps;
|
||||
using Server.Targeting;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class HonorVirtue
|
||||
{
|
||||
|
||||
private static readonly TimeSpan UseDelay = TimeSpan.FromMinutes( 5.0 );
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
VirtueGump.Register( 107, new OnVirtueUsed( OnVirtueUsed ) );
|
||||
}
|
||||
|
||||
private static void OnVirtueUsed( Mobile from )
|
||||
{
|
||||
if ( from.Alive )
|
||||
{
|
||||
from.SendLocalizedMessage( 1063160 ); // Target what you wish to honor.
|
||||
from.Target = new InternalTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base( 12, false, TargetFlags.None )
|
||||
{
|
||||
CheckLOS = true;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
if ( pm == null )
|
||||
return;
|
||||
|
||||
if ( targeted == pm )
|
||||
{
|
||||
EmbraceHonor( pm );
|
||||
}
|
||||
else if ( targeted is Mobile )
|
||||
Honor( pm, (Mobile) targeted );
|
||||
}
|
||||
|
||||
protected override void OnTargetOutOfRange( Mobile from, object targeted )
|
||||
{
|
||||
from.SendLocalizedMessage( 1063232 ); // You are too far away to honor your opponent
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetHonorDuration( PlayerMobile from )
|
||||
{
|
||||
switch ( VirtueHelper.GetLevel( from, VirtueName.Honor ) )
|
||||
{
|
||||
case VirtueLevel.Seeker: return 30;
|
||||
case VirtueLevel.Follower: return 90;
|
||||
case VirtueLevel.Knight: return 300;
|
||||
|
||||
default: return 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmbraceHonor( PlayerMobile pm )
|
||||
{
|
||||
if ( pm.HonorActive )
|
||||
{
|
||||
pm.SendLocalizedMessage( 1063230 ); // You must wait awhile before you can embrace honor again.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GetHonorDuration( pm ) == 0 )
|
||||
{
|
||||
pm.SendLocalizedMessage( 1063234 ); // You do not have enough honor to do that
|
||||
return;
|
||||
}
|
||||
|
||||
TimeSpan waitTime = DateTime.UtcNow - pm.LastHonorUse;
|
||||
if ( waitTime < UseDelay )
|
||||
{
|
||||
TimeSpan remainingTime = UseDelay - waitTime;
|
||||
int remainingMinutes = (int) Math.Ceiling( remainingTime.TotalMinutes );
|
||||
|
||||
pm.SendLocalizedMessage( 1063240, remainingMinutes.ToString() ); // You must wait ~1_HONOR_WAIT~ minutes before embracing honor again
|
||||
return;
|
||||
}
|
||||
|
||||
pm.SendGump( new HonorSelf( pm ) );
|
||||
|
||||
}
|
||||
|
||||
public static void ActivateEmbrace( PlayerMobile pm )
|
||||
{
|
||||
int duration = GetHonorDuration( pm );
|
||||
int usedPoints;
|
||||
|
||||
if ( pm.Virtues.Honor < 4399)
|
||||
usedPoints = 400;
|
||||
else if ( pm.Virtues.Honor < 10599 )
|
||||
usedPoints = 600;
|
||||
else
|
||||
usedPoints = 1000;
|
||||
|
||||
VirtueHelper.Atrophy( pm, VirtueName.Honor, usedPoints );
|
||||
|
||||
pm.HonorActive = true;
|
||||
pm.SendLocalizedMessage( 1063235 ); // You embrace your honor
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( duration ),
|
||||
delegate() {
|
||||
pm.HonorActive = false;
|
||||
pm.LastHonorUse = DateTime.UtcNow;
|
||||
pm.SendLocalizedMessage( 1063236 ); // You no longer embrace your honor
|
||||
} );
|
||||
}
|
||||
|
||||
private static void Honor( PlayerMobile source, Mobile target )
|
||||
{
|
||||
IHonorTarget honorTarget = target as IHonorTarget;
|
||||
GuardedRegion reg = (GuardedRegion) source.Region.GetRegion( typeof( GuardedRegion ) );
|
||||
Map map = source.Map;
|
||||
|
||||
if ( honorTarget == null )
|
||||
return;
|
||||
|
||||
if ( honorTarget.ReceivedHonorContext != null )
|
||||
{
|
||||
if ( honorTarget.ReceivedHonorContext.Source == source )
|
||||
return;
|
||||
|
||||
if ( honorTarget.ReceivedHonorContext.CheckDistance() )
|
||||
{
|
||||
source.SendLocalizedMessage( 1063233 ); // Somebody else is honoring this opponent
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( target.Hits < target.HitsMax )
|
||||
{
|
||||
source.SendLocalizedMessage( 1063166 ); // You cannot honor this monster because it is too damaged.
|
||||
return;
|
||||
}
|
||||
|
||||
BaseCreature cret = target as BaseCreature;
|
||||
if ( target.Body.IsHuman && (cret == null || (!cret.AlwaysAttackable && !cret.AlwaysMurderer)) )
|
||||
{
|
||||
|
||||
if( reg == null || reg.IsDisabled() )
|
||||
{
|
||||
//Allow honor on blue if Out of guardzone
|
||||
}
|
||||
else if ( map != null && (map.Rules & MapRules.HarmfulRestrictions) == 0 )
|
||||
{
|
||||
//Allow honor on blue if in Fel
|
||||
}
|
||||
else
|
||||
{
|
||||
source.SendLocalizedMessage( 1001018 ); // You cannot perform negative acts
|
||||
return; //cannot honor in trammel town on blue
|
||||
}
|
||||
}
|
||||
|
||||
if( Core.ML && target is PlayerMobile )
|
||||
{
|
||||
source.SendLocalizedMessage( 1075614 ); // You cannot honor other players.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( source.SentHonorContext != null )
|
||||
source.SentHonorContext.Cancel();
|
||||
|
||||
new HonorContext( source, target );
|
||||
|
||||
source.Direction = source.GetDirectionTo( target );
|
||||
|
||||
if ( !source.Mounted )
|
||||
source.Animate( 32, 5, 1, true, true, 0 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHonorTarget
|
||||
{
|
||||
HonorContext ReceivedHonorContext{ get; set; }
|
||||
}
|
||||
|
||||
public class HonorContext
|
||||
{
|
||||
private PlayerMobile m_Source;
|
||||
private Mobile m_Target;
|
||||
|
||||
private double m_HonorDamage;
|
||||
private int m_TotalDamage;
|
||||
|
||||
private int m_Perfection;
|
||||
|
||||
private enum FirstHit
|
||||
{
|
||||
NotDelivered,
|
||||
Delivered,
|
||||
Granted
|
||||
}
|
||||
|
||||
private FirstHit m_FirstHit;
|
||||
private bool m_Poisoned;
|
||||
private Point3D m_InitialLocation;
|
||||
private Map m_InitialMap;
|
||||
|
||||
private InternalTimer m_Timer;
|
||||
|
||||
public PlayerMobile Source{ get{ return m_Source; } }
|
||||
public Mobile Target{ get{ return m_Target; } }
|
||||
|
||||
public HonorContext( PlayerMobile source, Mobile target )
|
||||
{
|
||||
m_Source = source;
|
||||
m_Target = target;
|
||||
|
||||
m_FirstHit = FirstHit.NotDelivered;
|
||||
m_Poisoned = false;
|
||||
|
||||
m_InitialLocation = source.Location;
|
||||
m_InitialMap = source.Map;
|
||||
|
||||
source.SentHonorContext = this;
|
||||
((IHonorTarget)target).ReceivedHonorContext = this;
|
||||
|
||||
m_Timer = new InternalTimer( this );
|
||||
m_Timer.Start();
|
||||
source.m_hontime = (DateTime.UtcNow + TimeSpan.FromMinutes( 40 ));
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromMinutes( 40 ),
|
||||
delegate() {
|
||||
if (source.m_hontime < DateTime.UtcNow && source.SentHonorContext != null)
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public void OnSourceDamaged( Mobile from, int amount )
|
||||
{
|
||||
if ( from != m_Target )
|
||||
return;
|
||||
|
||||
if ( m_FirstHit == FirstHit.NotDelivered )
|
||||
m_FirstHit = FirstHit.Granted;
|
||||
}
|
||||
|
||||
public void OnTargetPoisoned()
|
||||
{
|
||||
m_Poisoned = true; // Set this flag for OnTargetDamaged which will be called next
|
||||
}
|
||||
|
||||
public void OnTargetDamaged( Mobile from, int amount )
|
||||
{
|
||||
if ( m_FirstHit == FirstHit.NotDelivered )
|
||||
m_FirstHit = FirstHit.Delivered;
|
||||
|
||||
if ( m_Poisoned )
|
||||
{
|
||||
m_HonorDamage += amount * 0.8;
|
||||
m_Poisoned = false; // Reset the flag
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_TotalDamage += amount;
|
||||
|
||||
if ( from == m_Source )
|
||||
{
|
||||
if ( m_Target.CanSee( m_Source ) && m_Target.InLOS( m_Source ) && ( m_Source.InRange( m_Target, 1 )
|
||||
|| ( m_Source.Location == m_InitialLocation && m_Source.Map == m_InitialMap ) ) )
|
||||
{
|
||||
m_HonorDamage += amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HonorDamage += amount * 0.8;
|
||||
}
|
||||
}
|
||||
else if ( from is BaseCreature && ((BaseCreature)from).GetMaster() == m_Source )
|
||||
{
|
||||
m_HonorDamage += amount * 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnTargetHit( Mobile from )
|
||||
{
|
||||
if ( from != m_Source || m_Perfection == 100 )
|
||||
return;
|
||||
|
||||
int bushido = (int) from.Skills.Bushido.Value;
|
||||
if ( bushido < 50 )
|
||||
return;
|
||||
|
||||
m_Perfection += bushido / 10;
|
||||
|
||||
if ( m_Perfection >= 100 )
|
||||
{
|
||||
m_Perfection = 100;
|
||||
m_Source.SendLocalizedMessage( 1063254 ); // You have Achieved Perfection in inflicting damage to this opponent!
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Source.SendLocalizedMessage( 1063255 ); // You gain in Perfection as you precisely strike your opponent.
|
||||
}
|
||||
}
|
||||
|
||||
public void OnTargetMissed( Mobile from )
|
||||
{
|
||||
if ( from != m_Source || m_Perfection == 0 )
|
||||
return;
|
||||
|
||||
m_Perfection -= 25;
|
||||
|
||||
if ( m_Perfection <= 0 )
|
||||
{
|
||||
m_Perfection = 0;
|
||||
m_Source.SendLocalizedMessage( 1063256 ); // You have lost all Perfection in fighting this opponent.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Source.SendLocalizedMessage( 1063257 ); // You have lost some Perfection in fighting this opponent.
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSourceBeneficialAction( Mobile to )
|
||||
{
|
||||
if ( to != m_Target )
|
||||
return;
|
||||
|
||||
if ( m_Perfection >= 0 )
|
||||
{
|
||||
m_Perfection = 0;
|
||||
m_Source.SendLocalizedMessage( 1063256 ); // You have lost all Perfection in fighting this opponent.
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSourceKilled()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public void OnTargetKilled()
|
||||
{
|
||||
Cancel();
|
||||
|
||||
int targetFame = m_Target.Fame;
|
||||
|
||||
if ( m_Perfection > 0 )
|
||||
{
|
||||
int restore = Math.Min( m_Perfection * ( targetFame + 5000 ) / 25000, 10 );
|
||||
|
||||
m_Source.Hits += restore;
|
||||
m_Source.Stam += restore;
|
||||
m_Source.Mana += restore;
|
||||
}
|
||||
|
||||
if ( m_Source.Virtues.Honor > targetFame )
|
||||
return;
|
||||
|
||||
double dGain = ( targetFame / 100 ) * (m_HonorDamage / m_TotalDamage ); //Initial honor gain is 100th of the monsters honor
|
||||
|
||||
if ( m_HonorDamage == m_TotalDamage && m_FirstHit == FirstHit.Granted)
|
||||
dGain = dGain * 1.5; //honor gain is increased alot more if the combat was fully honorable
|
||||
else
|
||||
dGain = dGain * 0.9;
|
||||
|
||||
int gain = Math.Min( (int)dGain, 200 );
|
||||
|
||||
if ( gain < 1 )
|
||||
gain=1; //Minimum gain of 1 honor when the honor is under the monsters fame
|
||||
|
||||
if ( VirtueHelper.IsHighestPath( m_Source, VirtueName.Honor ) )
|
||||
{
|
||||
m_Source.SendLocalizedMessage( 1063228 ); // You cannot gain more Honor.
|
||||
return;
|
||||
}
|
||||
|
||||
bool gainedPath = false;
|
||||
if ( VirtueHelper.Award( m_Source, VirtueName.Honor, (int) gain, ref gainedPath ) )
|
||||
{
|
||||
if ( gainedPath )
|
||||
m_Source.SendLocalizedMessage( 1063226 ); // You have gained a path in Honor!
|
||||
else
|
||||
m_Source.SendLocalizedMessage( 1063225 ); // You have gained in Honor.
|
||||
}
|
||||
}
|
||||
|
||||
public int PerfectionDamageBonus
|
||||
{
|
||||
get { return m_Perfection; }
|
||||
}
|
||||
|
||||
public int PerfectionLuckBonus
|
||||
{
|
||||
get{ return (m_Perfection * m_Perfection) / 10; }
|
||||
}
|
||||
|
||||
public bool CheckDistance()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
m_Source.SentHonorContext = null;
|
||||
((IHonorTarget)m_Target).ReceivedHonorContext = null;
|
||||
|
||||
m_Timer.Stop();
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private HonorContext m_Context;
|
||||
|
||||
public InternalTimer( HonorContext context ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) )
|
||||
{
|
||||
m_Context = context;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Context.CheckDistance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
250
Scripts/Engines/Virtues/Justice.cs
Normal file
250
Scripts/Engines/Virtues/Justice.cs
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class JusticeVirtue
|
||||
{
|
||||
private static TimeSpan LossDelay = TimeSpan.FromDays( 7.0 );
|
||||
private const int LossAmount = 950;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
VirtueGump.Register( 109, new OnVirtueUsed( OnVirtueUsed ) );
|
||||
}
|
||||
|
||||
public static bool CheckMapRegion( Mobile first, Mobile second )
|
||||
{
|
||||
Map map = first.Map;
|
||||
|
||||
if ( second.Map != map )
|
||||
return false;
|
||||
|
||||
return GetMapRegion( map, first.Location ) == GetMapRegion( map, second.Location );
|
||||
}
|
||||
|
||||
public static int GetMapRegion( Map map, Point3D loc )
|
||||
{
|
||||
if ( map == null || map.MapID >= 2 )
|
||||
return 0;
|
||||
|
||||
if ( loc.X < 5120 )
|
||||
return 0;
|
||||
|
||||
if ( loc.Y < 2304 )
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
public static void OnVirtueUsed( Mobile from )
|
||||
{
|
||||
if ( !from.CheckAlive() )
|
||||
return;
|
||||
|
||||
PlayerMobile protector = from as PlayerMobile;
|
||||
|
||||
if ( protector == null )
|
||||
return;
|
||||
|
||||
if ( !VirtueHelper.IsSeeker( protector, VirtueName.Justice ) )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049610 ); // You must reach the first path in this virtue to invoke it.
|
||||
}
|
||||
else if ( !protector.CanBeginAction( typeof( JusticeVirtue ) ) )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049370 ); // You must wait a while before offering your protection again.
|
||||
}
|
||||
else if ( protector.JusticeProtectors.Count > 0 )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049542 ); // You cannot protect someone while being protected.
|
||||
}
|
||||
else if ( protector.Map != Map.Felucca )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049372 ); // You cannot use this ability here.
|
||||
}
|
||||
else
|
||||
{
|
||||
protector.BeginTarget( 14, false, TargetFlags.None, new TargetCallback( OnVirtueTargeted ) );
|
||||
protector.SendLocalizedMessage( 1049366 ); // Choose the player you wish to protect.
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnVirtueTargeted( Mobile from, object obj )
|
||||
{
|
||||
PlayerMobile protector = from as PlayerMobile;
|
||||
PlayerMobile pm = obj as PlayerMobile;
|
||||
|
||||
if ( protector == null )
|
||||
return;
|
||||
|
||||
if ( !VirtueHelper.IsSeeker( protector, VirtueName.Justice ) )
|
||||
protector.SendLocalizedMessage( 1049610 ); // You must reach the first path in this virtue to invoke it.
|
||||
else if ( !protector.CanBeginAction( typeof( JusticeVirtue ) ) )
|
||||
protector.SendLocalizedMessage( 1049370 ); // You must wait a while before offering your protection again.
|
||||
else if ( protector.JusticeProtectors.Count > 0 )
|
||||
protector.SendLocalizedMessage( 1049542 ); // You cannot protect someone while being protected.
|
||||
else if ( protector.Map != Map.Felucca )
|
||||
protector.SendLocalizedMessage( 1049372 ); // You cannot use this ability here.
|
||||
else if ( pm == null )
|
||||
protector.SendLocalizedMessage( 1049678 ); // Only players can be protected.
|
||||
else if ( pm.Map != Map.Felucca )
|
||||
protector.SendLocalizedMessage( 1049372 ); // You cannot use this ability here.
|
||||
else if ( pm == protector || pm.Criminal || pm.Kills >= 5 )
|
||||
protector.SendLocalizedMessage( 1049436 ); // That player cannot be protected.
|
||||
else if ( pm.JusticeProtectors.Count > 0 )
|
||||
protector.SendLocalizedMessage( 1049369 ); // You cannot protect that player right now.
|
||||
else if ( pm.HasGump( typeof( AcceptProtectorGump ) ) )
|
||||
protector.SendLocalizedMessage( 1049369 ); // You cannot protect that player right now.
|
||||
else
|
||||
pm.SendGump( new AcceptProtectorGump( protector, pm ) );
|
||||
}
|
||||
|
||||
public static void OnVirtueAccepted( PlayerMobile protector, PlayerMobile protectee )
|
||||
{
|
||||
if ( !VirtueHelper.IsSeeker( protector, VirtueName.Justice ) )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049610 ); // You must reach the first path in this virtue to invoke it.
|
||||
}
|
||||
else if ( !protector.CanBeginAction( typeof( JusticeVirtue ) ) )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049370 ); // You must wait a while before offering your protection again.
|
||||
}
|
||||
else if ( protector.JusticeProtectors.Count > 0 )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049542 ); // You cannot protect someone while being protected.
|
||||
}
|
||||
else if ( protector.Map != Map.Felucca )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049372 ); // You cannot use this ability here.
|
||||
}
|
||||
else if ( protectee.Map != Map.Felucca )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049372 ); // You cannot use this ability here.
|
||||
}
|
||||
else if ( protectee == protector || protectee.Criminal || protectee.Kills >= 5 )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049436 ); // That player cannot be protected.
|
||||
}
|
||||
else if ( protectee.JusticeProtectors.Count > 0 )
|
||||
{
|
||||
protector.SendLocalizedMessage( 1049369 ); // You cannot protect that player right now.
|
||||
}
|
||||
else
|
||||
{
|
||||
protectee.JusticeProtectors.Add( protector );
|
||||
|
||||
string args = String.Format( "{0}\t{1}", protector.Name, protectee.Name );
|
||||
|
||||
protectee.SendLocalizedMessage( 1049451, args ); // You are now being protected by ~1_NAME~.
|
||||
protector.SendLocalizedMessage( 1049452, args ); // You are now protecting ~2_NAME~.
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnVirtueRejected( PlayerMobile protector, PlayerMobile protectee )
|
||||
{
|
||||
string args = String.Format( "{0}\t{1}", protector.Name, protectee.Name );
|
||||
|
||||
protectee.SendLocalizedMessage( 1049453, args ); // You have declined protection from ~1_NAME~.
|
||||
protector.SendLocalizedMessage( 1049454, args ); // ~2_NAME~ has declined your protection.
|
||||
|
||||
if ( protector.BeginAction( typeof( JusticeVirtue ) ) )
|
||||
Timer.DelayCall( TimeSpan.FromMinutes( 15.0 ), new TimerStateCallback( RejectDelay_Callback ), protector );
|
||||
}
|
||||
|
||||
public static void RejectDelay_Callback( object state )
|
||||
{
|
||||
Mobile m = state as Mobile;
|
||||
|
||||
if ( m != null )
|
||||
m.EndAction( typeof( JusticeVirtue ) );
|
||||
}
|
||||
|
||||
public static void CheckAtrophy( Mobile from )
|
||||
{
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if ( pm == null )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if ( (pm.LastJusticeLoss + LossDelay) < DateTime.UtcNow )
|
||||
{
|
||||
if ( VirtueHelper.Atrophy( from, VirtueName.Justice, LossAmount ) )
|
||||
from.SendLocalizedMessage( 1049373 ); // You have lost some Justice.
|
||||
|
||||
pm.LastJusticeLoss = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AcceptProtectorGump : Gump
|
||||
{
|
||||
private PlayerMobile m_Protector;
|
||||
private PlayerMobile m_Protectee;
|
||||
|
||||
public AcceptProtectorGump( PlayerMobile protector, PlayerMobile protectee ) : base( 150, 50 )
|
||||
{
|
||||
m_Protector = protector;
|
||||
m_Protectee = protectee;
|
||||
|
||||
Closable = false;
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
AddBackground( 0, 0, 396, 218, 3600 );
|
||||
|
||||
AddImageTiled( 15, 15, 365, 190, 2624 );
|
||||
AddAlphaRegion( 15, 15, 365, 190 );
|
||||
|
||||
AddHtmlLocalized( 30, 20, 360, 25, 1049365, 0x7FFF, false, false ); // Another player is offering you their <a href="?ForceTopic88">protection</a>:
|
||||
AddLabel( 90, 55, 1153, protector.Name );
|
||||
|
||||
AddImage( 50, 45, 9005 );
|
||||
AddImageTiled( 80, 80, 200, 1, 9107 );
|
||||
AddImageTiled( 95, 82, 200, 1, 9157 );
|
||||
|
||||
AddRadio( 30, 110, 9727, 9730, true, 1 );
|
||||
AddHtmlLocalized( 65, 115, 300, 25, 1049444, 0x7FFF, false, false ); // Yes, I would like their protection.
|
||||
|
||||
AddRadio( 30, 145, 9727, 9730, false, 0 );
|
||||
AddHtmlLocalized( 65, 148, 300, 25, 1049445, 0x7FFF, false, false ); // No thanks, I can take care of myself.
|
||||
|
||||
AddButton( 160, 175, 247, 248, 2, GumpButtonType.Reply, 0 );
|
||||
|
||||
AddImage( 215, 0, 50581 );
|
||||
|
||||
AddImageTiled( 15, 14, 365, 1, 9107 );
|
||||
AddImageTiled( 380, 14, 1, 190, 9105 );
|
||||
AddImageTiled( 15, 205, 365, 1, 9107 );
|
||||
AddImageTiled( 15, 14, 1, 190, 9105 );
|
||||
AddImageTiled( 0, 0, 395, 1, 9157 );
|
||||
AddImageTiled( 394, 0, 1, 217, 9155 );
|
||||
AddImageTiled( 0, 216, 395, 1, 9157 );
|
||||
AddImageTiled( 0, 0, 1, 217, 9155 );
|
||||
}
|
||||
|
||||
public override void OnResponse( Server.Network.NetState sender, RelayInfo info )
|
||||
{
|
||||
if ( info.ButtonID == 2 )
|
||||
{
|
||||
bool okay = info.IsSwitched( 1 );
|
||||
|
||||
if ( okay )
|
||||
JusticeVirtue.OnVirtueAccepted( m_Protector, m_Protectee );
|
||||
else
|
||||
JusticeVirtue.OnVirtueRejected( m_Protector, m_Protectee );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
194
Scripts/Engines/Virtues/Sacrifice.cs
Normal file
194
Scripts/Engines/Virtues/Sacrifice.cs
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class SacrificeVirtue
|
||||
{
|
||||
private static TimeSpan GainDelay = TimeSpan.FromDays( 1.0 );
|
||||
private static TimeSpan LossDelay = TimeSpan.FromDays( 7.0 );
|
||||
private const int LossAmount = 500;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
VirtueGump.Register( 110, new OnVirtueUsed( OnVirtueUsed ) );
|
||||
}
|
||||
|
||||
public static void OnVirtueUsed( Mobile from )
|
||||
{
|
||||
if ( !from.Hidden )
|
||||
{
|
||||
if ( from.Alive )
|
||||
from.Target = new InternalTarget();
|
||||
else
|
||||
Resurrect( from );
|
||||
}
|
||||
else
|
||||
from.SendLocalizedMessage( 1052015 ); // You cannot do that while hidden.
|
||||
}
|
||||
|
||||
public static void CheckAtrophy( Mobile from )
|
||||
{
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if ( pm == null )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if ( (pm.LastSacrificeLoss + LossDelay) < DateTime.UtcNow )
|
||||
{
|
||||
if ( VirtueHelper.Atrophy( from, VirtueName.Sacrifice, LossAmount ) )
|
||||
from.SendLocalizedMessage( 1052041 ); // You have lost some Sacrifice.
|
||||
|
||||
VirtueLevel level = VirtueHelper.GetLevel( from, VirtueName.Sacrifice );
|
||||
|
||||
pm.AvailableResurrects = (int)level;
|
||||
pm.LastSacrificeLoss = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void Resurrect( Mobile from )
|
||||
{
|
||||
if ( from.Alive )
|
||||
return;
|
||||
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if ( pm == null )
|
||||
return;
|
||||
|
||||
if ( from.Criminal )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052007 ); // You cannot use this ability while flagged as a criminal.
|
||||
}
|
||||
else if ( !VirtueHelper.IsSeeker( from, VirtueName.Sacrifice ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052004 ); // You cannot use this ability.
|
||||
}
|
||||
else if ( pm.AvailableResurrects <= 0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052005 ); // You do not have any resurrections left.
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We need to wait for them to accept the gump or they can just use
|
||||
* Sacrifice and cancel to have items in their backpack for free.
|
||||
*/
|
||||
from.CloseGump( typeof( ResurrectGump ) );
|
||||
from.SendGump( new ResurrectGump( from, true ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sacrifice( Mobile from, object targeted )
|
||||
{
|
||||
if ( !from.CheckAlive() )
|
||||
return;
|
||||
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if ( pm == null )
|
||||
return;
|
||||
|
||||
Mobile targ = targeted as Mobile;
|
||||
|
||||
if ( targ == null )
|
||||
return;
|
||||
|
||||
if ( !ValidateCreature( targ ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052014 ); // You cannot sacrifice your fame for that creature.
|
||||
}
|
||||
else if ( ((targ.Hits * 100) / Math.Max( targ.HitsMax, 1 )) < 90 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052013 ); // You cannot sacrifice for this monster because it is too damaged.
|
||||
}
|
||||
else if ( from.Hidden )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052015 ); // You cannot do that while hidden.
|
||||
}
|
||||
else if ( VirtueHelper.IsHighestPath( from, VirtueName.Sacrifice ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052068 ); // You have already attained the highest path in this virtue.
|
||||
}
|
||||
else if ( from.Fame < 2500 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052017 ); // You do not have enough fame to sacrifice.
|
||||
}
|
||||
else if ( DateTime.UtcNow < (pm.LastSacrificeGain + GainDelay) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052016 ); // You must wait approximately one day before sacrificing again.
|
||||
}
|
||||
else
|
||||
{
|
||||
int toGain;
|
||||
|
||||
if( from.Fame < 5000 )
|
||||
toGain = 500;
|
||||
else if( from.Fame < 10000 )
|
||||
toGain = 1000;
|
||||
else
|
||||
toGain = 2000;
|
||||
|
||||
from.Fame = 0;
|
||||
|
||||
// I have seen the error of my ways!
|
||||
targ.PublicOverheadMessage( MessageType.Regular, 0x3B2, 1052009 );
|
||||
|
||||
from.SendLocalizedMessage( 1052010 ); // You have set the creature free.
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerCallback( targ.Delete ) );
|
||||
|
||||
pm.LastSacrificeGain = DateTime.UtcNow;
|
||||
|
||||
bool gainedPath = false;
|
||||
|
||||
if ( VirtueHelper.Award( from, VirtueName.Sacrifice, toGain, ref gainedPath ) )
|
||||
{
|
||||
if ( gainedPath )
|
||||
{
|
||||
from.SendLocalizedMessage( 1052008 ); // You have gained a path in Sacrifice!
|
||||
|
||||
if ( pm.AvailableResurrects < 3 )
|
||||
++pm.AvailableResurrects;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1054160 ); // You have gained in sacrifice.
|
||||
}
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage( 1052016 ); // You must wait approximately one day before sacrificing again.
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ValidateCreature( Mobile m )
|
||||
{
|
||||
if ( m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned) )
|
||||
return false;
|
||||
|
||||
return ( m is Lich || m is Succubus || m is Daemon || m is EvilMage || m is EnslavedGargoyle || m is GargoyleEnforcer );
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base( 8, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
Sacrifice( from, targeted );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
138
Scripts/Engines/Virtues/Valor.cs
Normal file
138
Scripts/Engines/Virtues/Valor.cs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using Server.Engines.CannedEvil;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class ValorVirtue
|
||||
{
|
||||
private static TimeSpan LossDelay = TimeSpan.FromDays( 7.0 );
|
||||
private const int LossAmount = 250;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
VirtueGump.Register( 112, new OnVirtueUsed( OnVirtueUsed ) );
|
||||
}
|
||||
|
||||
public static void OnVirtueUsed( Mobile from )
|
||||
{
|
||||
if( from.Alive )
|
||||
{
|
||||
from.SendLocalizedMessage( 1054034 ); // Target the Champion Idol of the Champion you wish to challenge!.
|
||||
from.Target = new InternalTarget();
|
||||
}
|
||||
}
|
||||
|
||||
public static void CheckAtrophy( Mobile from )
|
||||
{
|
||||
PlayerMobile pm = from as PlayerMobile;
|
||||
|
||||
if( pm == null )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if( (pm.LastValorLoss + LossDelay) < DateTime.UtcNow )
|
||||
{
|
||||
if( VirtueHelper.Atrophy( from, VirtueName.Valor, LossAmount ) )
|
||||
from.SendLocalizedMessage( 1054040 ); // You have lost some Valor.
|
||||
|
||||
pm.LastValorLoss = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void Valor( Mobile from, object targ )
|
||||
{
|
||||
IdolOfTheChampion idol = targ as IdolOfTheChampion;
|
||||
|
||||
if( idol == null || idol.Deleted || idol.Spawn == null || idol.Spawn.Deleted )
|
||||
from.SendLocalizedMessage( 1054035 ); // You must target a Champion Idol to challenge the Champion's spawn!
|
||||
else if( from.Hidden )
|
||||
from.SendLocalizedMessage( 1052015 ); // You cannot do that while hidden.
|
||||
else if( idol.Spawn.HasBeenAdvanced )
|
||||
from.SendLocalizedMessage( 1054038 ); // The Champion of this region has already been challenged!
|
||||
else
|
||||
{
|
||||
VirtueLevel vl = VirtueHelper.GetLevel( from, VirtueName.Valor );
|
||||
if( idol.Spawn.Active )
|
||||
{
|
||||
if( idol.Spawn.Champion != null ) //TODO: Message?
|
||||
return;
|
||||
|
||||
int needed, consumed;
|
||||
switch( idol.Spawn.GetSubLevel() )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
needed = consumed = 2500;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
needed = consumed = 5000;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
needed = 10000;
|
||||
consumed = 7500;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
needed = 20000;
|
||||
consumed = 10000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( from.Virtues.GetValue( (int)VirtueName.Valor ) >= needed )
|
||||
{
|
||||
VirtueHelper.Atrophy( from, VirtueName.Valor, consumed );
|
||||
from.SendLocalizedMessage( 1054037 ); // Your challenge is heard by the Champion of this region! Beware its wrath!
|
||||
idol.Spawn.HasBeenAdvanced = true;
|
||||
idol.Spawn.AdvanceLevel();
|
||||
}
|
||||
else
|
||||
from.SendLocalizedMessage( 1054039 ); // The Champion of this region ignores your challenge. You must further prove your valor.
|
||||
}
|
||||
else
|
||||
{
|
||||
if( vl == VirtueLevel.Knight )
|
||||
{
|
||||
VirtueHelper.Atrophy( from, VirtueName.Valor, 11000 );
|
||||
from.SendLocalizedMessage( 1054037 ); // Your challenge is heard by the Champion of this region! Beware its wrath!
|
||||
idol.Spawn.EndRestart();
|
||||
idol.Spawn.HasBeenAdvanced = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1054036 ); // You must be a Knight of Valor to summon the champion's spawn in this manner!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base( 14, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
Valor( from, targeted );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
186
Scripts/Engines/Virtues/VirtueGump.cs
Normal file
186
Scripts/Engines/Virtues/VirtueGump.cs
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public delegate void OnVirtueUsed( Mobile from );
|
||||
|
||||
public class VirtueGump : Gump
|
||||
{
|
||||
private static Dictionary<int, OnVirtueUsed> m_Callbacks = new Dictionary<int, OnVirtueUsed>();
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.VirtueGumpRequest += new VirtueGumpRequestEventHandler( EventSink_VirtueGumpRequest );
|
||||
EventSink.VirtueItemRequest += new VirtueItemRequestEventHandler( EventSink_VirtueItemRequest );
|
||||
EventSink.VirtueMacroRequest += new VirtueMacroRequestEventHandler( EventSink_VirtueMacroRequest );
|
||||
}
|
||||
|
||||
public static void Register( int gumpID, OnVirtueUsed callback )
|
||||
{
|
||||
m_Callbacks[gumpID] = callback;
|
||||
}
|
||||
|
||||
private static void EventSink_VirtueItemRequest( VirtueItemRequestEventArgs e )
|
||||
{
|
||||
if ( e.Beholder != e.Beheld )
|
||||
return;
|
||||
|
||||
e.Beholder.CloseGump( typeof( VirtueGump ) );
|
||||
|
||||
if ( e.Beholder.Kills >= 5 )
|
||||
{
|
||||
e.Beholder.SendLocalizedMessage( 1049609 ); // Murderers cannot invoke this virtue.
|
||||
return;
|
||||
}
|
||||
|
||||
OnVirtueUsed callback = null;
|
||||
|
||||
m_Callbacks.TryGetValue(e.GumpID, out callback);
|
||||
|
||||
if ( callback != null )
|
||||
callback( e.Beholder );
|
||||
else
|
||||
e.Beholder.SendLocalizedMessage( 1052066 ); // That virtue is not active yet.
|
||||
}
|
||||
|
||||
|
||||
private static void EventSink_VirtueMacroRequest( VirtueMacroRequestEventArgs e )
|
||||
{
|
||||
int virtueID = 0;
|
||||
|
||||
switch ( e.VirtueID )
|
||||
{
|
||||
case 0: // Honor
|
||||
virtueID = 107; break;
|
||||
case 1: // Sacrifice
|
||||
virtueID = 110; break;
|
||||
case 2: // Valor;
|
||||
virtueID = 112; break;
|
||||
}
|
||||
|
||||
EventSink_VirtueItemRequest( new VirtueItemRequestEventArgs( e.Mobile, e.Mobile, virtueID ) );
|
||||
}
|
||||
|
||||
private static void EventSink_VirtueGumpRequest( VirtueGumpRequestEventArgs e )
|
||||
{
|
||||
Mobile beholder = e.Beholder;
|
||||
Mobile beheld = e.Beheld;
|
||||
|
||||
if ( beholder == beheld && beholder.Kills >= 5 )
|
||||
{
|
||||
beholder.SendLocalizedMessage( 1049609 ); // Murderers cannot invoke this virtue.
|
||||
}
|
||||
else if ( beholder.Map == beheld.Map && beholder.InRange( beheld, 12 ) )
|
||||
{
|
||||
beholder.CloseGump( typeof( VirtueGump ) );
|
||||
beholder.SendGump( new VirtueGump( beholder, beheld ) );
|
||||
}
|
||||
}
|
||||
|
||||
private Mobile m_Beholder, m_Beheld;
|
||||
|
||||
public VirtueGump( Mobile beholder, Mobile beheld ) : base( 0, 0 )
|
||||
{
|
||||
m_Beholder = beholder;
|
||||
m_Beheld = beheld;
|
||||
|
||||
Serial = beheld.Serial;
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
AddImage( 30, 40, 104 );
|
||||
|
||||
AddPage( 1 );
|
||||
|
||||
Add( new InternalEntry( 61, 71, 108, GetHueFor( 0 ) ) ); // Humility
|
||||
Add( new InternalEntry( 123, 46, 112, GetHueFor( 4 ) ) ); // Valor
|
||||
Add( new InternalEntry( 187, 70, 107, GetHueFor( 5 ) ) ); // Honor
|
||||
Add( new InternalEntry( 35, 135, 110, GetHueFor( 1 ) ) ); // Sacrifice
|
||||
Add( new InternalEntry( 211, 133, 105, GetHueFor( 2 ) ) ); // Compassion
|
||||
Add( new InternalEntry( 61, 195, 111, GetHueFor( 3 ) ) ); // Spiritulaity
|
||||
Add( new InternalEntry( 186, 195, 109, GetHueFor( 6 ) ) ); // Justice
|
||||
Add( new InternalEntry( 121, 221, 106, GetHueFor( 7 ) ) ); // Honesty
|
||||
|
||||
if ( m_Beholder == m_Beheld )
|
||||
{
|
||||
AddButton( 57, 269, 2027, 2027, 1, GumpButtonType.Reply, 0 );
|
||||
AddButton( 186, 269, 2071, 2071, 2, GumpButtonType.Reply, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] m_Table = new int[24]
|
||||
{
|
||||
0x0481, 0x0963, 0x0965,
|
||||
0x060A, 0x060F, 0x002A,
|
||||
0x08A4, 0x08A7, 0x0034,
|
||||
0x0965, 0x08FD, 0x0480,
|
||||
0x00EA, 0x0845, 0x0020,
|
||||
0x0011, 0x0269, 0x013D,
|
||||
0x08A1, 0x08A3, 0x0042,
|
||||
0x0543, 0x0547, 0x0061
|
||||
};
|
||||
|
||||
private int GetHueFor( int index )
|
||||
{
|
||||
if ( m_Beheld.Virtues.GetValue( index ) == 0 )
|
||||
return 2402;
|
||||
|
||||
int value = m_Beheld.Virtues.GetValue( index );
|
||||
|
||||
if ( value < 4000 )
|
||||
return 2402;
|
||||
|
||||
if( value >= 30000 )
|
||||
value = 20000; //Sanity
|
||||
|
||||
|
||||
int vl;
|
||||
|
||||
if( value < 10000 )
|
||||
vl = 0;
|
||||
else if( value >= 20000 && index == 5)
|
||||
vl = 2;
|
||||
else if( value >= 21000 && index != 1)
|
||||
vl = 2;
|
||||
else if( value >= 22000 && index == 1)
|
||||
vl = 2;
|
||||
else
|
||||
vl = 1;
|
||||
|
||||
|
||||
return m_Table[(index * 3) + (int) vl];
|
||||
}
|
||||
|
||||
private class InternalEntry : GumpImage
|
||||
{
|
||||
public InternalEntry( int x, int y, int gumpID, int hue ) : base( x, y, gumpID, hue )
|
||||
{
|
||||
}
|
||||
|
||||
public override string Compile()
|
||||
{
|
||||
return String.Format( "{{ gumppic {0} {1} {2} hue={3} class=VirtueGumpItem }}", X, Y, GumpID, Hue );
|
||||
}
|
||||
|
||||
private static byte[] m_Class = Gump.StringToBuffer( " class=VirtueGumpItem" );
|
||||
|
||||
public override void AppendTo( IGumpWriter disp )
|
||||
{
|
||||
base.AppendTo( disp );
|
||||
|
||||
disp.AppendLayout( m_Class );
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState state, RelayInfo info )
|
||||
{
|
||||
if ( info.ButtonID == 1 && m_Beholder == m_Beheld )
|
||||
m_Beholder.SendGump( new VirtueStatusGump( m_Beholder ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Scripts/Engines/Virtues/VirtueHelper.cs
Normal file
162
Scripts/Engines/Virtues/VirtueHelper.cs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public enum VirtueLevel
|
||||
{
|
||||
None,
|
||||
Seeker,
|
||||
Follower,
|
||||
Knight
|
||||
}
|
||||
|
||||
public enum VirtueName
|
||||
{
|
||||
Humility,
|
||||
Sacrifice,
|
||||
Compassion,
|
||||
Spirituality,
|
||||
Valor,
|
||||
Honor,
|
||||
Justice,
|
||||
Honesty
|
||||
}
|
||||
|
||||
public class VirtueHelper
|
||||
{
|
||||
public static bool HasAny( Mobile from, VirtueName virtue )
|
||||
{
|
||||
return ( from.Virtues.GetValue( (int)virtue ) > 0 );
|
||||
}
|
||||
|
||||
public static bool IsHighestPath( Mobile from, VirtueName virtue )
|
||||
{
|
||||
return ( from.Virtues.GetValue( (int)virtue ) >= GetMaxAmount( virtue ) );
|
||||
}
|
||||
|
||||
public static VirtueLevel GetLevel( Mobile from, VirtueName virtue )
|
||||
{
|
||||
int v = from.Virtues.GetValue( (int)virtue );
|
||||
int vl;
|
||||
int vmax = GetMaxAmount( virtue );
|
||||
|
||||
if ( v < 4000 )
|
||||
vl = 0;
|
||||
else if ( v >= vmax)
|
||||
vl = 3;
|
||||
else
|
||||
vl = ( v + 9999 ) / 10000;
|
||||
|
||||
return (VirtueLevel)vl;
|
||||
}
|
||||
|
||||
public static int GetMaxAmount( VirtueName virtue )
|
||||
{
|
||||
if( virtue == VirtueName.Honor )
|
||||
return 20000;
|
||||
|
||||
if( virtue == VirtueName.Sacrifice )
|
||||
return 22000;
|
||||
|
||||
return 21000;
|
||||
}
|
||||
|
||||
public static bool Award( Mobile from, VirtueName virtue, int amount, ref bool gainedPath )
|
||||
{
|
||||
int current = from.Virtues.GetValue( (int)virtue );
|
||||
|
||||
int maxAmount = GetMaxAmount( virtue );
|
||||
|
||||
if ( current >= maxAmount )
|
||||
return false;
|
||||
|
||||
if( (current + amount) >= maxAmount )
|
||||
amount = maxAmount - current;
|
||||
|
||||
VirtueLevel oldLevel = GetLevel( from, virtue );
|
||||
|
||||
from.Virtues.SetValue( (int)virtue, current + amount );
|
||||
|
||||
gainedPath = ( GetLevel( from, virtue ) != oldLevel );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Atrophy( Mobile from, VirtueName virtue )
|
||||
{
|
||||
return Atrophy( from, virtue, 1 );
|
||||
}
|
||||
|
||||
public static bool Atrophy( Mobile from, VirtueName virtue, int amount )
|
||||
{
|
||||
int current = from.Virtues.GetValue( (int)virtue );
|
||||
|
||||
if( (current - amount) >= 0 )
|
||||
from.Virtues.SetValue( (int)virtue, current - amount );
|
||||
else
|
||||
from.Virtues.SetValue( (int)virtue, 0 );
|
||||
|
||||
return ( current > 0 );
|
||||
}
|
||||
|
||||
public static bool IsSeeker( Mobile from, VirtueName virtue )
|
||||
{
|
||||
return ( GetLevel( from, virtue ) >= VirtueLevel.Seeker );
|
||||
}
|
||||
|
||||
public static bool IsFollower( Mobile from, VirtueName virtue )
|
||||
{
|
||||
return ( GetLevel( from, virtue ) >= VirtueLevel.Follower );
|
||||
}
|
||||
|
||||
public static bool IsKnight( Mobile from, VirtueName virtue )
|
||||
{
|
||||
return ( GetLevel( from, virtue ) >= VirtueLevel.Knight );
|
||||
}
|
||||
|
||||
public static void AwardVirtue( PlayerMobile pm, VirtueName virtue, int amount )
|
||||
{
|
||||
if ( virtue == VirtueName.Compassion )
|
||||
{
|
||||
if ( pm.CompassionGains > 0 && DateTime.UtcNow > pm.NextCompassionDay )
|
||||
{
|
||||
pm.NextCompassionDay = DateTime.MinValue;
|
||||
pm.CompassionGains = 0;
|
||||
}
|
||||
|
||||
if ( pm.CompassionGains >= 5 )
|
||||
{
|
||||
pm.SendLocalizedMessage( 1053004 ); // You must wait about a day before you can gain in compassion again.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool gainedPath = false;
|
||||
string virtueName = Enum.GetName( typeof( VirtueName ), virtue );
|
||||
|
||||
if ( VirtueHelper.Award( pm, virtue, amount, ref gainedPath ) )
|
||||
{
|
||||
// TODO: Localize?
|
||||
if ( gainedPath )
|
||||
pm.SendMessage( "You have gained a path in {0}!", virtueName );
|
||||
else
|
||||
pm.SendMessage( "You have gained in {0}.", virtueName );
|
||||
|
||||
if ( virtue == VirtueName.Compassion )
|
||||
{
|
||||
pm.NextCompassionDay = DateTime.UtcNow + TimeSpan.FromDays( 1.0 );
|
||||
++pm.CompassionGains;
|
||||
|
||||
if ( pm.CompassionGains >= 5 )
|
||||
pm.SendLocalizedMessage( 1053004 ); // You must wait about a day before you can gain in compassion again.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Localize?
|
||||
pm.SendMessage( "You have achieved the highest path of {0} and can no longer gain any further.", virtueName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
110
Scripts/Engines/Virtues/VirtueInfoGump.cs
Normal file
110
Scripts/Engines/Virtues/VirtueInfoGump.cs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class VirtueInfoGump : Gump
|
||||
{
|
||||
private Mobile m_Beholder;
|
||||
private int m_Desc;
|
||||
private string m_Page;
|
||||
private VirtueName m_Virtue;
|
||||
|
||||
public VirtueInfoGump( Mobile beholder, VirtueName virtue, int description ) : this( beholder, virtue, description, null )
|
||||
{
|
||||
}
|
||||
|
||||
public VirtueInfoGump( Mobile beholder, VirtueName virtue, int description, string webPage ) : base( 0, 0 )
|
||||
{
|
||||
m_Beholder = beholder;
|
||||
m_Virtue = virtue;
|
||||
m_Desc = description;
|
||||
m_Page = webPage;
|
||||
|
||||
int value = beholder.Virtues.GetValue( (int)virtue );
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
AddImage( 30, 40, 2080 );
|
||||
AddImage( 47, 77, 2081 );
|
||||
AddImage( 47, 147, 2081 );
|
||||
AddImage( 47, 217, 2081 );
|
||||
AddImage( 47, 267, 2083 );
|
||||
AddImage( 70, 213, 2091 );
|
||||
|
||||
AddPage( 1 );
|
||||
|
||||
int maxValue = VirtueHelper.GetMaxAmount( m_Virtue );
|
||||
|
||||
int valueDesc;
|
||||
int dots;
|
||||
|
||||
if( value < 4000 )
|
||||
dots = value / 400;
|
||||
else if( value < 10000 )
|
||||
dots = (value - 4000) / 600;
|
||||
else if( value < maxValue )
|
||||
dots = (value - 10000) / ((maxValue-10000)/10);
|
||||
else
|
||||
dots = 10;
|
||||
|
||||
for ( int i = 0; i < 10; ++i )
|
||||
AddImage( 95 + (i * 17), 50, i < dots ? 2362 : 2360 );
|
||||
|
||||
|
||||
if( value < 1 )
|
||||
valueDesc = 1052044; // You have not started on the path of this Virtue.
|
||||
else if( value < 400 )
|
||||
valueDesc = 1052045; // You have barely begun your journey through the path of this Virtue.
|
||||
else if( value < 2000 )
|
||||
valueDesc = 1052046; // You have progressed in this Virtue, but still have much to do.
|
||||
else if( value < 3600 )
|
||||
valueDesc = 1052047; // Your journey through the path of this Virtue is going well.
|
||||
else if( value < 4000 )
|
||||
valueDesc = 1052048; // You feel very close to achieving your next path in this Virtue.
|
||||
else if( dots < 1 )
|
||||
valueDesc = 1052049; // You have achieved a path in this Virtue.
|
||||
else if( dots < 9 )
|
||||
valueDesc = 1052047; // Your journey through the path of this Virtue is going well.
|
||||
else if( dots < 10 )
|
||||
valueDesc = 1052048; // You feel very close to achieving your next path in this Virtue.
|
||||
else
|
||||
valueDesc = 1052050; // You have achieved the highest path in this Virtue.
|
||||
|
||||
|
||||
AddHtmlLocalized( 157, 73, 200, 40, 1051000 + (int)virtue, false, false );
|
||||
AddHtmlLocalized( 75, 95, 220, 140, description, false, false );
|
||||
AddHtmlLocalized( 70, 224, 229, 60, valueDesc, false, false );
|
||||
|
||||
AddButton( 65, 277, 1209, 1209, 1, GumpButtonType.Reply, 0 );
|
||||
|
||||
AddButton( 280, 43, 4014, 4014, 2, GumpButtonType.Reply, 0 );
|
||||
|
||||
AddHtmlLocalized( 83, 275, 400, 40, (webPage == null) ? 1052055 : 1052052, false, false ); // This virtue is not yet defined. OR -click to learn more (opens webpage)
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState state, RelayInfo info )
|
||||
{
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, m_Virtue, m_Desc, m_Page ) );
|
||||
|
||||
if( m_Page != null )
|
||||
state.Send( new LaunchBrowser( m_Page ) ); //No message about web browser starting on OSI
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueStatusGump( m_Beholder ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
104
Scripts/Engines/Virtues/VirtueStatusGump.cs
Normal file
104
Scripts/Engines/Virtues/VirtueStatusGump.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class VirtueStatusGump : Gump
|
||||
{
|
||||
private Mobile m_Beholder;
|
||||
|
||||
public VirtueStatusGump( Mobile beholder ) : base( 0, 0 )
|
||||
{
|
||||
m_Beholder = beholder;
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
AddImage( 30, 40, 2080 );
|
||||
AddImage( 47, 77, 2081 );
|
||||
AddImage( 47, 147, 2081 );
|
||||
AddImage( 47, 217, 2081 );
|
||||
AddImage( 47, 267, 2083 );
|
||||
AddImage( 70, 213, 2091 );
|
||||
|
||||
AddPage( 1 );
|
||||
|
||||
AddHtml( 140, 73, 200, 20, "The Virtues", false, false );
|
||||
|
||||
AddHtmlLocalized( 80, 100, 100, 40, 1051000, false, false ); // Humility
|
||||
AddHtmlLocalized( 80, 129, 100, 40, 1051001, false, false ); // Sacrifice
|
||||
AddHtmlLocalized( 80, 159, 100, 40, 1051002, false, false ); // Compassion
|
||||
AddHtmlLocalized( 80, 189, 100, 40, 1051003, false, false ); // Spirituality
|
||||
AddHtmlLocalized( 200, 100, 200, 40, 1051004, false, false ); // Valor
|
||||
AddHtmlLocalized( 200, 129, 200, 40, 1051005, false, false ); // Honor
|
||||
AddHtmlLocalized( 200, 159, 200, 40, 1051006, false, false ); // Justice
|
||||
AddHtmlLocalized( 200, 189, 200, 40, 1051007, false, false ); // Honesty
|
||||
|
||||
AddHtmlLocalized( 75, 224, 220, 60, 1052062, false, false ); // Click on a blue gem to view your status in that virtue.
|
||||
|
||||
AddButton( 60, 100, 1210, 1210, 1, GumpButtonType.Reply, 0 );
|
||||
AddButton( 60, 129, 1210, 1210, 2, GumpButtonType.Reply, 0 );
|
||||
AddButton( 60, 159, 1210, 1210, 3, GumpButtonType.Reply, 0 );
|
||||
AddButton( 60, 189, 1210, 1210, 4, GumpButtonType.Reply, 0 );
|
||||
AddButton( 180, 100, 1210, 1210, 5, GumpButtonType.Reply, 0 );
|
||||
AddButton( 180, 129, 1210, 1210, 6, GumpButtonType.Reply, 0 );
|
||||
AddButton( 180, 159, 1210, 1210, 7, GumpButtonType.Reply, 0 );
|
||||
AddButton( 180, 189, 1210, 1210, 8, GumpButtonType.Reply, 0 );
|
||||
|
||||
AddButton( 280, 43, 4014, 4014, 9, GumpButtonType.Reply, 0 );
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState state, RelayInfo info )
|
||||
{
|
||||
switch ( info.ButtonID )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Humility, 1052051 ) );
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Sacrifice, 1052053, @"http://update.uo.com/design_389.html" ) );
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Compassion, 1053000, @"http://update.uo.com/design_412.html" ) );
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Spirituality, 1052056 ) );
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Valor, 1054033, @"http://update.uo.com/design_427.html" ) );
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Honor, 1052058, @"http://guide.uo.com/virtues_2.html" ) );
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Justice, 1052059, @"http://update.uo.com/design_413.html" ) );
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueInfoGump( m_Beholder, VirtueName.Honesty, 1052060 ) );
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
m_Beholder.SendGump( new VirtueGump( m_Beholder, m_Beholder ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue