static bool SpellupOthers( CharData ch ) { if (ch == null) return false; if (ch.InRoom.HasFlag(RoomTemplate.ROOM_NO_MAGIC)) return false; if( !ch.IsAwake() || ch.Fighting ) return false; if( !ch.CanSpeak() ) return false; CharData victim = null; foreach( CharData ivictim in ch.InRoom.People ) { if (ivictim != ch && CharData.CanSee(ch, ivictim) && MUDMath.NumberBits(1) == 0 && ivictim.IsNPC()) { victim = ivictim; break; } } if( !victim ) return false; if( victim.Hitpoints < ( victim.GetMaxHit() - 10 ) ) { if( CheckDefensive( ch, victim, "full heal", 75 ) ) return true; if( CheckDefensive( ch, victim, "aid", 60 ) ) return true; if( CheckDefensive( ch, victim, "heal", 75 ) ) return true; if( CheckDefensive( ch, victim, "mending", 75 ) ) return true; } if (!victim.IsAffected(Affect.AFFECT_HASTE)) if( CheckDefensive( ch, victim, "haste", 45 ) ) return true; return false; }
/// <summary> /// Private communication between two characters. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Whisper(CharData ch, string[] str) { if( ch == null ) return; if (str.Length == 0) { ch.SendText("Whisper what to who?\r\n"); return; } CharData victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("They're not here.\r\n"); return; } if (str.Length < 2) { ch.SendText("Whisper what?\r\n"); return; } if (!ch.CanSpeak()) { return; } string text = String.Join(" ", str, 1, (str.Length - 1)); text = DrunkSpeech.MakeDrunk(text, ch); SocketConnection.Act("$n&n whispers quietly to $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); string buf = "&n&+c$n&n&+c whispers '&+c" + text + "&n&+c'&n"; SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.victim); buf = "&n&+cYou whisper &+c'" + text + "&n&+c' to $N&n"; SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character); // Chatterbot code. if (victim.ChatBot != null) { victim.ChatBot.CheckConversation(victim, ch, text); } return; }
/// <summary> /// Say something to the members of your group. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void GroupChat(CharData ch, string[] str) { if( ch == null ) return; // No arguments, no leader, no chance. if (!ch.GroupLeader) { ch.SendText("Tell who, yourself? You are not in a group!\r\n"); return; } if (str.Length < 1) { ch.SendText("Tell your group what?\r\n"); return; } if (!ch.CanSpeak()) { ch.SendText("Your lips move but no sound comes out.\r\n"); return; } String text = String.Join(" ", str, 1, (str.Length - 1)); text = DrunkSpeech.MakeDrunk(text, ch); foreach (CharData groupChar in Database.CharList) { string buf; if (groupChar == ch) { buf = String.Format("&+GYou tell the group '&n&+G{0}&+G'.&n\r\n", text); ch.SendText(buf); continue; } if (groupChar.IsSameGroup(ch) && !groupChar.InRoom.HasFlag(RoomTemplate.ROOM_SILENT) && !groupChar.HasInnate(Race.RACE_MUTE) && !groupChar.IsAffected(Affect.AFFECT_MUTE) && groupChar.IsAwake()) { buf = String.Format("&+G{0}&n&+G tells the group '&n&+G{1}&+G'.&n\r\n", ch.ShowNameTo(groupChar, true), SocketConnection.TranslateText(text, ch, groupChar)); groupChar.SendText(buf); } } return; }
/// <summary> /// Say something out loud. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Say(CharData ch, string[] str) { if( ch == null ) return; if (str.Length == 0) { ch.SendText("Say what?\r\n"); return; } if (!ch.CanSpeak()) { ch.SendText("Your lips move but no sound comes out.\r\n"); return; } string text = String.Join(" ", str); text = DrunkSpeech.MakeDrunk(text, ch); if (ch.InRoom != null) { foreach (CharData roomChar in ch.InRoom.People) { if (roomChar == ch || roomChar.IsNPC()) continue; string output; if (ch.IsNPC() || (!ch.IsNPC() && (((PC)ch).Speaking == Race.Language.god || ((PC)ch).Speaking == Race.Language.unknown))) { output = String.Format("{0} says '&n$T&n'", ch.ShowNameTo(roomChar, true)); } else { output = String.Format("{0} says in {1} '&n$T&n'", ch.ShowNameTo(roomChar, true), ch.IsNPC() ? Race.LanguageTable[(int)Race.RaceList[ch.GetOrigRace()].PrimaryLanguage] : Race.LanguageTable[(int)((PC)ch).Speaking]); } // Add foreign language filter. SocketConnection.Act(output, roomChar, null, SocketConnection.TranslateText(text, ch, roomChar), SocketConnection.MessageTarget.character); // Chatterbot code. May want to restrict chatterbots to tells, asks, and whispers. if (roomChar.ChatBot != null) { roomChar.ChatBot.CheckConversation(roomChar, ch, text); } } } // MOBtrigger = false; SocketConnection.Act("You say '&n$T&n'", ch, null, text, SocketConnection.MessageTarget.character); // prog_speech_trigger( argument, ch ); ch.DoorTrigger(text); return; }
/// <summary> /// Direct telepathy-like communication with another individual. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Tell(CharData ch, string[] str) { if( ch == null ) return; if (!ch.CanSpeak()) { ch.SendText("Your lips move but no sound comes out.\r\n"); return; } if (str.Length < 2) { ch.SendText("Tell what to who?\r\n"); return; } /* * PCs can receive a tell anywhere, but NPCs only can only hear them in the same room. * * get PC target first, if fails then get NPC */ CharData victim = ch.GetCharWorld(str[0]); if (!victim || (victim.IsNPC() && victim.InRoom != ch.InRoom)) { ch.SendText("They aren't here.\r\n"); return; } if (victim == ch) { ch.SendText("You listen to your own thoughts. *cricket* *cricket*\r\n"); return; } if ((ch.IsRacewar(victim)) && (!ch.IsImmortal() && !victim.IsImmortal()) && (ch.InRoom != victim.InRoom)) { ch.SendText("They aren't here.\r\n"); return; } /* Can tell to other side of racewar iff the opponent is in the same room or one of the people are Immortals. */ if ((!ch.IsImmortal() && !victim.IsImmortal()) && (ch.IsRacewar(victim)) && (victim.InRoom != ch.InRoom)) { ch.SendText("They aren't here.\r\n"); return; } if ((!ch.IsNPC() && (ch.HasActionBit(PC.PLAYER_SILENCE) || !ch.HasActionBit(PC.PLAYER_TELL) || (!victim.IsNPC() && !victim.HasActionBit(PC.PLAYER_TELL)))) || victim.InRoom.HasFlag(RoomTemplate.ROOM_SILENT)) { ch.SendText("They can't hear you.\r\n"); return; } if (!victim.Socket && !victim.IsNPC()) { SocketConnection.Act("$N&n is &+Llinkdead&n.", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (!ch.IsImmortal() && !victim.IsAwake()) { SocketConnection.Act("$E isn't paying attention.", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (victim.IsIgnoring(ch)) { SocketConnection.Act("$E is ignoring you.", ch, null, victim, SocketConnection.MessageTarget.character); return; } string text = String.Join(" ", str, 1, (str.Length - 1)); text = DrunkSpeech.MakeDrunk(text, ch); int position = victim.CurrentPosition; victim.CurrentPosition = Position.standing; Race.Language lang = ch.IsNPC() ? Race.RaceList[ch.GetOrigRace()].PrimaryLanguage : ((PC)ch).Speaking; if (lang == Race.Language.god || lang == Race.Language.unknown) { text = String.Format("&+WYou tell $N&+W '$t&+W'&n"); } else { text = String.Format("&+WYou tell $N&+W in {0} '$t&+W'&n", Race.LanguageTable[(int)lang]); } SocketConnection.Act(text, ch, text, victim, SocketConnection.MessageTarget.character); if (lang == Race.Language.god || lang == Race.Language.unknown) { text = String.Format("&+W$n&+W tells you '$t&+W'&n"); } else { text = String.Format("&+W$n&+W tells you in {0} '$t&+W'&n", Race.LanguageTable[(int)lang]); } SocketConnection.Act(text, ch, SocketConnection.TranslateText(text, ch, victim), victim, SocketConnection.MessageTarget.victim); victim.CurrentPosition = position; victim.ReplyTo = ch; if (victim.HasActionBit(PC.PLAYER_AFK)) { SocketConnection.Act("Just so you know, $E is &+RAFK&n.", ch, null, victim, SocketConnection.MessageTarget.character); } else if (victim.HasActionBit(PC.PLAYER_BOTTING)) { SocketConnection.Act("Just so you know, $E is a &+YBOT&n", ch, null, victim, SocketConnection.MessageTarget.character); } // players can't have talk files -- go home! Quest stuff. if (!victim.IsNPC()) { return; } bool questfound = false; foreach (QuestTemplate it in QuestTemplate.QuestList) { bool isquest = (ch.IsImmortal() && !MUDString.StringsNotEqual(text, "quest")) ? true : false; if (it.Messages == null || (it.IndexNumber != victim.MobileTemplate.IndexNumber)) continue; foreach (TalkData message in it.Messages) { if (MUDString.NameContainedIn(text, message.Keywords) || isquest) { ch.SendText("\r\n"); ch.SendText(message.Message); questfound = true; } } } // Chatterbot code. Bots won't check if a quest matched (prevents multiple statements). if (!questfound && victim.ChatBot != null) { victim.ChatBot.CheckConversation(victim, ch, text); } return; }
/// <summary> /// Reports current condition verbally. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Report(CharData ch, string[] str) { string arg = String.Empty; if (ch == null) { Log.Error("Commandreport: null ch.", 0); return; } if (!ch.CanSpeak()) { ch.SendText("Your lips move but no sound comes out.\r\n"); return; } string buf = String.Empty; if (str.Length == 0) { buf += "&nYou report: " + ch.Hitpoints + "/" + ch.GetMaxHit() + " hp " + ch.CurrentMana + "/" + ch.MaxMana + " mana " + ch.CurrentMoves + "/" + ch.MaxMoves + " mv.\r\n"; ch.SendText(buf); buf += "$n&n reports: " + ch.Hitpoints + "/" + ch.GetMaxHit() + " hp " + ch.CurrentMana + "/" + ch.MaxMana + " mana " + ch.CurrentMoves + "/" + ch.MaxMoves + " mv.\r\n"; SocketConnection.Act(buf, ch, null, null, SocketConnection.MessageTarget.room); return; } //report is essentially a tell, why not use that code? buf += arg + " reporting: " + ch.Hitpoints + "/" + ch.GetMaxHit() + " hp " + ch.CurrentMana + "/" + ch.MaxMana + " mana " + ch.CurrentMoves + "/" + ch.MaxMoves + " mv.\r\n"; CommandType.Interpret(ch, "tell " + buf); return; }
/// <summary> /// Reply to the last 'tell' that you received. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Reply(CharData ch, string[] str) { if( ch == null ) return; if (!ch.CanSpeak()) { ch.SendText("Your lips move but no sound comes out.\r\n"); return; } CharData victim = ch.ReplyTo; if (!victim) { ch.SendText("They aren't here.\r\n"); return; } if ((!ch.IsNPC() && (ch.HasActionBit(PC.PLAYER_SILENCE) || !ch.HasActionBit(PC.PLAYER_TELL) || (!victim.IsNPC() && !victim.HasActionBit(PC.PLAYER_TELL)))) || victim.InRoom.HasFlag(RoomTemplate.ROOM_SILENT)) { ch.SendText("Your message didn't get through.\r\n"); return; } if (str.Length == 0) { ch.SendText("Reply what?\r\n"); return; } if (!victim.Socket) { SocketConnection.Act("$N is &+Llinkdead&n.", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (!ch.IsImmortal() && !victim.IsAwake()) { SocketConnection.Act("$E can't hear you.", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (victim.IsIgnoring(ch)) { SocketConnection.Act("$E is ignoring you.", ch, null, victim, SocketConnection.MessageTarget.character); return; } string text = String.Join(" ", str); text = DrunkSpeech.MakeDrunk(text, ch); SocketConnection.Act("&+WYou tell $N&+W '$t&+W'&n", ch, text, victim, SocketConnection.MessageTarget.character); int position = victim.CurrentPosition; victim.CurrentPosition = Position.standing; SocketConnection.Act("&+W$n&+W tells you '$t&+W'&n", ch, SocketConnection.TranslateText(text, ch, victim), victim, SocketConnection.MessageTarget.victim); victim.CurrentPosition = position; victim.ReplyTo = ch; if (victim.HasActionBit(PC.PLAYER_AFK)) { SocketConnection.Act("Just so you know, $E is &+RAFK&n.", ch, null, victim, SocketConnection.MessageTarget.character); } else if (victim.HasActionBit(PC.PLAYER_BOTTING)) { SocketConnection.Act("Just so you know, $E is a &+YBOT&n", ch, null, victim, SocketConnection.MessageTarget.character); } return; }
/// <summary> /// Use a scroll to invoke its magical spells. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Recite(CharData ch, string[] str) { if( ch == null ) return; Object scroll; Object obj = null; CharData victim; string arg1 = String.Empty; string arg2 = String.Empty; if (!(scroll = ch.GetObjCarrying(arg1))) { ch.SendText("You do not have that &+Wscroll&n.\r\n"); return; } if (scroll.ItemType != ObjTemplate.ObjectType.scroll) { ch.SendText("You can recite only &+Wscrolls&n.\r\n"); return; } if (String.IsNullOrEmpty(arg2)) { victim = ch; if (ch.Fighting != null) { victim = ch.Fighting; } } else { if (((victim = ch.GetCharRoom(arg2)) == null) && !(obj = ch.GetObjHere(arg2))) { ch.SendText("You can't find it.\r\n"); return; } } if (!ch.CanSpeak()) { ch.SendText("Your lips move but no sound comes out.\r\n"); return; } if (ch.IsNPC() && !ch.IsFreewilled()) { SocketConnection.Act("You try to recite $p&n, but you have no free will.", ch, scroll, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n tries to recite $p&n, but has no free will.", ch, scroll, null, SocketConnection.MessageTarget.room); return; } ch.WaitState(2 * Event.TICK_COMBAT); SocketConnection.Act("You recite $p&n.", ch, scroll, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n recites $p&n.", ch, scroll, null, SocketConnection.MessageTarget.room); if (ch.CheckSkill("scrolls")) { switch (MUDMath.NumberBits(3)) { case 0: case 1: case 2: case 3: SocketConnection.Act("You can't understand $p&n at all.", ch, scroll, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n can't understand $p&n at all.", ch, scroll, null, SocketConnection.MessageTarget.room); return; case 4: case 5: case 6: ch.SendText("You must have said something incorrectly.\r\n"); SocketConnection.Act("$n&n must have said something incorrectly.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$p&n blazes brightly, then is gone.", ch, scroll, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n blazes brightly and disappears.", ch, scroll, null, SocketConnection.MessageTarget.room); scroll.RemoveFromWorld(); ; return; case 7: SocketConnection.Act( "You completely botch the recitation, and $p&n bursts into &+Rflames&n!!", ch, scroll, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n &+rglows&n and then bursts into &+Rflame&n!", ch, scroll, null, SocketConnection.MessageTarget.room); /* * Command.damage( ) call after Object.extract_obj in case the damage would * have extracted ch. This is okay because we merely mark * obj.deleted; it still retains all values until list_update. * Sloppy? Okay, create another integer variable. */ scroll.RemoveFromWorld(); Combat.InflictDamage(ch, ch, scroll.Level, "scrolls", ObjTemplate.WearLocation.none, AttackType.DamageType.fire); return; } } if (scroll.Level > ch.Level) { SocketConnection.Act("$p&n is too high level for you.", ch, scroll, null, SocketConnection.MessageTarget.character); } else { /* scroll.Values[0] is not used for scrolls */ for (int i = 1; i <= 4; i++) { String spellName = SpellNumberToTextMap.GetSpellNameFromNumber(scroll.Values[i]); if (String.IsNullOrEmpty(spellName)) { Log.Error("Recite: Spell number " + obj.Values[i] + " not found for object " + scroll.ObjIndexNumber + ". Make sure it's in the SpellNumberToTextMap."); } Spell spell = StringLookup.SpellLookup(spellName); if (!spell) { Log.Error("Recite: Spell '" + spellName + "' not found for object " + scroll.ObjIndexNumber + ". Make sure it's in the spells file."); } else { spell.Invoke(ch, scroll.Level, ch); } } } if (!ch.IsNPC() || (ch.IsNPC() && ch.IsAffected(Affect.AFFECT_CHARM))) { scroll.RemoveFromWorld(); } return; }
/// <summary> /// Channel function - sends text to a specific output channel. /// </summary> /// <param name="ch"></param> /// <param name="argument"></param> /// <param name="channel"></param> /// <param name="verb"></param> public static void SendToChannel( CharData ch, string argument, TalkChannel channel, string verb ) { if (ch == null || String.IsNullOrEmpty(argument)) { return; } string text; int position; if( String.IsNullOrEmpty(argument) ) { text = String.Format( "{0} what?\r\n", verb ); ch.SendText( text ); return; } if( !ch.IsNPC() && ch.HasActionBit(PC.PLAYER_SILENCE ) ) { text = String.Format( "You can't {0}.\r\n", verb ); ch.SendText( text ); return; } if( !ch.CanSpeak() ) { ch.SendText( "Your lips move but no sound comes out.\r\n" ); return; } ch.SetListening(channel, true); // Make the words look drunk if needed... argument = DrunkSpeech.MakeDrunk( argument, ch ); switch( channel ) { default: text = String.Format( "You {0} '{1}'\r\n", verb, argument ); ch.SendText( text ); text = String.Format( "$n&n {0}s '$t'", verb ); break; case TalkChannel.shout: text = String.Format( "You {0} '{1}'\r\n", verb, argument ); ch.SendText( text ); text = String.Format( "$n&n {0}s '$t'", verb ); break; case TalkChannel.yell: text = String.Format( "You {0} '{1}'\r\n", verb, argument ); ch.SendText( text ); text = String.Format( "$n&n {0}s '$t'", verb ); break; case TalkChannel.guild: text = String.Format( "&+L[&+C$n&+L]&n&+c $t&n" ); Act( text, ch, argument, null, MessageTarget.character ); break; case TalkChannel.immortal: text = String.Format( "&+L[&+r$n&+L]&n $t" ); position = ch.CurrentPosition; ch.CurrentPosition = Position.standing; Act( text, ch, argument, null, MessageTarget.character ); ch.CurrentPosition = position; break; } foreach( SocketConnection socket in Database.SocketList ) { CharData originalChar = socket.Original ? socket.Original : socket.Character; CharData targetChar = socket.Character; if( socket.ConnectionStatus == ConnectionState.playing && targetChar != ch && !originalChar.IsListening( channel ) && !originalChar.InRoom.HasFlag( RoomTemplate.ROOM_SILENT ) ) { if( channel == TalkChannel.immortal && !originalChar.IsImmortal() ) continue; if( channel == TalkChannel.guild && ( !originalChar.IsGuild() || !ch.IsSameGuild( originalChar ) ) ) continue; if( channel == TalkChannel.shout && targetChar.InRoom.Area != ch.InRoom.Area && !targetChar.IsImmortal() ) continue; position = targetChar.CurrentPosition; if( channel != TalkChannel.shout && channel != TalkChannel.yell ) targetChar.CurrentPosition = Position.standing; if( channel == TalkChannel.shout || channel == TalkChannel.yell ) { // TODO: BUG: FIXME: Get rid of this hard-coded mob index number crap! if( ( ch.IsNPC() && ( ch.MobileTemplate.IndexNumber == 9316 || ch.MobileTemplate.IndexNumber == 9748 ) ) || (!targetChar.IsNPC() && targetChar.HasActionBit(PC.PLAYER_SHOUT))) { // Add foreign language filter if( !ch.IsNPC() ) { Act( text, ch, TranslateText( argument, ch, originalChar ), targetChar, MessageTarget.victim ); } else { Act( text, ch, argument, targetChar, MessageTarget.victim ); } } } else { Act( text, ch, argument, targetChar, MessageTarget.victim ); } targetChar.CurrentPosition = position; } } return; }
/// <summary> /// Handles all spellcasting, whether it be willing, singing, or casting /// If they got here as a bard, they're using the SING command word, /// if they got here as a psionicist, they're using the WILL command word, /// and if they got here as anything else, they're using CAST. /// /// These are just cheesy details handled by CommandType.cs... we don't care. /// What we do care about is that we *know* it's safe to base all our /// messages/decisions on the character's class. /// /// This function is also *mob-safe*, meaning that mobs can cast spells /// too. However, this is not the preferred method (as far as I can tell) /// /// Shaman totems are checked for in this function. /// </summary> /// <param name="ch"></param> /// <param name="argument"></param> public static void Cast( CharData ch, string argument ) { // No casting while berzerked... Nor singing! Hah! if (ch.IsAffected(Affect.AFFECT_BERZERK)) { ch.SendText( "Not while you're in a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!\r\n" ); return; } // No casting while thirsty... Nor singing! Hah! if (ch.IsAffected(Affect.AFFECT_THIRST) && ( ch.IsNPC() || ( (PC)ch ).Thirst < 10 ) ) { ch.SendText( "&+BNo&+Ct w&+chi&+ble &+cyo&+Bu'&+cre &+Bso p&+carc&+Bhed&n!\r\n" ); return; } String[] pieces = argument.Split( new Char[] {'\''}, StringSplitOptions.RemoveEmptyEntries); if (pieces.Length < 1) { ch.SendText("Spell names must always be in single quotes, such as: cast 'magic missile' troll.\r\n"); return; } if (pieces.Length > 1) { pieces[1] = pieces[1].Trim(); } Spell spell; if (((spell = StringLookup.SpellLookup(pieces[0])) == null) || ((!ch.HasSpell(pieces[0])) && !ch.IsImmortal())) { ch.SendText( "You can't do that.\r\n" ); return; } if( !CheckTotem( ch, spell )) return; if( !ch.CheckConcentration( spell ) ) return; if (!ch.CheckMemorized(spell)) return; if( ( !ch.CanSpeak() || ch.HasInnate(Race.RACE_MUTE)) && !ch.IsClass(CharClass.Names.psionicist)) { ch.SendText( "Your lips move but no sound comes out.\r\n" ); return; } if( !ch.InRoom.CheckCastable( ch, ch.IsClass( CharClass.Names.bard ), true) ) return; if( ch.InRoom.CheckStarshell( ch ) ) return; int manaUsed = 0; // TODO: Rather than hard-code psionicist as a mana class, let that be set in the class files. if (ch.IsClass(CharClass.Names.psionicist)) { manaUsed = Macros.ManaCost(ch, spell); } else if (ch.IsClass(CharClass.Names.bard)) { manaUsed = spell.MinimumMana; } // Locate targets. if( ch.IsNPC() ) { ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, "Magic.Cast: Attempting to find _targetType for " + ch.ShortDescription + "&n." ); } if (pieces.Length > 1) { ProcessSpellTargets(ch, spell, pieces[1]); } else { ProcessSpellTargets(ch, spell, null); } }