So I was reminiscing about powerhour and how cool it was to have a super gaining duration. I know this script exists on other servers, but no one has publicly released it onto runuo.com or servuo.com; I think, in part, because there are some who believe its not necessary with the GGS in place. However what about those of us who still use Rate Over Time?! Just a thought.

So I did some digging and I came up with these links:
http://www.runuo.com/community/threads/power-hour.95461/#post-801732
http://www.runuo.com/community/threads/runuo-svn-gain-potions.484250/#post-3737580
http://www.runuo.com/community/threads/power-hour.60203/

And remarkable I came up with nothing except a few broken references. So I decided to use the first link (in the list above) and came up with this:

PowerHour.cs

Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;

using Server;
using Server.Commands;
using Server.Items;
using Server.Mobiles;


namespace Server.Misc
{
    public class PowerHour
    {
        const int StartTime = 19, EndTime = 20; // Happy Hour from 7:00pm to 8:00pm (clock is  in 24hr format)

        //public void SendNotification (Mobile from)
        //{
        //    if (DateTime.Now.Hour >= StartTime)
        //    {
        //        from.PlaySound(0xFF);
        //        from.SendMessage("Power Hour is upon us, make haste and hone your skills wisely!");
        //        //World.Broadcast(0x35, true, "Power Hour is upon us, make haste and hone your skills wisely!");
        //    }
        //    else if (DateTime.Now.Hour < EndTime)
        //    {
        //        from.PlaySound(0xFE);
        //        from.SendMessage("Power Hour hath ended!");
        //        //World.Broadcast(0x35, true, "Power Hour hath ended!");
        //    }
        //    else
        //    {
        //       
        //    }
        //}

        public static bool On
        {
            get
            {
                return ((DateTime.Now.Hour >= StartTime) && (DateTime.Now.Hour < EndTime));    
            }
        }
    }
}

SkillCheck.cs

Code:
        public static void Gain( Mobile from, Skill skill )
        {
            if ( from.Region.IsPartOf( typeof( Regions.Jail ) ) )
                return;

            if ( from is BaseCreature && ((BaseCreature)from).IsDeadPet )
                return;

            if ( skill.SkillName == SkillName.Focus && from is BaseCreature )
                return;

            if ( skill.Base < skill.Cap && skill.Lock == SkillLock.Up )
            {
                int toGain = 1;

                #region Powerhour Testing

                if (PowerHour.On)   
                {
                    toGain = toGain * 2;
                    // Console.WriteLine("This Is Your Total Gain:" + toGain); // Debug
                }
                else if (!PowerHour.On) 
                {
                    toGain = toGain * 1;

                    // Console.WriteLine("This Is Your Total Gain:" + toGain); // Debug
                }

                #endregion

                if ( skill.Base <= 10.0 )
                    toGain = Utility.Random( 4 ) + 1;

What I need, and I'm having trouble with, is sending a global message that tells players when powerhour begins and when powerhour ends (with a warning about 5 min before it ends). I've never been too good with timers and I'm not too familiar with DateTime.UtcNow (I don't know which clock that derives from), so I used DateTime.Now which reads off the servers local clock. The commented out portion above is commented because it compiles but it doesn't work; the sound never plays and the messages don't display.

Catch 22: This script may not be useful for everyone, but this is the complete system listed here. It's been tested and it does what is intended; it doubles your skill gain during a specified hour. I'm just asking if anyone wants to help me with my issues above regarding a potential timer/ global message edit, and I'm asking if anyone wants to contribute anything else to this system here on the forum; maybe add a toggle so that the system can be shut on and off. The possibilities are endless ;)
 
I'm just going to gloss over how I handled power hour on my shard, it was a bit of a quick and dirty, no doubt there are better ways to handle it, but this has been live on my shard for about a year without any reported problems. It might just be good to give you some ideas of how to do it yourself.

Features:
  • Players are not forced into taking their power hour at a particular time.
  • Power hour can be activated every 23 hours.
  • Power hour bonus can be customized per skill, so for example you can give a huge bonus for Swordsmanship but only a small bonus for crafting skills.
  • This uses PlayerMobile.cs and SkillCheck.cs edits, there are probably ways to do this with zero edits since I believe there are event handlers for skill checks.
PlayerMobile portion:
Code:
        #region Skill gain bonuses

        private bool m_PowerHour;
        private DateTime m_LastPowerHour;
        private DateTime m_LastPowerHourDeed;

        // no reason this shouldn't be auto property. should probably be private.
        public DateTime LastPowerHour
        {
            get { return m_LastPowerHour; }
            set { m_LastPowerHour = value; }
        }

        // timespan.zero means power hour is ready.
        public TimeSpan TimeUntilPowerHour
        {
            get
            {
                TimeSpan ts = m_LastPowerHour - DateTime.UtcNow + TimeSpan.FromHours(23.0);
                if (ts <= TimeSpan.Zero)
                    return TimeSpan.Zero;

                return ts;
            }
        }

        // a string explaining time until next power hour, for use in gumps etc
        public string PowerHourString
        {
            get
            {
                if (TimeUntilPowerHour == TimeSpan.Zero)
                    return "Your power hour is ready now.";

                int hours = TimeUntilPowerHour.Hours;
                int minutes = TimeUntilPowerHour.Minutes;

                return hours.ToString() + (hours == 1 ? " hour and " : " hours and ") + minutes +
                       (minutes == 1 ? " minute" : " minutes");
            }
        }

        // checked on skill gain, player will receive a message saying power hour is up the first time they try gain a skill after PH finishes
        public bool IsPowerHour
        {
            get
            {
                if (!m_PowerHour)
                    return false;

                if (m_LastPowerHourDeed + TimeSpan.FromHours(1.0) > DateTime.UtcNow)
                    return true;

                if (m_LastPowerHour + TimeSpan.FromHours(1.0) > DateTime.UtcNow)
                    return true;
               
                SendMessage("Your enthusiasm fades and you no longer feel passionate about learning new skills.");
                m_PowerHour = false;

                return false;
            }
        }

        // TRY actvate
        public void TryActivatePowerhour()
        {
            if (IsPowerHour)
                SendMessage("It is already power hour.");
            else if (TimeUntilPowerHour == TimeSpan.Zero)
                ActivatePowerHour(false);
            else
                SendMessage("You must wait another " + PowerHourString + " until your next power hour.");
        }

        // FORCE activate
        public void ActivatePowerHour(bool deed)
        {
            if (deed)
                m_LastPowerHourDeed = DateTime.UtcNow;
            else
                m_LastPowerHour = DateTime.UtcNow;

            m_PowerHour = true;
            FixedParticles(0x375A, 10, 15, 5010, EffectLayer.Waist);
            PlaySound(0x1EE);
            SendMessage("You feel vigorous and able to learn skills more efficiently!");
        }

        #endregion

PlayerMobile serialization:
Code:
Serialize:
writer.Write(m_LastPowerHourDeed);
writer.Write(m_LastPowerHour);

Deserialize:
m_LastPowerHourDeed = reader.ReadDateTime();
m_LastPowerHour = reader.ReadDateTime();
m_PowerHour = m_LastPowerHour + TimeSpan.FromHours(1.0) > DateTime.UtcNow;

I have this code in the CheckSkill method of SkillCheck.cs:
Code:
            var pm = from as PlayerMobile
            if (pm!=null && pm.IsPowerHour)
            {
                    if (from.AccessLevel >= AccessLevel.Owner)
                        from.SendMessage("You are benefiting from accelerated gains.");
                    diff *= skill.Info.PowerHourMod;
            }

Ok finally, that list little piece of code "diff *= skill.Info.PowerHourMod" is what makes the power hour modification different per skill. For this I made a core edit, but this is doable without editing the core pretty easily with a pre-formed dictionary. If you want a simple flat rate for power hour gains just change it to something like "diff *= 2".

And last but not least you probably realised there's no way to actually activate power hour with this code. On my own server it's activated through gumps or power hour deeds (the deeds are purchasable for a special currency). To create your own methods of activating power hour, you just want to call either "TryActivatePowerhour" or "ActivatePowerHour" - the former being used unless it's a special case where you are force activating and ignoring normal time constraints.
 
Last edited:
@gametec
Credit to: Warumschletes and Soteric

Found something that works with your method, which I like.
using System;


using System.IO;


using Server;


namespace Server.Misc

{

public class PowerHour

{

const int Begin = 19, End = 20;// Power Hour from 19 to 20

public static void Initialize()

{


Timer t = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMilliseconds(500), delegate()

{


TimeSpan nowTime = DateTime.Now.TimeOfDay;

if (nowTime.Hours == 18 && nowTime.Minutes == 45 && nowTime.Seconds == 0)

World.Broadcast(0x22, true, "Power hour will start in 15 minutes.");

if (nowTime.Hours == 19 && nowTime.Minutes == 0 && nowTime.Seconds == 0)

World.Broadcast(0x22, true, "Power hour is now active!!");

if (nowTime.Hours == 19 && nowTime.Minutes == 15 && nowTime.Seconds == 0)

World.Broadcast(0x22, true, "Power hour is currently active, with 45 minutes remaining!!");

if (nowTime.Hours == 19 && nowTime.Minutes == 30 && nowTime.Seconds == 0)

World.Broadcast(0x22, true, "Power hour is currently active, with 30 minutes remaining!!");

if (nowTime.Hours == 19 && nowTime.Minutes == 45 && nowTime.Seconds == 0)

World.Broadcast(0x22, true, "Power hour is currently active, with 15 minutes remaining!!");

if (nowTime.Hours == 20 && nowTime.Minutes == 0 && nowTime.Seconds == 0)

World.Broadcast(0x22, true, "Power hour has now ended!!");

});


}


public static bool On

{

get { return ((Begin <= DateTime.Now.Hour) && (DateTime.Now.Hour <= End)); }

}

}

}
Pre-PowerHour.jpg
 

Attachments

  • PowerHour.cs
    1.7 KB · Views: 71
Back