RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Power Hour

milt

Knight
Power Hour

I don't know why I haven't seen anyone release a version of power hour, but I was eager to make it myself.

I made a pretty stable system, but I am not quite sure on the exact changes in gaining. Does anyone know the specific stats of how much extra you gain during your power hour for stats and skills? Any help appreciated.

Thanks
 

LordHogFred

Knight
You never actually gained more as such. You just had a chance of gaining more often. In your powerhour you had twice the chance of gaining skills as opposed to any other time.
 

Packer898

Knight
Which version of powerhour are you talking about? Officially before they even acknowledged the the timed powerhours with the messages they had powerhours between 11-12 CST on Atlantic. Everyone would crowd into the Deceit bone knight rooms then and you could actually gain pretty good. Then like they turned off a switch at 12 CST the gains would stop.

Then I remember they changed it so that your first 1 hour of playtime every 24 hours you would gain better. Everyone would log off on boats etc... to 8x8 magery when they first logged on. We would always log off at the wisp spawn then all log on together and train resist.

Then they added the messages displaying when powerhour was.

SO which one are you trying to implement? 1, 2 or 3? =)-
 

Kamron

Knight
I am trying to remember how the original powerhour works (I have it coded at home). The one that was used for the majority of its lifespan worked (basically) how Packer explained it~
Packet898 said:
Then I remember they changed it so that your first 1 hour of playtime every 24 hours you would gain better.
To elaborate, when you logged on (lets say the first time in 2 weeks), your powerhour started immediately. It lasted 1 hour, then after that it would start again in 24 hours. Now if you did not login for more than 24 hours, it would start immediately when you logged in, and your next powerhour starts 24 hours after that.

Also as Packer said they used messages to indicate when it started/ended. They also used sounds, but I don't remember exactly which ones, and if it was when it ended or started, etc.
 

Packer898

Knight
The "original" one was denied to be in operation by OSI for a long time. But the logs from players etc.. proved that it was from 11-12 on Atlantic shard. Then around pub 14? they changed it to be the first hour you logged on with no messages or warnings etc... then later on add the messages and such.
 

milt

Knight
Hmm well I realize what you guys mean. I have thought of many different ways that I can code it, but I think I like the version where it actually says "Your power hour will begin soon" and etc. I didn't play too often back then, but every once and awhile I played my friends account. I think it used to be so that you got to choose when your power hour would be, by saying 'power hour' and then it would say "Your power hour will begin soon" and then like five mins later it would start it. *sigh* I remember the good old days of OSI... I sort of miss that
 

milt

Knight
By the way, I will show you the main PowerHour.cs. It's really simple and is not intended to be 100% accurate or stable. This is what I have done so far:

Code:
using System;
using Server;
using System.Collections;
using Server.Mobiles;
using Server.Items;
namespace Server.Mobiles
{
 public class PowerHourClass
 {
  public static void Initialize()
  {
   //register event handler
   EventSink.Speech += new SpeechEventHandler( EventSink_PowerHour );
  }
  public static void EventSink_PowerHour( SpeechEventArgs e )
  {
   Mobile from = e.Mobile;
   if ( e.Speech == "power hour" )
   {
    if( from is PlayerMobile )
    {
     PlayerMobile pm = (PlayerMobile)from;
     if( pm.PowerHour == PowerHour.Current )
      from.SendMessage("You are already in your power hour.");
     else if( pm.PowerHour == PowerHour.Waiting )
      from.SendMessage("You are already waiting for your power hour to start");
     else if( pm.PowerHour == PowerHour.Used )
      from.SendMessage("You have already used your power hour in the past 24 hours. Try again later.");
     else if( pm.PowerHour == PowerHour.Ready )
     {
      pm.PowerHour = PowerHour.Waiting;
      Timer t = new WaitPowerHourTimer(pm);
      t.Start();
      pm.SendMessage("Your power hour will begin soon.");
     }
     else
      from.SendMessage("An error occured. Please contact a gamemaster if you encounter this error.");
    }
   }
  }
  public class WaitPowerHourTimer : Timer
  {
   private PlayerMobile pm;
   public WaitPowerHourTimer( PlayerMobile from ) : base( TimeSpan.FromMinutes( 5.0 ) )
   {
    pm = from;
   }
   protected override void OnTick()
   {
    pm.PowerHour = PowerHour.Current;
    pm.SendMessage("Your power hour has began.");
    Timer ti = new PowerHourTimer(pm);
    ti.Start();
   }
  }
  public class PowerHourTimer : Timer
  {
   private PlayerMobile pm;
   public PowerHourTimer( PlayerMobile from ) : base( TimeSpan.FromMinutes( 60.0 ) )
   {
    pm = from;
   }
   protected override void OnTick()
   {
    pm.PowerHour = PowerHour.Used;
    pm.SendMessage("Your power hour has ended.");
    Timer t = new WaitTimer(pm);
    t.Start();
   }
  }
  public class WaitTimer : Timer
  {
   private PlayerMobile pm;
   public WaitTimer( PlayerMobile from ) : base( TimeSpan.FromHours( 24.0 ) )
   {
    pm = from;
   }
   protected override void OnTick()
   {
    pm.PowerHour = PowerHour.Ready;
   }
  }
 }
}

As you may notice, sometimes I get frusterated when I try to name my classes, timers, variables etc. It's just the way I program and I know it might not be the best way. But anywho, aside this script, I have an enum in playermobile that has those phases of powerhour that you see in this script. Ready, Waiting, Current, and Used. I use those to set and detect multiple things. Also, I modified skillcheck.cs to do checks to see if it is PowerHour.Current for the players, and if so, do the appropriate stat and skill handling. But yeah, like I said, it's probably not the best or stable code, but it's my rough draft.
 

Packer898

Knight
Very nice. I was thinking about this myself but was not really looking forward to attempting it. Hopefully once you get this finished and tested you can release it. I for one would love to have it back on my shard =)- Wonderful WONDERFUL idea!
 

Kamron

Knight
So according to the way your power hour works, someone has to say the words for it to work... lol interesting, but kind of weird.
 

milt

Knight
Yeah, but isn't that the way that it used to be? I could almost swear that that is how it used to be when I played... Maybe it's just been so long. *confused* :confused:
 

Packer898

Knight
Powerhour started regardless on whether you said anything or not. I know after they added the timer and messages that I would be doing something and then get the message that my powerhour has started and be like "Oh SHit" lol. The messages should just check what the status is( ie 5 minutes to go or whatever) not be the trigger for them.
 

Rabban

Sorceror
Well the funny part is that a friend of mine swears up and down that the RunUO shard we play on (which uses very few unique scripts) has a power hour for the first hour you log in per 24 hours.

I haven't tested it, but he says that he gains better right after he first logs in each day (might be his imagination). I've checked the default distribution of RunUO and found no trace of said powerhour, so he may very well be crazy.
 

milt

Knight
Yeh, and a timer to toggle when they can do powerhour... :) I've had so many ideas latley on how I can do it
 

Admin God

Wanderer
lol hmm be a bit of work but i guess you could compile all the ideas into one with a control panel to offer admins a way of deciding which to use... I'm up for the challenge if you want help.
 

LordHogFred

Knight
I can't wait to have this on my shard now, it'll allow me to make initial gains lower but make the power hours really useful.

Any chance of a SkillCheck.cs that's compatible with your PowerHour.cs you posted? :p
 

milt

Knight
Well, I'll give you mine, but just letting you know before hand that it may not be accurate. You can check out where I incorporated the power hour, and make your custom changes from there. Here it is:

Code:
using System;
using Server;
using Server.Mobiles;
namespace Server.Misc
{
 public class SkillCheck
 {
  private const bool AntiMacroCode = true;  //Change this to false to disable anti-macro code
  public static TimeSpan AntiMacroExpire = TimeSpan.FromMinutes( 5.0 ); //How long do we remember targets/locations?
  public const int Allowance = 3; //How many times may we use the same location/target for gain
  private const int LocationSize = 5; //The size of eeach location, make this smaller so players dont have to move as far
  private static bool[] UseAntiMacro = new bool[]
  {
   // true if this skill uses the anti-macro code, false if it does not
   false,// Alchemy = 0,
   true,// Anatomy = 1,
   true,// AnimalLore = 2,
   true,// ItemID = 3,
   true,// ArmsLore = 4,
   false,// Parry = 5,
   true,// Begging = 6,
   false,// Blacksmith = 7,
   false,// Fletching = 8,
   true,// Peacemaking = 9,
   true,// Camping = 10,
   false,// Carpentry = 11,
   false,// Cartography = 12,
   false,// Cooking = 13,
   true,// DetectHidden = 14,
   true,// Discordance = 15,
   true,// EvalInt = 16,
   true,// Healing = 17,
   true,// Fishing = 18,
   true,// Forensics = 19,
   true,// Herding = 20,
   true,// Hiding = 21,
   true,// Provocation = 22,
   false,// Inscribe = 23,
   true,// Lockpicking = 24,
   true,// Magery = 25,
   true,// MagicResist = 26,
   false,// Tactics = 27,
   true,// Snooping = 28,
   true,// Musicianship = 29,
   true,// Poisoning = 30,
   false,// Archery = 31,
   true,// SpiritSpeak = 32,
   true,// Stealing = 33,
   false,// Tailoring = 34,
   true,// AnimalTaming = 35,
   true,// TasteID = 36,
   false,// Tinkering = 37,
   true,// Tracking = 38,
   true,// Veterinary = 39,
   false,// Swords = 40,
   false,// Macing = 41,
   false,// Fencing = 42,
   false,// Wrestling = 43,
   true,// Lumberjacking = 44,
   true,// Mining = 45,
   true,// Meditation = 46,
   true,// Stealth = 47,
   true,// RemoveTrap = 48,
   true,// Necromancy = 49,
   false,// Focus = 50,
   true,// Chivalry = 51
   true,// Bushido = 52
   true,//Ninjitsu = 53
  };
  public static void Initialize()
  {
   Mobile.SkillCheckLocationHandler = new SkillCheckLocationHandler( Mobile_SkillCheckLocation );
   Mobile.SkillCheckDirectLocationHandler = new SkillCheckDirectLocationHandler( Mobile_SkillCheckDirectLocation );
   Mobile.SkillCheckTargetHandler = new SkillCheckTargetHandler( Mobile_SkillCheckTarget );
   Mobile.SkillCheckDirectTargetHandler = new SkillCheckDirectTargetHandler( Mobile_SkillCheckDirectTarget );
  }
  public static bool Mobile_SkillCheckLocation( Mobile from, SkillName skillName, double minSkill, double maxSkill )
  {
   Skill skill = from.Skills[skillName];
   if ( skill == null )
    return false;
   double value = skill.Value;
   if ( value < minSkill )
    return false; // Too difficult
   else if ( value >= maxSkill )
    return true; // No challenge
   double chance = (value - minSkill) / (maxSkill - minSkill);
   Point2D loc = new Point2D( from.Location.X / LocationSize, from.Location.Y / LocationSize );
   return CheckSkill( from, skill, loc, chance );
  }
  public static bool Mobile_SkillCheckDirectLocation( Mobile from, SkillName skillName, double chance )
  {
   Skill skill = from.Skills[skillName];
   if ( skill == null )
    return false;
   if ( chance < 0.0 )
    return false; // Too difficult
   else if ( chance >= 1.0 )
    return true; // No challenge
   Point2D loc = new Point2D( from.Location.X / LocationSize, from.Location.Y / LocationSize );
   return CheckSkill( from, skill, loc, chance );
  }
  public static bool CheckSkill( Mobile from, Skill skill, object amObj, double chance )
  {
   if ( from.Skills.Cap == 0 )
    return false;
   bool success = ( chance >= Utility.RandomDouble() );
   double gc = (double)(from.Skills.Cap - from.Skills.Total) / from.Skills.Cap;
   gc += ( skill.Cap - skill.Base ) / skill.Cap;
   gc /= 2;
[COLOR=red]   if(from is PlayerMobile)
   {
    PlayerMobile myPM = (PlayerMobile)from;
    if(myPM.PowerHour == PowerHour.Current)
     gc += ( 1.0 - chance ) * ( success ? 0.6 : 0.3 );[/COLOR]
[COLOR=red]    else
     gc += ( 1.0 - chance ) * ( success ? 0.3 : 0.1 );
   }[/COLOR]
   gc /= 2;
   gc *= skill.Info.GainFactor;
   if ( gc < 0.01 )
    gc = 0.01;
   if ( from is BaseCreature && ((BaseCreature)from).Controled )
    gc *= 2;
   if ( from.Alive && ( ( gc >= Utility.RandomDouble() && AllowGain( from, skill, amObj ) ) || skill.Base < 10.0 ) )
    Gain( from, skill );
   return success;
  }
  public static bool Mobile_SkillCheckTarget( Mobile from, SkillName skillName, object target, double minSkill, double maxSkill )
  {
   Skill skill = from.Skills[skillName];
   if ( skill == null )
    return false;
   double value = skill.Value;
   if ( value < minSkill )
    return false; // Too difficult
   else if ( value >= maxSkill )
    return true; // No challenge
   double chance = (value - minSkill) / (maxSkill - minSkill);
   return CheckSkill( from, skill, target, chance );
  }
  public static bool Mobile_SkillCheckDirectTarget( Mobile from, SkillName skillName, object target, double chance )
  {
   Skill skill = from.Skills[skillName];
   if ( skill == null )
    return false;
   if ( chance < 0.0 )
    return false; // Too difficult
   else if ( chance >= 1.0 )
    return true; // No challenge
   return CheckSkill( from, skill, target, chance );
  }
  private static bool AllowGain( Mobile from, Skill skill, object obj )
  {
   if ( from is PlayerMobile && AntiMacroCode && UseAntiMacro[skill.Info.SkillID] )
    return ((PlayerMobile)from).AntiMacroCheck( skill, obj );
   else
    return true;
  }
  public enum Stat { Str, Dex, Int }
  public static void Gain( Mobile from, Skill skill )
  {
   if ( from.Region is 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 )
   {
    [COLOR=red]int toGain;[/COLOR]
    [COLOR=red]if( from is PlayerMobile )
    {
     PlayerMobile that = (PlayerMobile)from;[/COLOR]
[COLOR=red]     if(that.PowerHour == PowerHour.Current)
      toGain = 3;
     else
      toGain = 1;
    }[/COLOR]
[COLOR=red]    else
     toGain = 1;[/COLOR]
    if ( skill.Base <= 10.0 )
     toGain = Utility.Random( 4 ) + 1;
    Skills skills = from.Skills;
    if ( ( skills.Total / skills.Cap ) >= Utility.RandomDouble() )//( skills.Total >= skills.Cap )
    {
     for ( int i = 0; i < skills.Length; ++i )
     {
      Skill toLower = skills[i];
      if ( toLower != skill && toLower.Lock == SkillLock.Down && toLower.BaseFixedPoint >= toGain )
      {
       toLower.BaseFixedPoint -= toGain;
       break;
      }
     }
    }
    if ( (skills.Total + toGain) <= skills.Cap )
    {
     skill.BaseFixedPoint += toGain;
    }
   }
   if ( skill.Lock == SkillLock.Up )
   {
    SkillInfo info = skill.Info;
    if ( from.StrLock == StatLockType.Up && (info.StrGain / 33.3) > Utility.RandomDouble() )
     GainStat( from, Stat.Str );
    else if ( from.DexLock == StatLockType.Up && (info.DexGain / 33.3) > Utility.RandomDouble() )
     GainStat( from, Stat.Dex );
    else if ( from.IntLock == StatLockType.Up && (info.IntGain / 33.3) > Utility.RandomDouble() )
     GainStat( from, Stat.Int );
   }
  }
  public static bool CanLower( Mobile from, Stat stat )
  {
   switch ( stat )
   {
    case Stat.Str: return ( from.StrLock == StatLockType.Down && from.RawStr > 10 );
    case Stat.Dex: return ( from.DexLock == StatLockType.Down && from.RawDex > 10 );
    case Stat.Int: return ( from.IntLock == StatLockType.Down && from.RawInt > 10 );
   }
   return false;
  }
  public static bool CanRaise( Mobile from, Stat stat )
  {
   if ( !(from is BaseCreature && ((BaseCreature)from).Controled) )
   {
    if ( from.RawStatTotal >= from.StatCap )
     return false;
   }
   switch ( stat )
   {
    case Stat.Str: return ( from.StrLock == StatLockType.Up && from.RawStr < 100 );
    case Stat.Dex: return ( from.DexLock == StatLockType.Up && from.RawDex < 100 );
    case Stat.Int: return ( from.IntLock == StatLockType.Up && from.RawInt < 100 );
   }
   return false;
  }
  public static void IncreaseStat( Mobile from, Stat stat, bool atrophy )
  {
   atrophy = atrophy || (from.RawStatTotal >= from.StatCap);
   switch ( stat )
   {
    case Stat.Str:
    {
     if ( atrophy )
     {
      if ( CanLower( from, Stat.Dex ) && (from.RawDex < from.RawInt || !CanLower( from, Stat.Int )) )
       --from.RawDex;
      else if ( CanLower( from, Stat.Int ) )
       --from.RawInt;
     }
     if ( CanRaise( from, Stat.Str ) )
      ++from.RawStr;
     break;
    }
    case Stat.Dex:
    {
     if ( atrophy )
     {
      if ( CanLower( from, Stat.Str ) && (from.RawStr < from.RawInt || !CanLower( from, Stat.Int )) )
       --from.RawStr;
      else if ( CanLower( from, Stat.Int ) )
       --from.RawInt;
     }
     if ( CanRaise( from, Stat.Dex ) )
      ++from.RawDex;
     break;
    }
    case Stat.Int:
    {
     if ( atrophy )
     {
      if ( CanLower( from, Stat.Str ) && (from.RawStr < from.RawDex || !CanLower( from, Stat.Dex )) )
       --from.RawStr;
      else if ( CanLower( from, Stat.Dex ) )
       --from.RawDex;
     }
     if ( CanRaise( from, Stat.Int ) )
      ++from.RawInt;
     break;
    }
   }
  }
  private static TimeSpan m_StatGainDelay = TimeSpan.FromMinutes( 10.0 );
[COLOR=red]  private static TimeSpan m_PHStatGainDelay = TimeSpan.FromMinutes( 5.0 );[/COLOR]
  public static void GainStat( Mobile from, Stat stat )
  {
[COLOR=red]   if(from is PlayerMobile)
   {
    PlayerMobile pm = (PlayerMobile)from;[/COLOR]
[COLOR=red]    if(pm.PowerHour == PowerHour.Current)
    {
     if ( (from.LastStatGain + m_PHStatGainDelay) >= DateTime.Now )
      return;
    }[/COLOR]
[COLOR=red]    else
    {
     if ( (from.LastStatGain + m_StatGainDelay) >= DateTime.Now )
      return;
    }
   }[/COLOR]
[COLOR=red]   else
   {
    if ( (from.LastStatGain + m_StatGainDelay) >= DateTime.Now )
     return;
   }[/COLOR]
   from.LastStatGain = DateTime.Now;
   bool atrophy = ( (from.RawStatTotal / (double)from.StatCap) >= Utility.RandomDouble() );
   IncreaseStat( from, stat, atrophy );
  }
 }
}

The parts in red were what I changed / added. Like I said, it may not be the most stable code and accurate, but since you asked, you may have it.
 
Top