public static void Group(CharData ch, string[] str) { if( ch == null ) return; // Group with no arguments should show group staus. if (str.Length == 0) { ch.ShowGroup(); return; } if (!MUDString.IsPrefixOf(str[0], "all")) { int added = 0; foreach (CharData ivictim in ch.InRoom.People) { if (ivictim == ch || ivictim.FlightLevel != ch.FlightLevel || ch.IsRacewar(ivictim)) continue; if (((ivictim.IsNPC() && ivictim.HasActionBit(MobTemplate.ACT_PET)) || (!ivictim.IsNPC() && ivictim.IsConsenting(ch))) && ivictim.Master == ch && !ivictim.GroupLeader) { ch.AddGroupMember(ivictim); ++added; } } if (added < 1) { ch.SendText("No new group members.\r\n"); } return; } CharData victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } if (ch == victim) { ch.RemoveFromGroup(victim); return; } if (ch.IsRacewar(victim) && !victim.IsNPC()) { ch.SendText("You can't group with such slime!\r\n"); return; } if (ch.IsSameGroup(victim)) { if (ch.GroupLeader == ch) { ch.RemoveFromGroup(victim); } else { ch.SendText("Only the leader of a group may kick someone out.\r\n"); } return; } if (ch.GroupLeader == null || ch.GroupLeader == ch) { string buf; if (victim.GroupLeader == null) { if ((!victim.IsNPC() && !victim.IsConsenting(ch)) || (victim.IsNPC() && victim.Master != ch)) { buf = String.Format("{0} doesn't want to be in your group.\r\n", victim.ShowNameTo(ch, true)); ch.SendText(buf); } else { ch.GroupLeader = ch; ch.AddGroupMember(victim); } } else { buf = String.Format("{0} is in another group.\r\n", victim.ShowNameTo(ch, true)); ch.SendText(buf); } } else { ch.SendText("You must be the head of the group to add someone.\r\n"); } return; }
// This function needs to be rewritten to take args! public static void Whirlwind(CharData ch, string[] str) { if( ch == null ) return; bool found = false; if (!ch.IsNPC() && !ch.HasSkill("whirlwind")) { ch.SendText("You don't know how to do that...\r\n"); return; } Object wield = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!wield || wield.ItemType != ObjTemplate.ObjectType.weapon) { ch.SendText("You need to wield a weapon first.\r\n"); return; } SocketConnection.Act("$n&n holds $p&n firmly, and starts spinning round...", ch, wield, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You hold $p&n firmly, and start spinning round...", ch, wield, null, SocketConnection.MessageTarget.character); foreach (CharData roomChar in ch.InRoom.People) { if ((roomChar.IsNPC() || (ch.IsRacewar(roomChar) && !roomChar.IsImmortal())) && CharData.CanSee(roomChar, ch)) { found = true; SocketConnection.Act("$n&n turns towards YOU!", ch, null, roomChar, SocketConnection.MessageTarget.victim); Combat.SingleAttack(ch, roomChar, "whirlwind", ObjTemplate.WearLocation.hand_one); // Added small amount of lag per target hit ch.WaitState(3); } } if (!found) { SocketConnection.Act("$n&n looks dizzy, and a tiny bit embarrassed.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You feel dizzy, and a tiny bit embarrassed.", ch, null, null, SocketConnection.MessageTarget.character); } ch.WaitState(Skill.SkillList["whirlwind"].Delay); ch.PracticeSkill("whirlwind"); if (!found && MUDMath.NumberPercent() < 25) { SocketConnection.Act("$n&n loses $s balance and colapses into a heap.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You lose your balance and fall into a heap.", ch, null, null, SocketConnection.MessageTarget.character); ch.CurrentPosition = Position.stunned; } return; }
/// <summary> /// Give a player consent to do things, such as group you, portal you, etc. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Consent(CharData ch, string[] str) { if( ch == null ) return; CharData worldChar; if (ch.IsNPC()) { ch.SendText("No consenting for mobs!"); return; } if (str.Length == 0) { ch.SendText("Consent who?\r\n"); return; } if (!MUDString.StringsNotEqual(str[0], "who")) { bool found = false; // Sadly inefficient code. foreach (CharData it in Database.CharList) { if (ch.IsConsenting(it)) { SocketConnection.Act("You continue consenting $N&n.", ch, null, it.Name, SocketConnection.MessageTarget.character); found = true; } } if (!found) { ch.SendText("You are not consenting anyone.\r\n"); } foreach (CharData it in Database.CharList) { worldChar = it; if (worldChar.IsNPC()) continue; if (worldChar.IsConsenting(ch)) { SocketConnection.Act("$N&n is consenting you.", ch, null, worldChar, SocketConnection.MessageTarget.character); } } return; } CharData victim = ch.GetCharWorld(str[0]); if (!victim || (ch.IsRacewar(victim))) { ch.SendText("That person doesn't exist.\r\n"); return; } if (victim == ch) { ch.SendText("You no longer give consent to anyone.\r\n"); foreach (CharData it in Database.CharList) { if (ch.IsConsenting(it)) { ch.StopConsenting(it); SocketConnection.Act("$N&n stops consenting you.", it, null, ch, SocketConnection.MessageTarget.character); SocketConnection.Act("You stop consenting $N&n.", ch, null, it, SocketConnection.MessageTarget.character); } } return; } // Consenting a victim again turns off consenting. if (ch.IsConsenting(victim)) { ch.StopConsenting(victim); SocketConnection.Act("$N&n stops consenting you.", victim, null, ch, SocketConnection.MessageTarget.character); SocketConnection.Act("You stop consenting $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); } else { ch.StartConsenting(victim); SocketConnection.Act("You now give consent to $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n has given you $s consent.", ch, null, victim, SocketConnection.MessageTarget.victim); } 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> /// Player track command. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void TrackCommand(CharData ch, string[] str) { if( ch == null ) return; CharData victim; if (ch.IsAffected(Affect.AFFECT_TRACK)) { ch.SendText("You stop tracking.\r\n"); Combat.StopHunting(ch); ch.RemoveAffect(Affect.AFFECT_TRACK); return; } if (!ch.HasSkill("track")) { ch.SendText("You couldn't track an &+Lelephant&n in your own bedroom.\r\n"); return; } if (str.Length == 0) { ch.SendText("Whom are you trying to track?\r\n"); return; } if (ch.Riding) { ch.SendText("You can't sniff a trail mounted.\r\n"); return; } if (ch.FlightLevel != 0) { ch.SendText("You find tracks on the _ground_!\r\n"); return; } if (ch.InRoom.IsWater()) { ch.SendText("You can't track through water.\r\n"); return; } if (ch.CurrentPosition != Position.standing) { if (ch.CurrentPosition == Position.fighting) ch.SendText("You're too busy fighting .\r\n"); else ch.SendText("You must be standing to track!\r\n"); return; } /* only imps can hunt to different areas */ bool area = (ch.GetTrust() < Limits.LEVEL_OVERLORD); if (area) { victim = ch.GetCharInArea(str[0]); } else { victim = ch.GetCharWorld(str[0]); } if (!victim || (!victim.IsNPC() && (ch.IsRacewar(victim)) && !ch.IsImmortal())) { ch.SendText("You can't find a trail of anyone like that.\r\n"); return; } if (ch.InRoom == victim.InRoom) { SocketConnection.Act("You're already in $N&n's room!", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* * Deduct some movement. */ if (ch.CurrentMoves > 2) { ch.CurrentMoves -= 3; } else { ch.SendText("You're too exhausted to hunt anyone!\r\n"); return; } SocketConnection.Act("$n carefully sniffs the air.", ch, null, null, SocketConnection.MessageTarget.room); ch.WaitState(Skill.SkillList["track"].Delay); Exit.Direction direction = Track.FindPath(ch.InRoom.IndexNumber, victim.InRoom.IndexNumber, ch, -40000, area); if (direction == Exit.Direction.invalid) { SocketConnection.Act("You can't sense $N&n's trail from here.", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* * Give a random direction if the player misses the die roll. */ if ((ch.IsNPC() && MUDMath.NumberPercent() > 75) /* NPC @ 25% */ || (!ch.IsNPC() && MUDMath.NumberPercent() > /* PC @ norm */ ((PC)ch).SkillAptitude["track"])) { do { direction = Database.RandomDoor(); } while (!(ch.InRoom.ExitData[(int)direction]) || !(ch.InRoom.ExitData[(int)direction].TargetRoom)); } ch.PracticeSkill("track"); /* * Display the results of the search. */ ch.SetAffectBit(Affect.AFFECT_TRACK); string buf = String.Format("You sense $N&n's trail {0} from here...", direction.ToString()); SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character); if (ch.CurrentPosition == Position.standing) { ch.Move(direction); } Combat.StartHunting(ch, victim); return; }
public static void Ignore(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) { ch.SendText("No ignoring for mobs!"); return; } if (str.Length == 0) { ch.SendText("Ignore who?\r\n"); return; } if (!MUDString.StringsNotEqual(str[0], "who")) { bool found = false; // Sadly inefficient code. foreach (CharData it in Database.CharList) { if (ch.IsIgnoring(it)) { SocketConnection.Act("You are ignoring $N&n.", ch, null, it.Name, SocketConnection.MessageTarget.character); found = true; } } if (!found) { ch.SendText("You are not ignoring anyone.\r\n"); } foreach (CharData it in Database.CharList) { if (it.IsNPC()) continue; if (it.IsIgnoring(ch)) { SocketConnection.Act("$N&n is ignoring you.", ch, null, it, SocketConnection.MessageTarget.character); } } return; } CharData victim = ch.GetCharWorld(str[0]); if (!victim || (ch.IsRacewar(victim))) { ch.SendText("That person doesn't exist.\r\n"); return; } if (victim == ch) { ch.SendText("You no longer ignore anyone.\r\n"); foreach (CharData it in Database.CharList) { if (ch.IsIgnoring(it)) { ch.StopIgnoring(it); SocketConnection.Act("$N&n stops ignoring you.", it, null, ch, SocketConnection.MessageTarget.character); SocketConnection.Act("You stop ignoring $N&n.", ch, null, it, SocketConnection.MessageTarget.character); } } return; } // Ignoring someone you're already ignoring makes you stop ignoring them (toggle) if (ch.IsIgnoring(victim)) { ch.StopIgnoring(victim); SocketConnection.Act("$N&n stops ignoring you.", victim, null, ch, SocketConnection.MessageTarget.character); SocketConnection.Act("You stop ignoring $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); } else { ch.StartIgnoring(victim); SocketConnection.Act("You now ignore $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n is now ignoring you.", ch, null, victim, SocketConnection.MessageTarget.victim); } return; }
/// <summary> /// Sends a beep tone to the target user's terminal. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Beep(CharData ch, string[] str) { if( ch == null ) return; string buf; if (ch.IsNPC()) { return; } if (str.Length < 1) { ch.SendText("Beep who?\r\n"); return; } CharData victim = ch.GetCharWorld(str[0]); if (!victim || (ch.IsRacewar(victim))) { ch.SendText("They are not here.\r\n"); return; } if (victim.IsNPC()) { ch.SendText("They are not beepable.\r\n"); return; } if (ch != victim) { buf = String.Format("You beep {0}.\r\n", victim.Name); ch.SendText(buf); buf = String.Format("\a\a{0} has beeped you.\r\n", ch.Name); victim.SendText(buf); } else { buf = String.Format("\aYou beep yourself. Pervert.\a\r\n"); ch.SendText(buf); } return; }
static void GroupExperienceGain( CharData ch, CharData victim ) { int highest = 1; /* * Monsters will now eat a share of the experience in a group if it gets the kill. * Dying of mortal wounds or poison doesn't give xp to anyone! */ if( victim == ch ) return; int members = 0; // Check for highest level group member and number of members in room foreach( CharData groupChar in ch.InRoom.People ) { if (groupChar.IsSameGroup(ch)) { members++; } if (groupChar.Level > highest) { highest = groupChar.Level; } } if( members == 0 ) { Log.Error( "GroupExperienceGain: {0} members.", members ); members = 1; } if (!victim.IsNPC() && !ch.IsNPC()) { // Player killed a player, check for frags. FraglistData.CheckForFrag(ch, victim); } else if (victim.IsNPC() && !ch.IsNPC()) { // Player killed a mob, check for faction changes. AdjustFaction(ch, victim); } foreach( CharData groupChar in ch.InRoom.People ) { int factor; if( !groupChar.IsSameGroup( ch ) || groupChar.IsNPC() ) continue; // Previously factor was set to be 110% - 10% per group member. This caused people in groups // to get insane high amounts of experience. This was originally added because players were // getting seemingly too little exp in groups larger than two. This method gives them 94% + // 6% per group member of original exp which is then split among the members. // This will cause groups with the following number of members to get a certain percentage as // compared to the solo person: // 1 = 100% 2 = 53% 3 = 37% 4 = 29% 5 = 24% 6 = 21% 7 = 19% 8 = 17% 9 = 16% // 10 = 15% 11 = 14% 12 = 13% 13 = 13% 14 = 13% 15 = 13% 16 = 12% 17 = 11% 18 = 11% // 19 = 10% 20 = 10% // Previously the total amount of experience was split among the group. This yielded percentages // of: // 1 = 100% 2 = 50% 3 = 33% 4 = 25% 5 = 20% 6 = 16% 7 = 14% 8 = 12% 9 = 11% // 10 = 10% 11 = 9% 12 = 8% 13 = 7% 14 = 7% 15 = 6% 16 = 6% 17 = 5% 18 = 5% // 19 = 5% 20 = 5% // // While this may not seem like a big difference, 3 to 4 person groups have basically gotten a // 10-15% increase, while 5-7 person groups have basically gotten a 20-35% increase. // // This should be quite a bit better, but depending on how the actual results are, this equation // may need to be changed so that it may be as high as 90% + 10% per group member of original // exp. However, instead of making a large change, if things don't seem right, try a change // of just 1% at first and gauge the results. // // Since experience is one of the most delicate and precise factors of the MUD, it needs to be // changed and tweaked in very small increments. Please contact Xangis ([email protected]) // if you plan on making any changes // // After making a few observations on the math of the experience, I've decided to finalize it at // 91 + members * 9 / members. // // The chart for this is as follows: // 1 = 100% 2 = 54% 3 = 39% 4 = 31% 5 = 27% 6 = 24% 7 = 22% 8 = 20% 9 = 19% // // However we use a different curve for those in groups of 10 or more. We don't like large // groups. // // We use the curve we were previously using, 94 + members * 6 / members. // // 10 = 15% 11 = 14% 12 = 13% 13 = 13% 14 = 13% 15 = 13% 16 = 12% 17 = 11% 18 = 11% // 19 = 10% 20 = 10% // // The overall bonus impDescriptor._actFlags of this is that compared to two days ago people will get this // percentage more experience: // // 1 = 0% 2 = 1.8% 3 = 5.4% 4 = 6.9% 5 = 12.5% 6 = 14.3% 7 = 15.8% 8 = 17.6% 9 = 18.8% // // Groups 10 or larger will not have any difference from 5-24. // // It seems that people didn't have the skills to handle our exp curve. Wusses. Well // i've made it quite a _bitvector easier on people in groups of 2-4 and a slight _bitvector easier on // groups of 5-9 by using // // The chart for this is as follows: // 1 = 100% 2 = 65% 3 = 53% 4 = 40% 5 = 36% 6 = 28% 7 = 26% 8 = 20% 9 = 19% // // The overall increases are: // 2 = 20.4% 3 = 35.9% 4 = 29.0% 5 = 33.3% 6 = 16.7% 7 = 18.2% if (members < 4) { factor = (70 + (members * 30)) / members; } else if (members < 6) { factor = (80 + (members * 20)) / members; } else if (members < 8) { factor = (80 + (members * 15)) / members; } else if (members < 10) { factor = (90 + (members * 10)) / members; } else { factor = (94 + (members * 6)) / members; } int xp = ComputeExperience( groupChar, victim ) * factor / 100; // Prevent total cheese leveling with unbalanced groups. Well, not // prevent, but reduce. A level 10 grouped with a 30 will end up // getting 80% of experience. A level 1 with a 50 will end up // getting 51%. Not enough of a reduction IMHO, but a little might // be all that we need. /* I increased this 150% as plvling is too easy. */ if( highest > ( ch.Level + 10 ) ) { xp = ( xp * ( 100 - ( 3 * ( highest - ch.Level ) ) / 2 ) ) / 100; } // Only check Trophy for NPC as victim, killer over level 5, // and victim less than 20 levels lower than killer. if (victim.IsNPC() && !groupChar.IsNPC() && (groupChar.Level > 4) && ((ch.Level - victim.Level) < 20)) { xp = (xp * CheckTrophy(groupChar, victim, members)) / 100; } if( xp == 0 ) continue; if( ( ch.IsRacewar( victim ) ) && ( !ch.IsNPC() && !groupChar.IsNPC() ) ) { ch.SendText( "You lost half of the experience by grouping with scum.\r\n" ); xp /= 2; } string buf; if (xp > 0) { buf = "You receive your portion of the experience.\r\n"; } else { buf = "You lose your portion of the experience.\r\n"; } groupChar.SendText( buf ); if (!groupChar.IsNPC()) { groupChar.GainExperience(xp); } foreach( Object obj in groupChar.Carrying ) { if( obj.WearLocation == ObjTemplate.WearLocation.none ) continue; if( ( obj.HasFlag( ObjTemplate.ITEM_ANTI_EVIL ) && groupChar.IsEvil() ) || ( obj.HasFlag( ObjTemplate.ITEM_ANTI_GOOD ) && groupChar.IsGood() ) || ( obj.HasFlag( ObjTemplate.ITEM_ANTI_NEUTRAL ) && groupChar.IsNeutral() ) ) { SocketConnection.Act( "&+LYou are wracked with &n&+rp&+Ra&n&+ri&+Rn&+L by&n $p&+L.&n", groupChar, obj, null, SocketConnection.MessageTarget.character ); SocketConnection.Act( "$n&+L convulses in &+Cp&n&+ca&+Ci&n&+cn&+L from&n $p&+L.&n", groupChar, obj, null, SocketConnection.MessageTarget.room ); obj.RemoveFromChar(); obj.AddToRoom( groupChar.InRoom ); } } } return; }
/// <summary> /// Code to check if someone just fragged. /// Will also have to add to race, class, and guild frag tables in /// addition to the master frag table. This does not update any /// lists yet and instead only updates the totals. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void CheckForFrag( CharData ch, CharData victim ) { // NPC's don't participate in fragging, can't frag yourself, // have to be within 10 levels, no same side frags, no frags // from races not participating in racewars, have to be level // 20 to frag, and have to be a valid class. // Check to see if kill qualifies for a frag. if( ch.IsNPC() ) return; if( victim.IsNPC() ) return; if( ch == victim ) return; if( ch.GetRacewarSide() == Race.RacewarSide.neutral ) return; if( !ch.IsRacewar( victim ) ) return; if( ch.IsImmortal() ) return; if( victim.IsImmortal() ) return; if( victim.Level < 20 ) return; if( ch.Level < 20 ) return; if( ( ch.Level - 10 ) > victim.Level ) return; if (ch.IsClass(CharClass.Names.none) || victim.IsClass(CharClass.Names.none)) return; if( victim.GetOrigRace() > Limits.MAX_PC_RACE ) return; // Give frag to ch. ( (PC)ch ).Frags++; // Protect against polymorphed character race frags. if( ch.GetOrigRace() < Limits.MAX_PC_RACE ) { _fraglist._totalFragsByRaceAndClass[ch.GetOrigRace()][ (int)ch.CharacterClass.ClassNumber]++; _fraglist._totalFragsBySide[ (int)ch.GetRacewarSide() ]++; } if( ( (PC)ch ).GuildMembership != null ) ( (PC)ch ).GuildMembership.Frags++; // Take frag from victim. ( (PC)victim ).Frags--; // Protect against polymorphed character race frags if( victim.GetOrigRace() < Limits.MAX_PC_RACE ) { _fraglist._totalFragsByRaceAndClass[victim.GetOrigRace()][ (int)victim.CharacterClass.ClassNumber]--; _fraglist._totalFragsBySide[ (int)victim.GetRacewarSide() ]--; } if (((PC)victim).GuildMembership != null) { ((PC)victim).GuildMembership.Frags--; } ch.SendText( "&+WYou gain a frag!&n\r\n" ); victim.SendText( "&+WYou lose a frag!&n\r\n" ); string text = ch.Name + " has fragged " + victim.Name + " in room " + ch.InRoom.IndexNumber + "."; ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, text ); Log.Trace( text ); // Check to see if either person goes up or down on their particular lists. if( ( (PC)ch ).Frags > 0 ) { SortFraglist( ch, _fraglist._topFrags ); SortFraglist( ch, _fraglist._topRaceFrags[ ch.GetOrigRace() ] ); SortFraglist(ch, _fraglist._topClassFrags[(int)ch.CharacterClass.ClassNumber]); } else if( ( (PC)ch ).Frags < 0 ) { SortFraglist( ch, _fraglist._bottomFrags ); SortFraglist( ch, _fraglist._bottomRaceFrags[ ch.GetOrigRace() ] ); SortFraglist(ch, _fraglist._bottomClassFrags[(int)ch.CharacterClass.ClassNumber]); } if( ( (PC)victim ).Frags > 0 ) { SortFraglist( victim, _fraglist._topFrags ); SortFraglist( victim, _fraglist._topRaceFrags[ victim.GetOrigRace() ] ); SortFraglist(victim, _fraglist._topClassFrags[(int)victim.CharacterClass.ClassNumber]); } else if( ( (PC)victim ).Frags < 0 ) { SortFraglist( victim, _fraglist._bottomFrags ); SortFraglist( victim, _fraglist._bottomRaceFrags[ victim.GetOrigRace() ] ); SortFraglist(victim, _fraglist._bottomClassFrags[(int)victim.CharacterClass.ClassNumber]); } _fraglist.Save(); return; }
/* * Compute xp for a kill. * Also adjust alignment of killer. * Edit this function to change xp computations. */ static int ComputeExperience( CharData killer, CharData victim ) { int percent = 100; int sign; int alignDir; // Uses a semi-exponential table called ExperienceTable.Table // no exp is awarded for anything 20 levels below you. // exp is reduced by 10% per level of the creature below you // for the first 9 levels, and then another 1% for the next 9 levels. // It actually counts down starting at 91%. /* If victim is lower level */ if( victim.Level < killer.Level ) { /* If victim is less than 10 levels below */ if( killer.Level - victim.Level < 10 ) { percent = 101 - ( ( killer.Level - victim.Level ) * 10 ); } /* If victim is less than 20 levels below */ else if( killer.Level - victim.Level < 20 ) { percent = 20 - ( killer.Level - victim.Level ); } else { percent = 0; } } /* If victim is over 10 levels over */ else if( victim.Level > ( killer.Level + 10 ) && killer.Level <= 20 ) { // Experience penalty for killing stuff way higher than you, 33 level difference and you // get about nothing. // Tweaked this slightly, 96 % at 10 levels above, 96% at 10 levels, etc percent = 129 - ( ( victim.Level - killer.Level ) * 4 ); if( percent < 2 ) percent = 2; } else percent += ( victim.Level - killer.Level ); if( killer.Alignment > 0 ) sign = 1; else sign = -1; if( victim.Alignment > 0 ) alignDir = -1; else alignDir = 1; int chance = Math.Abs( killer.Alignment - victim.Alignment ) - sign * killer.Alignment; chance /= 10; if( chance < 0 ) chance *= -1; if( killer.Level > victim.Level ) chance -= ( killer.Level - victim.Level ); chance = Macros.Range( 0, chance, 100 ); string lbuf = String.Format( "ComputeExperience: {0} has a {1} chance of gaining {2} align.", killer.Name, chance, alignDir ); ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, lbuf ); if( MUDMath.NumberPercent() < chance && killer.Alignment != -1000 ) { killer.Alignment += alignDir; if( killer.Alignment <= -1000 ) killer.SendText( "&+RThe d&+rarkside t&+lakes over...&n\r\n" ); } killer.Alignment = Macros.Range( -1000, killer.Alignment, 1000 ); // 25% bonus for sanctuary if (victim.IsAffected(Affect.AFFECT_SANCTUARY)) { percent = ( percent * 5 ) / 4; } // 10% bonus for fireshield if( victim.IsAffected( Affect.AFFECT_FIRESHIELD ) ) { percent = ( percent * 11 ) / 10; } // 12.5% bonus for an armed opponent Object obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_one ); if( obj ) { percent = ( percent * 9 ) / 8; } // 8.25% bonus for secondary weapon obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_two ); if( obj ) { percent = ( percent * 13 ) / 12; } // 10% bonus for racially hated mobs if( MUDString.NameContainedIn( Race.RaceList[ victim.GetRace() ].Name, Race.RaceList[ killer.GetOrigRace() ].Hate ) ) { percent = ( percent * 11 ) / 10; } // 10% penalty for killing same race if( victim.GetRace() == killer.GetOrigRace() ) { percent = ( percent * 9 ) / 10; } // Lowbie experience bonus was eliminated since the ExperienceTable.Table // made it no longer necessary if( victim.IsNPC() ) { // 5% bonus for aggros if( victim.HasActionBit(MobTemplate.ACT_AGGRESSIVE ) ) { percent = ( percent * 21 ) / 20; } // 50% penalty for killing shopkeepers if( victim.MobileTemplate.ShopData != null ) percent = percent / 2; // No bonus for special function #1 because they get that by having a class. // 10% bonus for each extra special function. int count = victim.SpecialFunction.Count; percent = ( percent * ( 10 + count ) ) / 10; } else { // Player-vs-player experience // // Killing a level 1-5 makes you lose a small amount of experience // and you get no experience for anyone under level 10. // // Those 11-20 are worth one fifth experience. if( victim.Level < 6 ) { killer.SendText( "You killed a newbie! You feel like a twink!\r\n" ); return (victim.Level - 6); } if( victim.Level < 11 ) { return 0; } if( victim.Level < 20 ) { percent /= 5; } else { percent *= 2; } if( !killer.IsRacewar( victim ) ) { if( !killer.HasActionBit( PC.PLAYER_BOTTING )) { killer.SendText("You gain no experience for killing your own side.\r\n"); return 0; } // Same-side bot kills are worth normal experience. killer.SendText("You gain experience for vanquishing an automaton.\r\n"); } else if( killer.HasActionBit( PC.PLAYER_BOTTING )) { // Racewar bot kills. 50% bonus exp. killer.SendText("You gain bonus experience for killing an automaton.\r\n"); percent = percent * 3/2; } } int xp = ( percent * ExperienceTable.Table[ victim.Level ].MobExperience ) / 100; xp = Math.Max( 0, xp ); return xp; }
/// <summary> /// Creating a portal. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <param name="indexNumber"></param> public static void MakePortal(CharData ch, Spell spell, int level, Target target, int indexNumber) { Room location; CharData victim = (CharData)target; Room original = ch.InRoom; if (ch.IsNPC()) return; if (!victim) { ch.SendText("Who exactly is your target?\r\n"); return; } if (victim.IsNPC() && !ch.IsImmortal()) return; if (!Magic.HasSpellConsent(ch, victim)) { return; } if (victim == ch || ch.InRoom == victim.InRoom) { ch.SendText("Seems like a waste of time.\r\n"); return; } if (!(location = victim.InRoom) || victim.InRoom.HasFlag(RoomTemplate.ROOM_SAFE) || victim.InRoom.HasFlag(RoomTemplate.ROOM_PRIVATE) || victim.InRoom.HasFlag(RoomTemplate.ROOM_SOLITARY)) { ch.SendText("You can't seem to get a fix their location.\r\n"); return; } if (!victim.IsNPC() && (ch.IsRacewar(victim)) && !ch.IsImmortal()) { ch.SendText("Don't you wish it was that easy!\r\n"); return; } Object portal = Database.CreateObject(Database.GetObjTemplate(indexNumber), 0); if (victim.InRoom.HasFlag(RoomTemplate.ROOM_NO_GATE) || ch.InRoom.HasFlag(RoomTemplate.ROOM_NO_GATE)) { SocketConnection.Act("$p opens for a brief instant and then collapses.&n", ch, portal, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p opens for a brief instant and then collapses.&n", ch, portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$p opens for a brief instant and then collapses.&n", victim, portal, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p opens for a brief instant and then collapses.&n", victim, portal, null, SocketConnection.MessageTarget.room); portal.RemoveFromWorld(); return; } portal.Timer = level / 15; portal.Values[2] = level / 7; portal.Values[0] = location.IndexNumber; portal.AddToRoom(original); portal = Database.CreateObject(Database.GetObjTemplate(indexNumber), 0); portal.Timer = level / 15; portal.Values[2] = level / 7; portal.Values[0] = original.IndexNumber; portal.AddToRoom(location); switch (indexNumber) { case StaticObjects.OBJECT_NUMBER_PORTAL: SocketConnection.Act("$p&+Y rises up from the ground.&n", ch, portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$p&+Y rises up before you.&n", ch, portal, null, SocketConnection.MessageTarget.character); if (location.People.Count > 0) { SocketConnection.Act("$p&+Y rises up from the ground.&n", location.People[0], portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$p&+Y rises up from the ground.&n", location.People[0], portal, null, SocketConnection.MessageTarget.character); } break; case StaticObjects.OBJECT_NUMBER_MOONWELL: SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", ch, portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", ch, portal, null, SocketConnection.MessageTarget.character); if (location.People.Count > 0) { SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", location.People[0], portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("&+WSilver mists swirl and form into a $p.&n", location.People[0], portal, null, SocketConnection.MessageTarget.character); } break; case StaticObjects.OBJECT_NUMBER_WORMHOLE: SocketConnection.Act("$p&+L appears from a warping of space and time.&n", ch, portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$p&+L appears from a warping of space and time.&n", ch, portal, null, SocketConnection.MessageTarget.character); if (location.People.Count > 0) { SocketConnection.Act("$p&+L appears from a warping of space and time.&n", location.People[0], portal, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$p&+L appears from a warping of space and time.&n", location.People[0], portal, null, SocketConnection.MessageTarget.character); } break; } ch.WaitState(8); return; }
/// <summary> /// Finds a character in an arbitrary room. /// </summary> /// <param name="room"></param> /// <param name="ch"></param> /// <param name="argument"></param> /// <returns></returns> public static CharData GetCharAtRoom( Room room, CharData ch, string argument ) { string arg = String.Empty; int number = MUDString.NumberArgument( argument, ref arg ); int count = 0; foreach( CharData roomChar in ch.InRoom.People ) { if( ch.FlightLevel != roomChar.FlightLevel ) continue; if( !roomChar.IsNPC() && ( ch.IsRacewar( roomChar ) ) && !ch.IsImmortal() ) { if( !MUDString.NameContainedIn( arg, Race.RaceList[ roomChar.GetRace() ].Name ) ) continue; } else { if( !MUDString.NameContainedIn( arg, roomChar.Name ) ) continue; } if (++count == number) { return roomChar; } } return null; }
/// <summary> /// Show a character to another character. This is the abbreviated version used in "look room" /// </summary> /// <param name="victim"></param> /// <param name="ch"></param> public static void ShowCharacterToCharacterAbbreviated(CharData victim, CharData ch) { string text = String.Empty; if (!victim || !ch) { Log.Error("ShowCharacterToCharacter0(): null ch or victim.", 0); return; } if (victim.Rider && victim.Rider.InRoom == ch.InRoom) { return; } // If invis, show char invis symbol first. if (victim.IsAffected(Affect.AFFECT_INVISIBLE)) { text += "&+L*&n "; } // Show the player's description. if (((!ch.IsNPC() && victim.CurrentPosition == Position.standing) || (victim.IsNPC() && victim.MobileTemplate != null && victim.CurrentPosition == victim.MobileTemplate.DefaultPosition)) && (!String.IsNullOrEmpty(victim.FullDescription)) && !victim.Riding) { // Added long description does not have \r\n removed. We may want to. text += victim.Description + "&n"; } else { // Show the player's name. text += victim.ShowNameTo(ch, true) + "&n"; // Show the player's title. // Show the player's race, only if PC, and on the same side of the racewar or a god. if (!victim.IsNPC() && ((PC)victim).Title.Length > 0) { if (MUDString.StringsNotEqual(((PC)victim).Title, " &n") && (ch.IsNPC())) { text += ((PC)victim).Title; } if (victim.IsGuild() && (ch.IsNPC())) { text += " " + ((PC)victim).GuildMembership.WhoName; } if (!ch.IsRacewar(victim) || victim.IsImmortal() || ch.IsImmortal()) { text += " (" + Race.RaceList[victim.GetRace()].ColorName + ")"; } } // Show the player's condition. text += " is "; if (victim.CurrentPosition == Position.standing && victim.CanFly()) { text += "flying"; } else { text += Position.PositionString(victim.CurrentPosition); } text += " here"; if (victim.Fighting != null) { text += "&n fighting "; if (victim.Fighting == ch) { text += "&nyou!"; } else if (victim.InRoom == victim.Fighting.InRoom) { text += victim.Fighting.ShowNameTo(ch, false); } else { text += "&nsomeone who left??"; } } if (victim.Riding && victim.Riding.InRoom == victim.InRoom) { text += "&n, mounted on " + victim.Riding.ShowNameTo(ch, false); } text += "&n."; } if (victim.IsAffected(Affect.AFFECT_CASTING)) { text += "&n&+y (casting)&n"; } if (victim.IsAffected(Affect.AFFECT_MINOR_PARA)) { text += "&n (&+Yparalyzed)&n"; } if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_WIZINVIS) && victim.GetTrust() <= ch.GetTrust()) { text += " &n&+g*&n"; } if (victim.IsAffected(Affect.AFFECT_HIDE) && (ch.IsAffected(Affect.AFFECT_DETECT_HIDDEN) || ch.HasInnate(Race.RACE_DETECT_HIDDEN))) { text += " &n(&+LHiding&n)"; } if (victim.IsAffected(Affect.AFFECT_CHARM) && ch.HasActionBit(PC.PLAYER_GODMODE)) { text += " &n(&n&+mCharmed&n)"; } if ((victim.IsAffected(Affect.AFFECT_PASS_DOOR) || victim.HasInnate(Race.RACE_PASSDOOR)) && ch.HasActionBit(PC.PLAYER_GODMODE)) { text += " &n(&+WTranslucent&n)"; } if ((victim.GetRace() == Race.RACE_UNDEAD || victim.GetRace() == Race.RACE_VAMPIRE) && (ch.IsAffected( Affect.AFFECT_DETECT_UNDEAD) || ch.HasActionBit(PC.PLAYER_GODMODE))) { text += " &n(&+WPale&n)"; } if (victim.IsAffected(Affect.AFFECT_FAERIE_FIRE)) { text += " &n(&n&+mFa&+Me&n&+mr&+Mie&+L Aura&n)"; } if (victim.IsEvil() && (ch.IsAffected(Affect.AFFECT_DETECT_EVIL) || ch.HasInnate(Race.RACE_DETECT_ALIGN) || ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))) { text += " &n(&+rBlood&+L Aura&n)"; } if (victim.IsGood() && (ch.IsAffected(Affect.AFFECT_DETECT_GOOD) || ch.HasInnate(Race.RACE_DETECT_ALIGN) || ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))) { text += " &n(&+CLight&+L Aura&n)"; } if (victim.IsAffected(Affect.AFFECT_SANCTUARY)) { text += " &n(&+WWhite&+L Aura&n)"; } if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_AFK)) { text += " &n&+b(&+RAFK&n&+b)&n"; } if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_BOTTING)) { text += " &n&+b(&+YBot&n&+b)&n"; } text += "\r\n"; ch.SendText(text); return; }
/// <summary> /// The main social action processing routine. Sends the social strings and any associated sounds. /// </summary> /// <param name="ch">Character acting out the social.</param> /// <param name="command">Command entered by the character.</param> /// <param name="argument">Additional modifiers to the command entered.</param> /// <returns></returns> public bool CheckSocial(CharData ch, string command, string argument) { string arg = String.Empty; Social soc = FindSocial(command); if (soc == null) { return false; } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_NO_EMOTE)) { ch.SendText("You are anti-social!\r\n"); return true; } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING)) { ch.RemoveActionBit(PC.PLAYER_MEDITATING); ch.SendText("You stop meditating.\r\n"); } // Performing a social action removes hide and conceal. if (ch.IsAffected(Affect.AFFECT_MINOR_INVIS)) { ch.SendText("You appear.\r\n"); } ch.AffectStrip(Affect.AffectType.skill, "shadow form"); ch.AffectStrip(Affect.AffectType.spell, "concealment"); ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS); ch.RemoveAffect(Affect.AFFECT_HIDE); switch (ch.CurrentPosition) { case Position.dead: ch.SendText("Lie still; you are DEAD.\r\n"); return true; case Position.incapacitated: case Position.mortally_wounded: ch.SendText("You are hurt far too badly for that.\r\n"); return true; case Position.stunned: ch.SendText("You are too stunned to do that.\r\n"); return true; case Position.sleeping: // Special exception - only social when you're using when asleep is "snore". if (!"snore".StartsWith(soc.Name, StringComparison.CurrentCultureIgnoreCase)) { break; } ch.SendText("In your dreams, or what?\r\n"); return true; } MUDString.OneArgument(argument, ref arg); CharData victim = null; if (arg.Length == 0) { SocketConnection.Act(soc.CharNoArgument, ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act(soc.OthersNoArgument, ch, null, victim, SocketConnection.MessageTarget.room); if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null) { foreach (CharData cd in ch.InRoom.People) { cd.SendSound(soc.AudioFile); } } return true; } victim = ch.GetCharWorld(arg); if (!victim || (ch.IsRacewar(victim) && ch.InRoom != victim.InRoom)) { ch.SendText("They aren't here.\r\n"); } else if (victim == ch) { SocketConnection.Act(soc.CharSelf, ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act(soc.OthersSelf, ch, null, victim, SocketConnection.MessageTarget.room); if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null) { foreach (CharData cd in ch.InRoom.People) { cd.SendSound(soc.AudioFile); } } } else if (!ch.GetCharRoom(arg) && CharData.CanSee(ch, victim) && soc.CharFound.Length > 0 && soc.VictimFound.Length > 0) { if (!ch.IsImmortal()) { ch.SendText("You don't see them here.\r\n"); return true; } if (!victim.IsNPC()) { const string ldbase = "From far away, "; if (victim.IsIgnoring(ch)) { ch.SendText("They are ignoring you.\r\n"); return false; } Room original = ch.InRoom; ch.RemoveFromRoom(); ch.AddToRoom(victim.InRoom); string ldmsg = ldbase; ldmsg += soc.CharFound; SocketConnection.Act(ldmsg, ch, null, victim, SocketConnection.MessageTarget.character); ldmsg = ldbase; ldmsg += soc.VictimFound; SocketConnection.Act(ldmsg, ch, null, victim, SocketConnection.MessageTarget.victim); if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null) { foreach (CharData cd in ch.InRoom.People) { cd.SendSound(soc.AudioFile); } } ch.RemoveFromRoom(); ch.AddToRoom(original); } else { ch.SendText("They aren't here.\r\n"); } } else { SocketConnection.Act(soc.CharFound, ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act(soc.VictimFound, ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act(soc.OthersFound, ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null) { foreach (CharData cd in ch.InRoom.People) { cd.SendSound(soc.AudioFile); } } // If mobs are to respond to socials, it should be inserted here. // This might be useful for some quests, mob functions, or other things. } return true; }