public static void GodMode(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (!ch.Authorized("godmode")) return; if (ch.HasActionBit(PC.PLAYER_GODMODE)) { ch.RemoveActionBit(PC.PLAYER_GODMODE); ch.SendText("God mode off.\r\n"); } else { ch.SetActionBit(PC.PLAYER_GODMODE); ch.SendText("God mode on.\r\n"); } return; }
/// <summary> /// Sets and gets player configuration options. /// </summary> /// <param name="ch"></param> /// <param name="argument"></param> public static void Toggle(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (str.Length == 0) { ch.SendText("&+L+------------+------------------------------------------------------------+&n\r\n"); ch.SendText("&+L|&n&+m Option&+L |&n&+r Description&n &+L|&n\r\n"); ch.SendText("&+L+------------+------------------------------------------------------------+&n\r\n"); ch.SendText(ch.HasActionBit(PC.PLAYER_AUTOWRAP) ? "&+L[&+WX&+L]&n Autowrap &+L|&n &+cThe MUD automatically wraps long lines of text. &+L|&n\r\n" : "&+L[ ]&n Autowrap &+L|&n &+cThe MUD does not automatically wrap long text. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_BLANK) ? "&+L[&+WX&+L]&n Blank &+L|&n &+cYou have a blank line before your prompt. &+L|&n\r\n" : "&+L[ ]&n Blank &+L|&n &+cYou have no blank line before your prompt. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_BRIEF) ? "&+L[&+WX&+L]&n Brief &+L|&n &+cYou see brief descriptions. &+L|&n\r\n" : "&+L[ ]&n Brief &+L|&n &+cYou see long descriptions. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_CAST_TICK) ? "&+L[&+WX&+L]&n Casttick &+L|&n &+cYou see your casting ticks. &+L|&n\r\n" : "&+L[ ]&n Casttick &+L|&n &+cFor spam's sake, no casting ticks! &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_COMBINE) ? "&+L[&+WX&+L]&n Combine &+L|&n &+cYou see object lists in combined format. &+L|&n\r\n" : "&+L[ ]&n Combine &+L|&n &+cYou see object lists in single format. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_COLOR) ? "&+L[&+WX&+L]&n Color &+L|&n &+cYou see ANSI colors. &+L|&n\r\n" : "&+L[ ]&n Color &+L|&n &+cYou don't see ANSI colors. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_COLOR_CON) ? "&+L[&+WX&+L]&n Colorcon &+L|&n &+cYou see ANSI colors in consider messages. &+L|&n\r\n" : "&+L[ ]&n Colorcon &+L|&n &+cYou don't see ANSI colors in consider messages. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_MSP) ? "&+L[&+WX&+L]&n MSP &+L|&n &+cMUD Sound Protocol (MSP) support is on. &+L|&n\r\n" : "&+L[ ]&n MSP &+L|&n &+cMUD Sound Protocol (MSP) support is off. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_PAGER) ? "&+L[&+WX&+L]&n Pager &+L|&n &+cText is shown in separate pages. &+L|&n\r\n" : "&+L[ ]&n Pager &+L|&n &+cText is shown all-at-once with no paging. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_PROMPT) ? "&+L[&+WX&+L]&n Prompt &+L|&n &+cYou have a prompt. &+L|&n\r\n" : "&+L[ ]&n Prompt &+L|&n &+cYou don't have a prompt. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_SHOUT) ? "&+L[&+WX&+L]&n Shout &+L|&n &+cYou can hear shouts. &+L|&n\r\n" : "&+L[ ]&n Shout &+L|&n &+cYou cover your ears when someone is yelling. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_TELNET_GA) ? "&+L[&+WX&+L]&n TelnetGA &+L|&n &+cYou receive a telnet go-ahead sequence. &+L|&n\r\n" : "&+L[ ]&n TelnetGA &+L|&n &+cYou don't receive a telnet GA sequence. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_TELL) ? "&+L[&+WX&+L]&n Tell &+L|&n &+cYou can hear tells. &+L|&n\r\n" : "&+L[ ]&n Tell &+L|&n &+cYou are ignoring tells. &+L|&n\r\n" ); ch.SendText(ch.HasActionBit(PC.PLAYER_VICIOUS) ? "&+L[&+WX&+L]&n Vicious &+L|&n &+cYou are vicious and will kill mortally wounded foes. &+L|&n\r\n" : "&+L[ ]&n Vicious &+L|&n &+cYou aren't vicious and will spare a mortally wounded foe. &+L|&n\r\n"); ch.SendText(ch.HasActionBit(PC.PLAYER_MAP) ? "&+L[&+WX&+L]&n Map &+L|&n &+cYou see the maps. &+L|&n\r\n" : "&+L[ ]&n Map &+L|&n &+cYou do not see maps. &+L|&n\r\n"); if (ch.HasActionBit(PC.PLAYER_SILENCE)) { ch.SendText( "&+L[&+WX&+L]&n Silence &+L|&n &+cYou are silenced. &+L|&n\r\n"); } ch.SendText(!ch.HasActionBit(PC.PLAYER_NO_EMOTE) ? "&n" : "&+L[ ]&n emote | &+cYou can't emote. &+L|&n\r\n"); ch.SendText("&+L+------------+------------------------------------------------------------+&n\r\n"); string termStr = "&+L|&n &+cYour terminal type is " + ch.Socket.Terminal + " and MCCP is " + ch.Socket.MCCPEnabled + "."; while (termStr.Length < 82) termStr += " "; termStr += "&+L|&n\r\n"; ch.SendText(termStr); ch.SendText("&+L+-------------------------------------------------------------------------+&n\r\n"); } else { string word; Bitvector bit; int fSet; if (str[0][0] == '-') { fSet = 0; word = str[0].Substring(1); } else if (str[0][0] == '+') { fSet = 1; word = str[0].Substring(1); } else { fSet = 2; word = str[0]; } if (("blank".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_BLANK; else if (("autowrap".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_AUTOWRAP; else if (("brief".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_BRIEF; else if (("casttick".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_CAST_TICK; else if (("combine".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_COMBINE; else if (("color".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) { if (ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED) { ch.SendText("You cannot turn color off when using the enhanced client.\r\n"); return; } bit = PC.PLAYER_COLOR; } else if (("colorcon".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_COLOR_CON; else if (("msp".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_MSP; else if (("pager".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_PAGER; else if (("shout".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_SHOUT; else if (("prompt".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_PROMPT; else if (("telnetga".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_TELNET_GA; else if (("tell".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_TELL; else if (("vicious".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_VICIOUS; else if (("map".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_MAP; else if (("vicious".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_VICIOUS; else if (("compact".StartsWith(word, StringComparison.CurrentCultureIgnoreCase))) bit = PC.PLAYER_BLANK; else if (word.Contains("wimpy")) { CommandType.Interpret(ch, "wimpy " + word.Substring((word.IndexOf("wimpy") + 5))); return; } else if ("mccp".StartsWith(word, StringComparison.CurrentCultureIgnoreCase)) { ch.Socket.MCCPEnabled = !ch.Socket.MCCPEnabled; if (ch.Socket.MCCPEnabled) { ch.SendText("MCCP is now enabled."); } else { ch.SendText("MCCP is now disabled."); } return; } else { ch.SendText("&nConfig which option?\r\n"); return; } if (ch.IsClass(CharClass.Names.paladin) && bit == PC.PLAYER_VICIOUS) { ch.SendText("Paladins may not toggle vicious.\r\n"); /* Just to make sure they don't have it toggled on. */ ch.RemoveActionBit(bit); return; } if (fSet == 1) { if (bit != PC.PLAYER_NONE) { ch.SetActionBit(bit); } ch.SendText( (String.Format("&n{0} is now ON.\r\n", word.ToUpper()))); } else if (fSet == 0) { if (bit != PC.PLAYER_NONE) { ch.RemoveActionBit(bit); } ch.SendText((String.Format("&n{0} is now OFF.\r\n", word.ToUpper()))); } else if (fSet == 2) { if (bit != PC.PLAYER_NONE) { ch.ToggleActionBit(bit); } if (ch.HasActionBit(bit)) ch.SendText((String.Format("&n{0} is now ON.\r\n", word.ToUpper()))); else ch.SendText((String.Format("&n{0} is now OFF.\r\n", word.ToUpper()))); } } return; }
/// <summary> /// Lets a player turn ANSI color on and off. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void ColorCommand(CharData ch, string[] str) { if( ch == null ) return; if (!ch.HasActionBit(PC.PLAYER_COLOR)) { ch.SetActionBit(PC.PLAYER_COLOR); ch.SendText("&+LThe world becomes more &n&+mco&+Ml&+Wor&+Cf&n&+cul&+L.&n\r\n"); } else { SocketConnection.SendToCharBW("The color drains.\r\n", ch); ch.RemoveActionBit(PC.PLAYER_COLOR); } return; }
/// <summary> /// Used to flag a player as running or not running a bot. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Bot(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (ch.HasActionBit(PC.PLAYER_BOTTING)) { ch.RemoveActionBit(PC.PLAYER_BOTTING); ch.SendText("&nYou are no longer running a bot.\r\n"); SocketConnection.Act("$n&n's soul has returned to $s body.", ch, null, ch, SocketConnection.MessageTarget.room); } else { ch.SetActionBit(PC.PLAYER_BOTTING); ch.SendText("&nYou are now running a bot.\r\n"); SocketConnection.Act("$n&n's soul has left $s body.", ch, null, ch, SocketConnection.MessageTarget.room); } return; }
/// <summary> /// The camp function now simply creates a camp event. /// The Command.Quit function handles quitters and campers, based /// on the camping bit. The only goofy side effect of this is /// that an immortal who is camping can quit and get the /// "you roll up in your bedroll" message. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Camp(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (ch.CurrentPosition == Position.fighting || ch.Fighting) { ch.SendText("You're not gifted enough to make camp and fight at the same time.\r\n"); ch.RemoveActionBit(PC.PLAYER_CAMPING); return; } if (ch.FlightLevel != 0) { ch.SendText("Perhaps it would be more comfortable on the ground.\r\n"); return; } if (ch.HasActionBit(PC.PLAYER_CAMPING)) { ch.SendText("Your preparations are not quite complete.\r\n"); return; } if (ch.CurrentPosition < Position.stunned) { ch.SendText("Just lie still and finish &+RBle&+reding&n!\r\n"); return; } SocketConnection.Act("$n&n starts to set up camp.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You start to set up camp.\r\n"); ch.SetActionBit(PC.PLAYER_CAMPING); // Pass the character, the room they started camping in, and the // number of cycles to camp for // Pulse camp is 5 seconds, so make them wait for 1.5 minutes Event.CreateEvent(Event.EventType.camp, Event.TICK_CAMP, ch, ch.InRoom, 18); return; }
/// <summary> /// Command to set yourself as being away from keyboard. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void AFK(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (ch.HasActionBit(PC.PLAYER_AFK)) { ch.RemoveActionBit(PC.PLAYER_AFK); ch.SendText("&nYou are back at your keyboard.\r\n"); SocketConnection.Act("$n&n has returned to $s keyboard.", ch, null, ch, SocketConnection.MessageTarget.room); } else { ch.SetActionBit(PC.PLAYER_AFK); ch.SendText("&nYou are away from keyboard.\r\n"); SocketConnection.Act("$n&n has left $s keyboard.", ch, null, ch, SocketConnection.MessageTarget.room); } return; }
/// <summary> /// Meditate command. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Meditate(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (!ch.HasSkill("meditate")) { ch.SendText("You don't know how to meditate.\r\n"); return; } if (ch.HasActionBit(PC.PLAYER_MEDITATING)) { ch.RemoveActionBit(PC.PLAYER_MEDITATING); ch.SendText("You stop meditating.\r\n"); } if (ch.CurrentPosition != Position.resting) { ch.SendText("You must be resting in order to meditate.\r\n"); return; } if (ch.Fighting != null) { ch.SendText("Meditation during battle leads to permenant inner peace.\r\n"); return; } ch.SetActionBit(PC.PLAYER_MEDITATING); ch.WaitState(Skill.SkillList["meditate"].Delay); ch.PracticeSkill("meditate"); ch.SendText("You start meditating...\r\n"); return; }
/// <summary> /// Immortal invisibility command. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Invis(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (!ch.Authorized("wizinvis")) return; if (ch.HasActionBit(PC.PLAYER_WIZINVIS)) { ch.RemoveActionBit(PC.PLAYER_WIZINVIS); ch.SendText("You slowly fade back into existence.\r\n"); SocketConnection.Act("$n slowly fades into existence.", ch, null, null, SocketConnection.MessageTarget.room); } else { ch.SendText("You slowly vanish into thin air.\r\n"); SocketConnection.Act("$n slowly fades into thin air.", ch, null, null, SocketConnection.MessageTarget.room); ch.SetActionBit(PC.PLAYER_WIZINVIS); } return; }
/// <summary> /// Deliver a killing blow to the victim. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void KillingBlow( CharData ch, CharData victim ) { Event eventdata; Room room; bool noCorpse = false; StopFighting( victim, true ); if( victim.GroupLeader || victim.NextInGroup ) { victim.RemoveFromGroup( victim ); } if( ch != victim ) { if( victim.IsNPC() && victim.MobileTemplate.DeathFun.Count > 0 ) { victim.MobileTemplate.DeathFun[0].SpecFunction( victim, MobFun.PROC_NORMAL ); } // prog_death_trigger( victim ); } if( victim.IsNPC() && victim.DeathFunction != null ) { noCorpse = victim.DeathFunction.SpecFunction( victim, MobFun.PROC_DEATH ); } if( !noCorpse ) { MakeCorpse( victim ); } /* Strip all event-spells from victim! */ for( int i = (Database.EventList.Count - 1); i >= 0; i-- ) { eventdata = Database.EventList[i]; if( eventdata.Type == Event.EventType.immolate || eventdata.Type == Event.EventType.acid_arrow ) { if( (CharData)eventdata.Target2 == victim ) { Database.EventList.Remove( eventdata ); } } } if( victim.Rider ) { SocketConnection.Act( "$n&n dies suddenly, and you topple to the &n&+yground&n.", victim, null, victim.Rider, SocketConnection.MessageTarget.victim ); victim.Rider.Riding = null; victim.Rider.CurrentPosition = Position.resting; victim.Rider = null; } if( victim.Riding ) { SocketConnection.Act( "$n&n topples from you, &+Ldead&n.", victim, null, victim.Riding, SocketConnection.MessageTarget.victim ); victim.Riding.Rider = null; victim.Riding = null; } if (!victim.IsNPC() && victim.IsAffected(Affect.AFFECT_VAMP_BITE)) { victim.SetPermRace( Race.RACE_VAMPIRE ); } for (int i = (victim.Affected.Count - 1); i >= 0; i--) { /* Keep the ghoul affect */ if (!victim.IsNPC() && victim.IsAffected(Affect.AFFECT_WRAITHFORM)) { continue; } victim.RemoveAffect(victim.Affected[i]); } if( victim.IsNPC() ) { victim.MobileTemplate.NumberKilled++; // This may invalidate the char list. CharData.ExtractChar( victim, true ); return; } CharData.ExtractChar( victim, false ); //save corpses, don't wait til next save_corpse event Database.CorpseList.Save(); // Character has died in combat, extract them to repop point and put // them at the menu. /* * Pardon crimes once justice system is complete */ // This is where we send them to the menu. victim.DieFollower( victim.Name ); if( victim.InRoom ) { room = victim.InRoom; } else { List<RepopulationPoint> repoplist = victim.GetAvailableRepops(); if( repoplist.Count < 1 ) { victim.SendText( "There is no RepopPoint entry for your race and class. Sending you to limbo.\r\n" ); room = Room.GetRoom( StaticRooms.GetRoomNumber("ROOM_NUMBER_START") ); } else { // Drop them at the first repop point in the list. We may want to be fancier about this later, such as dropping them // at the repop for class none if their particular class isn't found. room = Room.GetRoom(repoplist[0].Room); if( !room ) { victim.SendText( "The repop point for your race/class does not exist. Please bug this. Sending you to limbo.\r\n" ); room = Room.GetRoom( StaticRooms.GetRoomNumber("ROOM_NUMBER_START") ); } if( !victim.IsNPC() && Room.GetRoom( ( (PC)victim ).CurrentHome ) ) { room = Room.GetRoom( ( (PC)victim ).CurrentHome ); } } } victim.RemoveFromRoom(); if( room ) { victim.InRoom = room; } // Put them in the correct body if( victim.Socket && victim.Socket.Original ) { CommandType.Interpret(victim, "return"); } // Reset reply pointers - handled by CharData.ExtractChar. CharData.SavePlayer( victim ); // Remove from char list: handled by CharData.ExtractChar. victim.Socket.ShowScreen(ModernMUD.Screen.MainMenuScreen); if( victim.Socket != null ) { victim.Socket.ConnectionStatus = SocketConnection.ConnectionState.menu; } // Just died flag used for safe time after re-login. victim.SetActionBit( PC.PLAYER_JUST_DIED ); return; }
/// <summary> /// This is called by Command.Memorize and Commandpray. This was originally /// attached to each function, but it's silly to have two large blocks /// of the same code /// </summary> /// <param name="ch"></param> /// <param name="argument"></param> /// <param name="pray"></param> public static void Memorize( CharData ch, string argument, bool pray ) { string text; Dictionary<String, Int32> memmed = new Dictionary<String, Int32>(); int[] circle = new int[ Limits.MAX_CIRCLE ]; int[] circfree = new int[ Limits.MAX_CIRCLE ]; // with an argument they want to start memorizing a new spell. if( !String.IsNullOrEmpty(argument) ) { // Must be in the proper position if( ch.CurrentPosition != Position.resting ) { if( pray ) ch.SendText( "You can only pray for spells while resting.\r\n" ); else ch.SendText( "You can memorize spells only when resting.\r\n" ); return; } // Find the spell they want Spell spell = StringLookup.SpellLookup( argument ); if( spell == null ) { ch.SendText( "Never heard of that spell...\r\n" ); return; } // Check to see that they can memorize another spell // Immortals have no limits if( !ch.IsImmortal() ) { if( ( (PC)ch ).Hunger <= 0 || ( (PC)ch ).Thirst <= 0 ) { ch.SendText( "You can't seem to concentrate on anything but your appetite.\r\n" ); } if( !ch.HasSpell( argument ) ) { ch.SendText( "That spell is beyond you.\r\n" ); return; } if (!pray && ((PC)ch).SpellAptitude[spell.Name] < 1) { ch.SendText( "You have not yet learned that spell. Find a place to scribe it.\r\n" ); return; } int lvltotal = 0; foreach( MemorizeData mem in ((PC)ch).Memorized ) { if (mem.Circle == spell.SpellCircle[(int)ch.CharacterClass.ClassNumber]) lvltotal += 1; } int numMemmable = 0; if (ch.CharacterClass.MemType == CharClass.MemorizationType.Lesser) { numMemmable = LesserMemchart[(ch.Level - 1), (spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] - 1)]; } else { numMemmable = Memchart[(ch.Level - 1), (spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] - 1)]; } if (lvltotal >= numMemmable ) { if( pray ) ch.SendText( "You can pray for no more spells of that level.\r\n" ); else ch.SendText( "You can memorize no more spells of that circle.\r\n" ); return; } } // If we know what they want and they can have it, let's create it. MemorizeData memm = CreateMemorizeData( ch, spell ); if( !memm ) { Log.Error( "Unable to create memorization (spell {0})", spell ); return; } // If they're not already memorizing, they are now. ch.SetActionBit(PC.PLAYER_MEMORIZING ); if( pray ) text = String.Format( "You start praying for {0} which will take about {1} seconds.\r\n", spell.Name, ( memm.Memtime / Event.TICK_PER_SECOND ) ); else text = String.Format( "You start memorizing {0} which will take about {1} seconds.\r\n", spell.Name, ( memm.Memtime / Event.TICK_PER_SECOND ) ); ch.SendText( text ); return; } bool found = false; // If they didn't give us an argument, that means that they must // want to either see their spell list or continue memorizing // Either way we show their spell list. // make sure they have some mem data first... int count; if( ( (PC)ch ).Memorized.Count > 0 ) { // Figure out what spells they have memorized foreach( MemorizeData mem in ((PC)ch).Memorized ) { if( mem.Memmed ) { if (memmed.ContainsKey(mem.Name)) { memmed[mem.Name] = memmed[mem.Name] + 1; } else { memmed[mem.Name] = 1; } } } // Show memorized spells if( pray ) ch.SendText( "You have prayed the following spells:\r\n" ); else ch.SendText( "You have memorized the following spells:\r\n" ); int circleIndex; for( circleIndex = 12; circleIndex > 0; circleIndex-- ) { foreach (KeyValuePair<String, Spell> kvp in Spell.SpellList) { if (kvp.Value.SpellCircle[(int)ch.CharacterClass.ClassNumber] != circleIndex) continue; if( memmed.ContainsKey(kvp.Key) && memmed[ kvp.Key ] > 0 && kvp.Value.Name != null ) { text = String.Format( "({0,2}{1} circle) {2} - {3}\r\n", kvp.Value.SpellCircle[(int)ch.CharacterClass.ClassNumber], MUDString.NumberSuffix(kvp.Value.SpellCircle[(int)ch.CharacterClass.ClassNumber]), memmed[ kvp.Key ], kvp.Value.Name ); ch.SendText( text ); } } } //end for(circle) // Figure out what spells they are working on if( pray ) ch.SendText( "You are praying for the following spells:\r\n" ); else ch.SendText( "You are memorizing the following spells:\r\n" ); int totalMem = 0; // TODO: Make sure we cycle through this in the right order. // [ might need to do _memorized.Reverse() ] foreach( MemorizeData mem in ((PC)ch).Memorized ) { if( mem.Name == null ) break; if( mem.Memmed ) continue; found = true; text = String.Format( " {0} seconds: ({1}{2}) {3}\r\n", ( ( totalMem + mem.Memtime ) / Event.TICK_PER_SECOND ), Spell.SpellList[mem.Name].SpellCircle[(int)ch.CharacterClass.ClassNumber], MUDString.NumberSuffix(Spell.SpellList[mem.Name].SpellCircle[(int)ch.CharacterClass.ClassNumber]), mem.Name ); ch.SendText( text ); totalMem += mem.Memtime; } } // // Tell them what they still have slots open for... for( count = 0; count < Limits.MAX_CIRCLE; ++count ) circle[ count ] = 0; foreach( MemorizeData mem in ((PC)ch).Memorized ) { circle[ ( mem.Circle - 1 ) ] += 1; } bool left = false; for( count = 0; count < Limits.MAX_CIRCLE; ++count ) { int numMemmable = 0; if (ch.CharacterClass.MemType == CharClass.MemorizationType.Lesser) { numMemmable = LesserMemchart[(ch.Level - 1), count]; } else { numMemmable = Memchart[(ch.Level - 1), count]; } circfree[ count ] = numMemmable - circle[ count ]; if( circfree[ count ] > 0 ) left = true; } if( !left ) { if( pray ) ch.SendText( "\r\nYou can pray for no more spells.\r\n" ); else ch.SendText( "\r\nYou can memorize no more spells.\r\n" ); } else { if( pray ) text = String.Format( "\r\nYou can pray for" ); else text = String.Format( "\r\nYou can memorize" ); for( count = 0; count < Limits.MAX_CIRCLE; ++count ) { if( circfree[ count ] > 0 ) { string buf2 = String.Format( " {0}x{1}{2}", circfree[ count ], ( count + 1 ), MUDString.NumberSuffix( count + 1 ) ); text += buf2; } } text += " level spells.\r\n"; ch.SendText( text ); } // If they aren't memming and they should be, start 'em up. if( found && !ch.HasActionBit(PC.PLAYER_MEMORIZING ) && ch.CurrentPosition == Position.resting ) { ch.SetActionBit(PC.PLAYER_MEMORIZING ); if( ( (PC)ch ).Hunger > 0 && ( (PC)ch ).Thirst > 0 ) { if( pray ) ch.SendText( "You continue your prayers.\r\n" ); else ch.SendText( "You continue your studies.\r\n" ); } } return; }